0

I am overriding django's default user model . I tried to link the userprofile with the CustomUser model and added a receiver which will automatically create instance of profile model when user is created based on their role

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from .managers  import CustomUserManager
from django.db.models.signals import post_save


# Create your models here.


class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_("email"),primary_key=True,unique=True,blank=False,null=False)
    phone_number = models.CharField(max_length=10,null=False,blank=False)
    ROLE_CHOICES = (
        ('ADMIN', 'ADMIN'),
        ('STUDENT','STUDENT'),
        ('TEACHER', 'TEACHER'),
        ('PRINCIPAL', 'PRINCIPAL'),
    )
    role = models.CharField(choices=ROLE_CHOICES, blank=True,default='ADMIN',max_length=10)   
    REQUIRED_FIELDS = ['phone_number','first_name','last_name']
    USERNAME_FIELD = "email"

    objects = CustomUserManager()

    def __str__(self):
        return self.email

  


class StudentProfile(models.Model):
    user = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
    id = models.AutoField(primary_key=True,unique=True)
    merit = models.CharField(max_length=6,blank=True,null=True)

    def __str__(self):
        return self.user.email

class TeacherProfile(models.Model):
    user = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
    id = models.AutoField(primary_key=True,unique=True)
    salary = models.CharField(max_length=6,blank=True,null=True)
    education = models.CharField(max_length=100,blank=True,null=True)

    def __str__(self):
        return self.user.email
    

class PrincipalProfile(models.Model):
    user = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
    id = models.AutoField(primary_key=True,unique=True)
    salary = models.CharField(max_length=6,blank=True,null=True)
    education = models.CharField(max_length=100,blank=True,null=True)
    years_of_experience = models.IntegerField(null=True, blank=True)

    def __str__(self):
        return self.user.email
    


@receiver(post_save, sender=CustomUser)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        if instance.role == 'PRINCIPAL':
            PrincipalProfile.objects.create(user=instance)
        elif instance.role == 'STUDENT':
            StudentProfile.objects.create(user=instance)
        elif instance.role == 'TEACHER':
            TeacherProfile.objects.create(user=instance)
        else:
            pass
    else:
        print("Profile not created")

As a newcomer to coding, I've crafted my first piece of code and I'm seeking the community's expertise to review its legitimacy and advise me on potential improvements. Your guidance would be greatly appreciated!

1 Answers1

0

Usage of AutoField

You don't need to include id = models.AutoField(primary_key=True,unique=True). Django does it for you:

By default, Django gives each model an auto-incrementing primary key...

Blank and Null

Django default values of null and blank for field are False, so you can avoid to explicitly specify this. It doesn't affect code understandability because it's really common.

Field Inheritance

Your profiles' models have similar fields & functionality so I would create separate class to inherit from with property abstract of its Meta set to True. It prevents corresponding table to be created in database.

class AbstractProfile(models.Model):
    user = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
    
    def __str__(self):
        return self.user.email

    class Meta:
        abstract = True

Therefore, you can avoid repeating of your code and be sure of profiles' integrity.

Files

I don't know if you did it for readability but commonly signals are stored in separate called handlers.py. And simple managers can be created in the same file as theirs models

I don't know if you want it but currently your user can have student, teacher etc profiles simultaneously (at least, in database level).