简体   繁体   中英

extending the abstractuser model for two different user types (customer,vendor)

models.py

 from django.contrib.auth.models import AbstractUser, BaseUserManager
 from django.db import models
 from django.utils.translation import ugettext_lazy as _


 class CustomUserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""

def _create_user(self, email, password=None, **extra_fields):
    """Create and save a User with the given email and password."""
    if not email:
        raise ValueError('The given email must be set')
    email = self.normalize_email(email)
    user = self.model(email=email, **extra_fields)
    user.set_password(password)
    user.save(using=self._db)
    return user

def create_user(self, email, password=None, **extra_fields):
    extra_fields.setdefault('is_staff', False)
    extra_fields.setdefault('is_superuser', False)
    return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password=None, **extra_fields):
    """Create and save a SuperUser with the given email and password."""
    extra_fields.setdefault('is_staff', True)
    extra_fields.setdefault('is_superuser', True)

    if extra_fields.get('is_staff') is not True:
        raise ValueError('Superuser must have is_staff=True.')
    if extra_fields.get('is_superuser') is not True:
        raise ValueError('Superuser must have is_superuser=True.')

    return self._create_user(email, password, **extra_fields)




 class CustomUser(AbstractUser):
     is_customer = models.BooleanField('customer status', default=False)
     is_vendor = models.BooleanField('vendor status', default=False)


 class Customer(models.Model):
     customeruser = models.OneToOneField(CustomUser, on_delete=models.CASCADE, 
      primary_key=True)
     username = None
     email = models.EmailField(_('email address'), unique=True)
     firstname = models.CharField(max_length=200)
     lastname = models.CharField(max_length=200)
      mobileno = models.IntegerField(blank=True, null=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()


 class Vendor(models.Model):
     vendoruser = models.OneToOneField(CustomUser, on_delete=models.CASCADE, primary_key=True)
     username = None
     email = models.EmailField(_('email address'), unique=True)
     firstname = models.CharField(max_length=200)
     lastname = models.CharField(max_length=200)
     mobileno = models.IntegerField(blank=True, null=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()
  1. I am using the email field as main field instead of the username field to signup and login. also, in admin.py i used email as the main field. While attempting makemigrations showing error (django.core.exceptions.FieldError: Unknown field(s) (mobileno) specified for CustomUser)Is it the right way to approach?

  2. can i use django default auth login,logout,password-reset functionalities for both of these user types?

Migration error... I would say you have mobileno somewhere in admin.py On CustomUser ModelAdmin class.

About User model. What you actually did is that you have still one user model(I think Django's auth doesn't support more) with some extra data for Customers and Vendors. So USERNAME_FIELD , REQUIRED_FIELDS etc. should be just on CustomUser class and only fields specified for customers and vendors should be on these models.

so your models should look something like this:

class CustomUser(AbstractUser):
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    
    username = None
    email = models.EmailField(_("email address"), unique=True)
    mobileno = models.IntegerField(blank=True, null=True)

    objects = CustomUserManager()

    def is_customer(self):
        return hasattr(self, "customer")

    def is_vendor(self):
        return hasattr(self, "vendor")



class Customer(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, 
    primary_key=True)
    customer_number = models.CharField(max_length=32)  # just some customer specific field
    

class Vendor(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, primary_key=True)
    vendor_number = models.CharField(max_length=32)  # just some vendor specific field

And you can add create_customer and create_vendor methods to manager:

class CustomUserManager(BaseUserManager):
    """Define a model manager for User model with no username field."""

    def _create_user(self, email, password=None, **extra_fields):
        """Create and save a User with the given email and password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password=None, **extra_fields):
        """Create and save a SuperUser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)
    
    def create_customer(self, email, password=None, customer_number, **extra_fields):
        user = self.create_user(email, password, **extra_fields)
        Customer.objects.create(user=user, customer_number=customer_number)
        return user
    
    def create_vendor(self, email, password=None, vendor_number, **extra_fields):
        user = self.create_user(email, password, **extra_fields)
        Vendor.objects.create(user=user, vendor_number=vendor_number)
        return user

You can read about it in Django's docs https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#extending-the-existing-user-model

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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