如何在 django 中使用 OneToOneFeild 扩展 AbstractBaseUser

how to extend AbstractBaseUser with OneToOneFeild in django

我创建了 AbstractBaseUser 模型和一个 BaseManager。

下面给出model.py

GENDER_CHOICES = (('M', 'Male'),('F', 'Female'))
class AccountManager(BaseUserManager):
    def create_user(self,email,username,phone,gender,password=None,**extrafields):
        if not email:
            raise ValueError("email is needed")
        if not username:
            raise ValueError("uname is needed")
        if not phone:
            raise ValueError("Phone is needed")
        if not gender:
            raise ValueError("gender is needed")
        user= self.model(
            email=self.normalize_email(email),
            username=username,
            phone=phone,
            gender=gender,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self,email,username,phone,gender,password,**extrafields):
        user=self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
            phone=phone,
            gender=gender,    
        )
        user.is_admin=True
        user.is_staff=True
        user.is_superuser=True
        user.save(using=self._db)
        return user   
class Account(AbstractBaseUser):
    ACCTYPE = (
        ('Student', 'Student'),
        ('Staff', 'Staff')
    )
    email=models.EmailField(verbose_name='E-mail', max_length=30, unique=True)
    username=models.CharField(verbose_name='Username', max_length=30, unique=True)
    last_login=models.DateTimeField(verbose_name='Last Login', auto_now=True)
    phone=models.CharField(verbose_name='Phone', max_length=50)
    gender= models.CharField(choices=GENDER_CHOICES, max_length=128)
    acctype = models.CharField(max_length=16, choices=ACCTYPE)
    is_admin=models.BooleanField(default=False)
    is_active=models.BooleanField(default=True)
    is_staff=models.BooleanField(default=False)
    is_superuser=models.BooleanField(default=False)
    USERNAME_FIELD ='username'
    REQUIRED_FIELDS=['email','phone','gender']
    objects=AccountManager()
    def __str__(self):
        return self.username
    def has_perm(self,perm,obj=None):
        return self.is_admin
    def has_module_perms(self, app_lebel):
        return True

And I am also tried to extend this user model Into StudentAccnt and StaffAccnt.

class StudentAccnt(models.Model):
    user=models.OneToOneField(Account,on_delete=models.CASCADE)
    reg_number=models.CharField(verbose_name='Reg NO', max_length=10,unique=True)

class StaffAccnt(models.Model):
    user=models.OneToOneField(Account,on_delete=models.CASCADE)
    id_number=models.CharField(verbose_name='Id NO', max_length=10,unique=True)

I want to create user using UserRegistrarionForm and add to StudentAccnt and StaffAccnt tables by checking acctype.

如何做到这一点??

终于找到解决办法了

it can be created using signals

When I create views for this custom user registration form, it simultaneously creates a corresponding instance.

我们需要导入这些

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import models

add this at end of the view

@receiver(post_save,sender=Account)
def create_usersaccnt(sender,instance,created,**kwrags):
    if created and (instance.acctype=='Student'):
        StudentAccnt.objects.create(user=instance)
    elif created and (instance.acctype=='Staff'):
        StaffAccnt.objects.create(user=instance)

@receiver(post_save,sender=Account)
def save_usersaccnt(sender,instance,created,**kwrags):
    if instance.acctype=='Student':
        instance.studentaccnt.save()
    elif instance.acctype=='Staff':
        instance.staffaccnt.save()

you can also specify it through additional python file called signals.py