繁体   English   中英

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

[英]Django User model saves twice into database

我正在尝试使用 Django 创建多用户注册系统。 但是,每当我调用save()方法来保存 User 类型时,它都会两次保存到 User 表中。 保存的第二个 model 的有趣之处在于许多必填字段为空。

我正在使用从AbstractBaseUser创建的自定义用户 model 。 我还为 CustomUser model 重写了 forms。 对于多种用户类型,我使用的是配置文件 model(学生 model 对用户模型有一个 OneToOne 字段)

模型.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

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

视图.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')

每当用户注册时,学生表如下所示: 学生报名后表

此外,这是用户表在注册后的样子(多次保存) 在此处输入图像描述

那么如何更正用户表中的多次保存呢? 此外,如何在大部分必填字段为空的情况下保存 model?

正如@RaghavKundra 所指出的,下面的行是导致多次保存到数据库的问题的原因

class Student(User):

相反,它应该是class Student(models.Model):

暂无
暂无

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

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