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!
Usage of AutoField
You don't need to include
id = models.AutoField(primary_key=True,unique=True). Django does it for you: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.
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).