Расширение модели абстрактного пользователя для двух различных типов пользователей (клиент, продавец)
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()
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?
can i use django default auth login,logout,password-reset functionalities for both of these user types?
Ошибка миграции... Я бы сказал, что у вас mobileno
где-то в admin.py
On CustomUser ModelAdmin class.
По поводу модели пользователя. На самом деле вы сделали то, что у вас все еще одна модель пользователя (я думаю, что Django's auth не поддерживает больше) с некоторыми дополнительными данными для клиентов и поставщиков. Поэтому USERNAME_FIELD
, REQUIRED_FIELDS
и т.д. должны быть только на классе CustomUser
и только поля, указанные для клиентов и поставщиков должны быть на этих моделях.
Итак, ваши модели должны выглядеть примерно так:
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
И вы можете добавить методы create_customer
и create_vendor
к менеджеру:
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
Вы можете прочитать об этом в документации Django https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#extending-the-existing-user-model