简体   繁体   English

Django 用户 model 两次保存到数据库

[英]Django User model saves twice into database

I am trying to create multi user registration system with Django.我正在尝试使用 Django 创建多用户注册系统。 However, anytime I call the save() method to save a User type, it saves into the User table twice.但是,每当我调用save()方法来保存 User 类型时,它都会两次保存到 User 表中。 The funny thing about the second model that is saved is that many required fields are empty.保存的第二个 model 的有趣之处在于许多必填字段为空。

I am using a custom user model that I created from AbstractBaseUser .我正在使用从AbstractBaseUser创建的自定义用户 model 。 I also rewrote the forms for the CustomUser model.我还为 CustomUser model 重写了 forms。 For the multiple user types, I am using a profile model (Student model has a OneToOne field to the user model)对于多种用户类型,我使用的是配置文件 model(学生 model 对用户模型有一个 OneToOne 字段)

models.py :模型.py

class User(AbstractBaseUser, PermissionsMixin):
    # I've removed some unimportant code here
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    
    class Types(models.TextChoices):
        STUDENT = 'STUDENT', 'Student'
        DEPARTMENT_USER = 'DEPARTMENT_USER', 'Department user'
        ADMIN = 'ADMIN', 'Admin'
    user_type = models.CharField(_('Type'), max_length=50, choices=Types.choices, default=Types.STUDENT)   
    
    first_name = models.CharField(_('First name'), max_length=70, blank=False, default="")     
    middle_name = models.CharField(_('Middle name'), max_length=70, blank=True, default="")         
    last_name = models.CharField(_('Last name'), max_length=70, blank=False, default="")   
           
    is_active = models.BooleanField(default=True)        
    is_staff = models.BooleanField(default=False) # a admin user; non super-user
    is_superuser = models.BooleanField(default=False) # a superuser
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    
    
    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = ['user_type', 'first_name', 'last_name'] # Email & Password are required by default.
    
    objects = UserManager()
    
    class Meta:
        verbose_name = ('user')
        verbose_name_plural = ('users')
        #db_table = 'auth_user'
        abstract = False


class AccountConfirmed(models.Model):
    # Model to determine which users have confirmed their email addresses. 
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='accountconfirmed')
    email_confirmed = models.BooleanField(default=False)
    reset_password = models.BooleanField(default=False)

    class Meta:
        app_label = 'auth'

# When the user model is created, through signals an AccountConfirmed model is also created.
# The email_confirmed and reset_password field is set to false. 
@receiver(models.signals.post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        AccountConfirmed.objects.create(user=instance)
    instance.accountconfirmed.save()
    
######################################################
######################################################


class Student(User):
    # This is the model class for students
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='students')
    matric_number = models.CharField(_('Matriculation number'), max_length=11, blank=False)
    department = models.CharField(_('Department'), max_length=40, blank=False)
    # has_graduated, level, etc. future possibilities    
    
    def __str__(self):
        return f'{self.user.email}'

forms.py : forms.py

class StudentSignupForm(UserCreationForm):
    # first_name = forms.CharField(max_length=70)     
    # middle_name = forms.CharField(max_length=70, required=False)         
    # last_name = forms.CharField(max_length=70)           
    matric_number = forms.CharField(min_length=10, max_length=11, help_text='Your Matric number must be 10 characters')
    department = forms.CharField(max_length=40, help_text='e.g Computer Science')  
    
    class Meta(UserCreationForm.Meta):
        model = User  
        fields = UserCreationForm.Meta.fields + ('matric_number', 'department')
    
    @transaction.atomic
    def save(self, commit=True):
        # Save the User instance and get a reference to it
        user = super().save(commit=False)      
        user.user_type = User.Types.STUDENT
        user.is_active = False
        #if commit:
        user.save()
        print(f' forms.py {user.email} {user.first_name}')
        student = Student.objects.create(user=user, matric_number=self.cleaned_data.get('matric_number'), department=self.cleaned_data.get('department'))
        # Add other details
        # Return User instance, not Student instance
        return user

views.py :视图.py

class StudentUserSignupView(CreateView):
    model = User
    template_name = 'account/signup.html'
    form_class = StudentSignupForm
    
    def get_context_data(self, **kwargs):
        kwargs['user_type'] = 'STUDENT'
        return super().get_context_data(**kwargs)
    
    def form_valid(self, form):
        user = form.save()
        #login(self.request, user)
        send_verification_mail(self, user)
        return redirect('verification_sent')

Anytime a user signs up, this is what the students table looks like:每当用户注册时,学生表如下所示: 学生报名后表

Also, this is what the users table look like after signup (with the multiple saves)此外,这是用户表在注册后的样子(多次保存) 在此处输入图像描述

So how do I correct the multiple saves in the user table?那么如何更正用户表中的多次保存呢? Also, How is it even possible to save a model with most of the required fields empty?此外,如何在大部分必填字段为空的情况下保存 model?

As pointed out by @RaghavKundra, the line below was what caused the problem of saving multiple times to the database正如@RaghavKundra 所指出的,下面的行是导致多次保存到数据库的问题的原因

class Student(User):

Instead of that, it should be class Student(models.Model):相反,它应该是class Student(models.Model):

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM