Search code examples
djangodjango-modelsdjango-rest-framework

Design User class in Django


I use the AbstractUser class to extend my User class. In my User class, there are currently 3 roles: Admin, Lecturer and Alumni. I can use is_superuser, is_staff to solve the problem, however, in the future there may be more roles appearing and if I use the above method it will not be possible to add more roles better. But if I use the additional field role = models.IntegerField(choices=Role.choices, default=Role.ALUMNI) it looks fine. But when using superuser, is_superuser = True and the user's role is Alumni. By the way, I'm working on a project using django, rest_framework. I want Users with the role of Lecturer to be created by the Admin and set a default password, and after 24 hours from the time of account creation, if the Lecturer does not change the password, the account will be locked and the Admin will have to reopen for Lecturer. I wrote two functions save and check_password_expiry but I'm not sure if it works as I want. Can someone solve my current problem, please?

class User(AbstractUser):

    class Role(models.IntegerChoices):
        ADMIN = 1, "Admin"
        LECTURER = 2, "Lecturer"
        ALUMNI = 3, "Alumni"

    avatar = CloudinaryField(null=True)
    cover = CloudinaryField(null=True)
    role = models.IntegerField(choices=Role.choices, default=Role.ALUMNI)
    alumni = models.OneToOneField(Alumni, on_delete=models.CASCADE, null=True, blank=True)
    friends = models.ManyToManyField('self', symmetrical=True, blank=True)

    def save(self, *args, **kwargs):
        if self.role == User.Role.LECTURER and not self.password: 
            self.set_password('ou@123')
        super().save()

    def check_password_expiry(self):
        if self.role == User.Role.LECTURER:
            if timezone.now() - self.date_joined > timedelta(hours=24):
                self.is_active = False
                self.save()
                
    def __str__(self):
        return f'{self.last_name} {self.first_name}'

Solution

  • Add role to the REQUIRED_FIELDS [Django-doc]:

    class User(AbstractUser):
        REQUIRED_FIELDS = ['role']
        # …

    As the documentation says:

    A list of the field names that will be prompted for when creating a user via the createsuperuser management command. The user will be prompted to supply a value for each of these fields. It must include any field for which blank is False or undefined and may include additional fields you want prompted for when a user is created interactively. REQUIRED_FIELDS has no effect in other parts of Django, like creating a user in the admin.