Поле пользователя Django is_staff установлено в true в экземпляре, но читается как false в классе разрешения
Я пытаюсь создать конечную точку api, которая выводит список всех пользователей в базе данных, но я хочу, чтобы это могли делать только сотрудники. По умолчанию при создании секретаря поле is_staff
в модели пользователей устанавливается в значение True
. В классе разрешений я проверяю, установлено ли это поле в true, и соответственно предоставляю разрешения.
Поскольку у меня много различных типов пользователей с немного отличающимися атрибутами, я создал конкретную базовую модель пользователя, которая наследуется другими моделями пользователей. Роль SECRETARY
назначается сериализатором при обработке запроса конечной точки создания секретаря.
class User(AbstractBaseUser):
class Roles(models.TextChoices):
"""define the user roles"""
ADMIN = "ADMIN", "Admin"
PRINTER = "PRINTER", "Printer"
SECRETARY = "SECRETARY", "Secretary"
PHOTOGRAPHER = "PHOTOGRAPHER", "Photographer"
EDITOR = "EDITOR", "Editor"
CLIENT = "CLIENT", "Client"
SYSTEM = "SYSTEM", "System"
APPLICANT = "APPLICANT", "Applicant"
id = models.CharField(
max_length=8, unique=True, primary_key=True, default=uidgen, editable=False
)
first_name = models.CharField("First Name", max_length=30, null=False)
last_name = models.CharField("Last Name", max_length=30, null=True, blank=True)
email = models.EmailField(
verbose_name="Email", max_length=255, unique=True, null=False
)
username = None
phone_number = models.CharField(
"Phone Number", max_length=20, null=False, unique=True
)
dob = models.DateField(verbose_name="Date Of Birth", blank=True, null=True)
role = models.CharField(max_length=50, default=Roles.CLIENT)
date_joined = models.DateTimeField(verbose_name="Date Joined", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="Last Login", auto_now=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["phone_number"]
is_staff = False
is_superuser = False
is_active = True
is_contractor = False
is_associate = False
phone_is_verified = False
email_is_verified = False
objects = UserManager()
User manager:
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError("The Email must be set")
user = self.model(
email=self.normalize_email(email),
)
if password:
user.set_password(password)
try:
if user.role == User.Roles.SECRETARY:
extra_fields.setdefault("is_staff", True)
else:
extra_fields.setdefault("is_staff", False)
except AttributeError:
user.role = User.Roles.ADMIN
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)
admin_user = self.create_user(email, password, **extra_fields)
admin_user.role = User.Roles.ADMIN
admin_user.save()
return admin_user
Модель секретаря:
class Secretary(User):
bank_number = models.CharField(max_length=50, null=True)
is_staff = True
class Meta:
verbose_name = "Secretary"
verbose_name_plural = "Secretaries"
def __str__(self):
return f"{self.first_name} {self.last_name}"
objects = UserManager()
Класс разрешения:
class UserListPermission(permissions.BasePermission):
def has_permission(self, request, view):
print(request.user.is_staff)
if view.action == "list" and request.user.is_staff:
return True
return False
def has_object_permission(self, request, view):
if view.action == "list" and request.user.is_staff:
return True
return False
Я создал секретаря вместе с маркером доступа и попытался получить доступ к конечной точке api только для сотрудников. Я получаю ответ:
{
"detail": "You do not have permission to perform this action."
}
В выводе оболочки сервера оператор print выдает False
. В оболочке django shell:
>>> sec = Secretary.objects.get(email='dinoseca@yahoo.de')
>>> sec.role
'SECRETARY'
>>> sec.is_staff
True
Когда я удаляю is_staff = True
из модели секретаря, вышеприведенный фрагмент оболочки приводит к False
Мне кажется, что ошибка кроется где-то в моем UserManager или моей модели User.
Вам необходимо сохранить пользователя перед возвратом в методе create_user. self.model просто создает экземпляр, а метод save должен быть вызван для сохранения экземпляра в базе данных.
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError("The Email must be set")
user = self.model(
email=self.normalize_email(email),
)
if password:
user.set_password(password)
try:
user.is_staff = True if user.role == User.Roles.SECRETARY else False
except AttributeError:
user.role = User.Roles.ADMIN
user.save(using=self._db)
return user
Это также может помочь прояснить https://stackoverflow.com/a/51163172/11128969