#django #django-models #django-views
Вопрос:
Я создал пользовательскую User
модель с несколькими ролями клиентов и сотрудников, где сотрудники также выполняют разные роли: водители и администрация.
Я расширил AbstractBaseUser
класс модели, чтобы настроить пользовательскую модель следующим образом:
class UserAccountManager(BaseUserManager):
def create_superuser(self, email, first_name, last_name, password, **other_fields):
other_fields.setdefault("is_staff", True)
other_fields.setdefault("is_superuser", True)
other_fields.setdefault("is_active", True)
other_fields.setdefault("is_driver", True)
other_fields.setdefault("is_customer", True)
other_fields.setdefault("is_responsable", True)
if other_fields.get("is_staff") is not True:
raise ValueError(_("Superuser must be assigned to is_staff."))
if other_fields.get("is_superuser") is not True:
raise ValueError(_("Superuser must be assigned to is_superuser."))
return self.create_user(email, first_name, last_name, password, **other_fields)
def create_user(self, email, first_name, last_name, password, **other_fields):
if not email:
raise ValueError(_("You must provide an email address"))
email = self.normalize_email(email)
user = self.model(email=email, first_name=first_name, last_name=last_name, **other_fields)
user.set_password(password)
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_("Email Address"), unique=True)
first_name = models.CharField(_("First Name"), max_length=150, unique=True)
last_name = models.CharField(_("Last Name"), max_length=150, unique=True)
mobile = models.CharField(_("Mobile Number"), max_length=150, blank=True)
is_active = models.BooleanField(_("Is Active"), default=False)
is_staff = models.BooleanField(_("Is Staff"), default=False)
is_driver = models.BooleanField(_("Is Driver"), default=False)
is_responsable = models.BooleanField(_("Is Responsable"), default=False)
is_customer = models.BooleanField(_("Is Customer"), default=False)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True, editable=False)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
objects = UserAccountManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name"]
class Meta:
verbose_name = "Account"
verbose_name_plural = "Accounts"
def __str__(self):
return self.first_name
и я создал два типа моделей, расширяющих эту модель, которые представляют каждую из них в другой роли и наследуют от User
модели:
class Employee(User):
registration_number = models.PositiveSmallIntegerField(_("Driver Registration Number"), unique=True)
picture = models.ImageField(
verbose_name=_("Driver Pic"), help_text=_("Driver Identity Picture"), upload_to="images/driver/"
)
birth_date = models.DateField(_("Date Birth of the Driver"))
city_id = models.ForeignKey("City", blank=True, null=True, on_delete=models.SET_NULL)
bank_id = models.ForeignKey("Bank", blank=True, null=True, on_delete=models.SET_NULL)
class Meta:
verbose_name = "Employee"
verbose_name_plural = "Employees"
def __str__(self):
return self.first_name " " self.last_name
class Customer(User):
company_name = models.CharField(_("Company Name"), max_length=150, unique=True)
website = models.CharField(_("Company website"), max_length=150, unique=True)
mobile_2 = models.CharField(_("Mobile Number"), max_length=150, blank=True)
class Meta:
verbose_name = "Customer"
verbose_name_plural = "Customers"
def __str__(self):
return self.first_name " " self.last_name
Я хочу зарегистрировать модели в admin.py:
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
pass
admin.site.register(Customer)
admin.site.register(Employee)
проблема в том, что, когда я пытаюсь добавить пользователя из админ-страницы, я не могу задать пароль для данного пользователя, у меня есть поле пароля, которые появляются, когда я хочу добавить нового пользователя в любой модели, но поле, похоже, как любой нормальный InputText, пароль будет отображаться при касании, и пароль не зарегистрированы в базе данных.
Я хотел бы добавить два типа сотрудников в model.py :
class Responsable(Employee):
responsability_type = models.CharField(max_length=4, blank=True)
class Meta:
verbose_name = "Responsable"
verbose_name_plural = "Responsables"
def __str__(self):
return self.first_name " " self.last_name
class Driver(Employee):
driving_licence = models.ImageField(
verbose_name=_("Driver Licence"), help_text=_("Driver Licence Picture"), upload_to="images/driver_licence/"
)
driver_licence_expiration_date = models.DateField(_("Expiration Date for Driver Licence"))
class Meta:
verbose_name = "Driver"
verbose_name_plural = "Drivers"
def __str__(self):
return self.first_name " " self.last_name
Я не знаю, стоит ли создавать эти модели для такого рода ролей, я хочу избежать получения нескольких таблиц с сохраненными в них паролями.
Ответ №1:
Не используйте наследование модели подобным образом, особенно для пользовательской User
модели. Создает уникальную модель , которая наследуется от AbstractBaseUser
, содержит тип пользователя и содержит все поля, которые вы объявили в своих текущих таблицах:
class User(AbstractBaseUser, PermissionsMixin):
class UserTypes(Enum):
customer = ('cu', 'Customer')
responsable = ('re', 'Responsable')
driver = ('dr', 'Driver')
@classmethod
def get_value(cls, member):
return cls[member].value[0]
user_type = models.CharField(max_length=2, choices=[x.value for x in UserTypes])
# Insert fields that are in common between all user types, for example:
email = models.EmailField(_("Email Address"), unique=True)
# Insert fields that could be None depending on the user type, for example:
company_name = models.CharField(_("Company Name"), max_length=150, unique=True, null=True, blank=True)
Затем добавьте это в свои настройки:
AUTH_USER_MODEL = 'yourappname.User'
Вы ModelAdmin
для управления пользователями должны наследовать от UserAdmin
, чтобы разрешить управление паролями:
@admin.register(User)
class UserAdmin(UserAdmin):
fieldsets = ((None, {'fields': ('email', 'password', 'user_type', 'company_name')})) # Other fields showed when updating an user
add_fieldsets = ((None, {'fields': ('email', 'password', 'user_type', 'company_name')})) # Other fields showed when creating an user
Комментарии:
1. Я думаю, что это усложнит мои взгляды на другую роль, но я попробую эту рекомендацию. Я не знаю, почему вы добавили класс метода `get_value().
2. Я добавил класс метода
get_value
, чтобы вы могли написать, например:User.objects.filter(user_type=User.UserTypes.get_value('driver'))
. Ваши представления будут проще с уникальной моделью, просто требуйте определенного типа пользователя и проверяйте его на проверку (аналогично коду, который я написал в этом комментарии). С несколькими моделями аутентификация была бы намного сложнее.