簡體   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