Reputation: 215
The Employee model in my Django project has a OneToOneField relationship with the built-in Django User model. I have then further inherited this Employee model into two different Manager and Associate models. Now, when a user logs in, I want to check if this user is a Manager or an Associate in my HTML template so that I can display different options, depending on whether they are a Manager or an Associate. What is the best way to that?
Models.py-
GENDER = [('male','Male'),('female','Female')]
class Employee(models.Model):
user_def = models.OneToOneField(User,on_delete=models.CASCADE,null=True)
name = models.CharField(max_length = 50)
age = models.IntegerField()
gender = models.CharField(max_length = 10,choices = GENDER)
def __str__(self):
return self.name
class Manager(Employee):
dept = models.CharField(max_length = 50)
def __str__(self):
return super().__str__()
class Associate(Employee):
reports_to = models.ForeignKey(Manager,on_delete=models.CASCADE)
def __str__(self):
return super().__str__()
Upvotes: 3
Views: 330
Reputation: 10399
Ooo, using model inheritance eh? Django has three types of model inheritance, and based on your problem, it seems like what you need is Meta inheritance.
In this case, you want to make your Employee
abstract and in the user_def
field, define the related_name
that provides a backwards relationship from the user to the subclassed models, which in your case would be the Manager
or Associate
models. You can't use any related_name
however. You need to include the app label and class within the related name, e.g.: related_name="%(app_label)s_%(class)s"
. Here, the app_label
and class
would be app labels and classes of Manager
and Associate
so if you have your models defined in an app called hr
, then to get the backwards relation from user
(user
is the user instance) to manager, you use user.hr_manager
. Likewise if the user is associate, use user.hr_associate
.
So, this backwards relation then essentially answers your question because since user has 1-to-1 relation to your Employee
model, the user can only either be a manager or an associate. They are mutually exclusive. Therefore, if your user is a manager, then that user will return a Manager
instance if you ask for user.hr_manager
and None if you ask for user.hr_associate
.
Now I notice you have allowed null=True
on your OneToOneField, so it is possible that the user will return None for both instances of user.hr_manager
and user.hr_associate
. Therefore, just remember to do a thorough if/elif/else check on the user.
GENDER = [('male','Male'),('female','Female')]
class Employee(models.Model):
user_def = models.OneToOneField(
User,
on_delete=models.CASCADE,
null=True,
related_name="%(app_label)s_%(class)s"
)
name = models.CharField(max_length=50)
age = models.IntegerField()
gender = models.CharField(
max_length=10,
choices = GENDER
)
class Meta:
abstract = True
class Manager(Employee):
dept = models.CharField(max_length=50)
def __str__(self):
return self.name
class Associate(Employee):
reports_to = models.ForeignKey(
Manager,
on_delete=models.CASCADE
)
def __str__(self):
return self.name
EDIT:
I haven't tested the code, specifically the part about user.hr_manager
/user.hr_associate
. They may actually throw an error instead of None if there is no backwards relationship. In this case, you can simply catch and ignore the errors and move on to the next if/elif/else check.
Upvotes: 2