I have created a role model for Employee so that employee will be assigned to control
the overall app based on his/her role. I mean if the role of employee is given can_create_only, then the employee should be able to create inventory, orders, items etc and if employee is given can_create_edit_and_delete, then the employee would be like one of the admin and etc. For this I have designed the model as below but I want to know what is the best way to handle such and why?
Should I go with middleware or decorator way? Can anyone give me an example, please?
class Role(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
class Meta:
verbose_name = 'Role'
verbose_name_plural = 'Roles'
class Employee(models.Model):
office = models.ForeignKey(
OfficeSetup, blank=False, null=False, on_delete=models.CASCADE)
name = models.CharField(max_length=150, blank=False, null=False)
designation = models.ForeignKey(Designation, blank=False, null=False)
section = models.ForeignKey(DepartmentSetup, blank=True, null=True)
phone_number = models.CharField(max_length=150, blank=True, null=True)
mobile_number = models.CharField(max_length=150, blank=True, null=True)
email = models.EmailField(max_length=150, blank=False, null=False)
gender = models.CharField(
max_length=4, choices=GENDER, blank=True, null=True)
role = models.ForeignKey(Role, blank=True, null=True)
username = models.CharField(max_length=100, blank=False, null=False)
password = models.CharField(max_length=100, blank=False, null=False)
avatar = models.ImageField(
null=True, blank=True, upload_to=upload_employee_image_path)
class Meta:
verbose_name = 'Employee'
verbose_name_plural = 'Employees'
def __str__(self):
return self.name
When creating an employee by admin, the username, password and email, the admin provides will create a new user instance along with the employee
Django comes with Groups and permissions which provides all most everything you are looking for.
This may help you - How do I use Django groups and permissions?
Django documentation - https://docs.djangoproject.com/en/1.11/topics/auth/
Related
I have many to many field in user model where one user can have multiple roles for example admin, patient, doctor and others. now I want to query data to get users with admin and all other roles and not doctor and patient role. I am using this
User.objects.exclude(roles__code_name__in=['pt', 'doc'])
now my one user signs up as patient too so he has admin and patient role both now i am unable to get him by using above query. so concluding... if user has two roles if one of it is patient and he has any other role too i want to get him too. what should i do? Thanks in advance
UPDATE
class User(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(max_length=60, blank=True, null=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
cnic = models.CharField(max_length=13, unique=True)
mobile = models.CharField(max_length=11, unique=True)
dob = models.DateField(blank=True, null=True)
full_name = models.CharField(max_length=90, blank=True, null=True)
profile_image = models.ImageField(max_length=255, upload_to=get_profile_image_path, null=True, blank=True, default=get_default_profile_image_path)
next_of_kin_name = models.CharField(max_length=60, blank=True, null=True)
next_of_kin_mobile = models.CharField(max_length=11, blank=True, null=True)
is_delete = models.BooleanField(default=False)
status = models.IntegerField(default=0)
contact = models.CharField(max_length=10, blank=True, null=True)
hospital = models.ForeignKey('Hospital', on_delete=models.SET_NULL, blank=True, null=True)
roles = models.ManyToManyField('Role', related_name='users')
is_staff = models.BooleanField(default=False)
balance = models.PositiveIntegerField(default=0)
gender = models.CharField(max_length=10, choices=gender_choices, default=gender_choices[0][0])
phone_verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey('self', related_name='+', blank=True, null=True, on_delete=models.CASCADE)
updated_at = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey('self', related_name='+', blank=True, null=True, on_delete=models.CASCADE)
This is my model it has roles as many to many field. i have multiple roles like doctor, patient, admin and many others custom created roles with custom permissions. I have a view where i want to get data of users that are not patients or doctors. everything was working fine until one of my admin user decides to sign up as patient so he has now both patient and admin role and now i am unable to get him by using above mentioned query
Eureka. This solution is working fine for me idk if it's the ideal approach bit is working at the moment. Thanks #all
User.objects.annotate(num_roles=Count('roles')).exclude(Q(id=self.request.user.id) | Q(is_delete=True) | Q(roles__code_name__in=['pt', 'doc', 'su']) & Q(num_roles=1)).order_by('-id')
I am working with some custom-made user models in Django. They are the following:
myCustomeUser responsible for the primary identity of a user
Industry is a user that will link with OneToOneField to the myCustomeUser
Employee is another user account, which will FK to the myCustomeUser and FK to Industry
my models.py:
class myCustomeUser(AbstractUser):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=20, unique="True", blank=False)
password = models.CharField(max_length=20, blank=False)
is_Employee = models.BooleanField(default=False)
is_Industry = models.BooleanField(default=False)
class Industry(models.Model):
user = models.OneToOneField(myCustomeUser, on_delete=models.CASCADE, primary_key=True, related_name='industry_releted_user')
name = models.CharField(max_length=200, blank=True)
owner = models.CharField(max_length=200, blank=True)
license = models.IntegerField(null=True, unique=True)
industry_extrafield = models.TextField(blank=True)
Now I need to write the model of Employee. There are some conditions also:
It should contain name, National ID, gmail, rank, employee_varified, named fields
This will inherit the myCustomeUser and Industry both
The Industry account user will primarily entry all the data of Employee in the database, except username and password(which are inherited from myCustomeUser)
Later on, the Employee will search his National ID given by the Industry and finish the registration process by creating his username and password.
I have tried the Employee model like this:
class Employee(models.Model):
user = models.ForeignKey(myCustomeUser,primary_key=True, null=True, on_delete=models.CASCADE)
industry = models.ForeignKey(Industry, on_delete=models.CASCADE)
National_ID = models.IntegerField(null=True, blank=False, unique=True)
name = models.CharField(max_length=200, blank=False, null=True)
gmail = models.EmailField(null=True, blank=False, unique=True)
rank = models.CharField(max_length=20, blank=False, null=True)
employee_varified = models.BooleanField(default=False, blank=True, null=True)
But the problem with this model is I cannot create any Employee object without giving user (that means username and password), But the Industry user needs to entry their Employee's data, before complete the Employee's registration.
how can I write my Employee model to solve this problem?
If you can't guarantee that a related object will exist when you create an object, you can make the relationship(s) optional.
So in your case, I'd create your model more like;
class Employee(models.Model):
user = models.ForeignKey(
myCustomeUser,
blank=True,
null=True,
on_delete=models.CASCADE
)
industry = models.ForeignKey(
Industry,
blank=True,
on_delete=models.CASCADE
)
national_id = models.IntegerField(
null=True,
blank=False,
unique=True
)
name = models.CharField(
max_length=200,
blank=False,
null=True
)
# ... etc
You may also benefit from having a look through the following site which might help you learn a thing or two about django
https://www.django-antipatterns.com/
Apologies if this question is too subjective.
If you are planning to close this question: please comment with a suggestion for a more appropriate place to post.
I'm super new to django and python, and I'm building a test app that keeps track of employees and who their managers are.
I would like to set up the domain model so that there there is only one list of employees, any of which can be managers, and all of which can be managed by any other employee who is designated a manager.
To achieve this, I did a self-join on the Employee model and have an "is_manager" flag to keep track of who is a manager and who isn't (see model below).
Is an acceptable pattern?
I'm worried it violates a design principle I'm not considering and there's some hairy trap that I'm walking into as a noob.
Thank you very much for your time.
models.py for the app:
class OrganizationTitle(models.Model):
def __str__(self):
return "{}".format(self.organization_title_name)
organization_title_name = models.CharField(max_length=150, unique=True)
class ClassificationTitle(models.Model):
def __str__(self):
return "{}".format(self.classification_title_name)
classification_title_name = models.CharField(max_length=150, unique=True)
class WorkingTitle(models.Model):
def __str__(self):
return "{}".format(self.working_title_name)
working_title_name = models.CharField(max_length=150, unique=True)
class Category(models.Model):
def __str__(self):
return "{}".format(self.category_name)
category_name = models.CharField(max_length=150, unique=True)
class Department(models.Model):
def __str__(self):
return "{}".format(self.department_name)
department_name = models.CharField(max_length=150, unique=True)
class Employee(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
org_title = models.ForeignKey(OrganizationTitle, blank=True, null=True, on_delete=models.SET_NULL)
manager = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL)
manager_email = models.EmailField(max_length=50, blank=True, null=True)
hire_date = models.DateField(blank=True, null=True)
classification_title = models.ForeignKey(ClassificationTitle, blank=True, null=True, on_delete=models.SET_NULL)
working_title = models.ForeignKey(WorkingTitle, blank=True, null=True, on_delete=models.SET_NULL)
email_address = models.EmailField(max_length=250, blank=False, unique=True,
error_messages={'unique': 'An account with this email exist.',
'required': 'Please provide an email address.'})
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
is_substitute = models.BooleanField(default=False)
department = models.ForeignKey(Department, blank=True, null=True, on_delete=models.SET_NULL)
is_active = models.BooleanField(default=True)
is_manager = models.BooleanField(default=False)
class Meta:
ordering = ('is_active', 'last_name',)
def __str__(self):
return "{}".format(self.first_name + ' ' + self.last_name)
That's perfectly fine.
I would recommend you to specify the related_name to keep your code more explicit:
manager = models.ForeignKey(..., related_name="managed_employees")
so then you can do something like:
bob.managed_employees.all()
Also, there are 2 things I would change (not your question but still regarding the models):
1.The manager_email field is redundant. I would remove it. You already have that information at tom.manager.email_address for example.
2.There are many fields that I would simply rename to name. For example:
class OrganizationTitle(models.Model):
def __str__(self):
return u"{}".format(self.name)
name = models.CharField(max_length=150, unique=True)
No need to call it organization_title_name. That's consistent with the first_name field (not employee_first_name).
Yes, this is an acceptable pattern. This is called a "recursive relationship", or "self referential foreign keys" and is a very common usecase in realworld applications.
Here is django's example supporting this usecase
I am creating a simple project which is about creating a resume by user. In resume, a user can have multiple experience, educational background and etc. That is why I have created the following table where experience, educational background, skills are foreignkey to the resume table.
class Resume(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=False, null=False, help_text="Full Name")
slug = models.SlugField(max_length=50, unique=True)
designation = models.CharField(max_length=200, blank=True, null=True)
city = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.name
class Education(models.Model):
resume = models.ForeignKey(Resume, related_name='education')
name = models.CharField(max_length=100, blank=False, null=False, help_text="Name of an institution")
course = models.CharField(max_length=200, blank=False, null=False, help_text="Name of a course")
description = models.CharField(max_length=400, blank=True, null=True)
start_date = models.DateField()
end_date = models.DateField()
class Experience(models.Model):
resume = models.ForeignKey(Resume, related_name='experience')
designation = models.CharField(max_length=100, blank=True, null=True)
company = models.CharField(max_length=100, blank=True, null=True)
description=models.CharField(max_length=400, blank=True, null=True)
start_date = models.DateField()
end_date = models.DateField()
class Skill(models.Model):
resume=models.ForeignKey(Resume, related_name="skills")
name = models.CharField(max_length=100, blank=True, null=True, help_text="Name of the skill")
class Meta:
verbose_name='Skill'
verbose_name_plural='Skills'
def __str__(self):
return self.name
Now for such situation, do I have to create a ResumeForm, EducationForm, ExperienceForm etc and create an Education, Experience and Skill formset or
I have to do something else. I do not have clear idea on how to move forward now for developing form with such
relation where Education, Skill can have multiple instance. Can anyone guide me, please?
Well the question is unclear but following with your idea you have 2 options:
First you can have existing values in Education, Experience, Skill. Then in the view you have a checkbox to add education, experience, skill.
Second you can add education, experience, skill creating a modelForm for each one and then passing the resume, It is not necessary use formset here
I have following two models
class Questionnaire(models.model)
name = models.CharField(max_length=128, null=True, blank=True)
type = models.CharField(max_length=128,choices=questionnaire_choices)
class TestPopulation(models.Model)
user = models.ForeignKey(User, blank=True, null=True)
age = models.CharField(max_length=20, blank=True, null=True)
education = models.CharField(max_length=50, blank=True, null=True,
choices=EDUCATION_CHOICES)
questionnaire = models.ManyToManyField(Questionnaire, blank=True, null=True)
Now how can i get number of questionnaires for the specific user (logged in user). ?
test_population = TestPopulation.objects.get(user=user)
test_population.questionnaire.all()
questionnaire.objects.filter(test_population__user=user).count()