signup as multiple user - python

The use case of my application is I will have different kinds of user. They are:
Agent
Agency
Manufacturer
They have their own kinds of attributes.
1 User
2 Agent
ID
FirstName
MiddleName
LastName
DOB
Sex
Address:
City
Street
Country
Mobile Number
Organization
3 Agency
ID
Name
Address:
City
Street
Country
Contact Number (Multiple numbers can be added)
Email
VAT/PAN Number
4 Manufacturer
ID
Name
Address:
City
Street
Country
Contact Number (Multiple numbers can be added)
Email
VAT/PAN Number
[ Note: Agency have agents. Manufacturer could be
associated with the agency or could have agents directly. ]
For this, I have designed my model in such a way
class Agency(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(
max_length=200,
blank=False,
null=False)
city = models.CharField(max_length=150, blank=False, null=False)
street = models.CharField(max_length=150, blank=True, null=True)
country = models.CharField(max_length=150, blank=True, null=True)
mobile_number = PhoneNumberField()
email = models.EmailField(blank=False, null=False)
vat_number = models.CharField(max_length=40, blank=False, null=False)
agent/models.py
class Agent(models.Model):
SEX_CHOICE = (
('male', 'Male'),
('female', 'Female'),
)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
agencies = models.ForeignKey(
Agency,
related_name="agents",
on_delete=models.CASCADE)
manufacturers = models.ForeignKey(
Manufacturer,
related_name="agents_manufacturer",
on_delete=models.CASCADE,
blank=True,
null=True)
first_name = models.CharField(
max_length=120,
blank=False,
null=False)
middle_name = models.CharField(
max_length=120,
blank=True,
null=True)
last_name = models.CharField(
max_length=120,
blank=False,
null=False)
date_of_birth = models.DateField(blank=True, null=True)
sex = models.CharField(max_length=6, choices=SEX_CHOICE)
city = models.CharField(max_length=150, blank=False, null=False)
street = models.CharField(max_length=150, blank=True, null=True)
country = models.CharField(max_length=150, blank=True, null=True)
mobile_number = PhoneNumberField()
manufacturer/models.py:
class Manufacturer(models.Model):
owner = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="manufacturer")
agency = models.ForeignKey(
Agency,
blank=True,
null=True,
related_name="agency_manufacturer",
on_delete=models.CASCADE)
name = models.CharField(
max_length=200,
blank=False,
null=False)
city = models.CharField(max_length=150, blank=False, null=False)
street = models.CharField(max_length=150, blank=True, null=True)
country = models.CharField(max_length=150, blank=True, null=True)
mobile_number = PhoneNumberField()
email = models.EmailField(blank=False, null=False)
vat_number = models.CharField(max_length=40, blank=False, null=False)
I have used django-rest-auth for authentication. When i go to /rest-auth/registration the field like username, password1, password2 will be there. But i need which type of user, he/she is either. How do i handle such condition? Because, user should be able to login as either agent or agency or manufacturer. Can anyone help me at this, please?

I would advise against multiple user models. It is because, you introduce complexity to your logic wherever you need to do something with a user.
Moreover, you will get same IDs for different users and you will run into issues to deal with it.
I would recommend to create a custom User model and introduce something called a 'role' which would tell you what kind of user it is.
Then, you can add user profile to your model to add additional information based on the user's role.
Example of user model with a role attribute:
class MyUser(AbstractUser):
ROLE_CHOICES = (
('A', 'agent'),
('G', 'agency'),
('M', 'manufacturer'),
)
role = models.CharField(max_length=1, choices=ROLE_CHOICES)
For the profile, you can add OneToOneField called user profile ( you can check django rest documentation how to do ).
To have different type of registration, you can start with the following view:
class RegisterView(generics.CreateAPIView):
role = None
def perform_create(self, serializer):
serializer.save(role=role)
And use it your urls for different type of roles like this:
urlpatterns = [
url(r'^agents/', RegisterView.as_view(role='agent'), name="agent_register"),
url(r'^agencies/', RegisterView.as_view(role='agency'), name="agency_register"),
url(r'^manufacturers/', RegisterView.as_view(role='manufacturer'), name="manufacturer_register"),
]

you can extend all your models from django.auth.models.User. or create your own user model and extend all your models from it.
when you want to detect type of user use code like this:
if Agent.objects.filter(pk=user.pk).exists():
# its agent
if Agency.objects.filter(pk=user.pk).exists():
# its agency
if Manufacturer.objects.filter(pk=user.pk).exists():
# its manufacturer
to extend your models from user model just update your code same as below:
from django.auth.models import User
class Agent(User):
<same as your example>
class Agency(User):
<same as your example>
class Manufacturer(User):
<same as your example>

Related

Django: how to save instance to a foreign key field based on the fields equally

So I have a user model that has a foreign key relation with class/room, I want a user to be able to press one button and all the users/students would be equally distributed throughout the class/room foreign key based on fields from the model like age, height and other fields.
so if there are 4 students 2 with age 14 and 2 with age 15 and there are two classes, the function should put one 14-year-old and one 15-year-old in 1 class and the same in the other class as well, just iterate through the users and distribute them by the selected field values equally, any resource or code snippet would be highly appreciated.
user model if needed
class User(AbstractBaseUser, PermissionsMixin):
class SEX(models.TextChoices):
MALE = "MALE", "Male"
FEMALE = "FEMALE", "Female"
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False, unique=True)
sex = models.CharField(
_("Sex Type"), max_length=50, choices=SEX.choices, default=None, blank=True, null=True)
email = models.EmailField(
_("Email"), max_length=254, unique=True, default=None, blank=True, null=True)
student_id = models.CharField(
_("student id"), unique=True, max_length=10, blank=True, null=True)
firstname = models.CharField(max_length=250, blank=False, null=True)
middlename = models.CharField(max_length=250, blank=False, null=True)
lastname = models.CharField(max_length=250, blank=False, null=True)
grade = models.ForeignKey(Grade, verbose_name=_(
"grade"), on_delete=models.SET_NULL, blank=True, null=True)
room = models.ForeignKey(Class, verbose_name=_(
"class"), related_name="student_room", on_delete=models.SET_NULL, blank=True, null=True) // class model forignkey
age = IntegerRangeField(min_value=1, max_value=99,
default=25, blank=True, null=True)
image = models.ImageField(
_("photo"), upload_to='user/Users/profile_pic', max_length=None, blank=False, null=True)
joined_date = models.DateTimeField(
_("created at"), auto_now=False, auto_now_add=True)
has_rated = models.BooleanField(_("Has rated the app"), default=False)
...
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
ordering = ('-joined_date',)
objects = CustomAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname']
def __str__(self):
return self.firstname
I have given a code snippet for you to find a solution.It might not be the efficient solution. But you shall have gist.
def assign_class(request, *args, **kwargs):
age14_users = User.objects.filter(age=14).order_by('-joined_date')
age14_users_pk_list=list(age14_users.values_list('pk', flat=True))
age15_users = User.objects.filter(age=15).order_by('-joined_date')
age15_users_pk_list=list(age15_users.values_list('pk', flat=True))
age14_users_count = len(age14_users_pk_list)
age15_users_count = len(age15_users_pk_list)
classes= Class.objects.all()
class_count = classes.count()
class_pk_list=list(classes.values_list('pk', flat=True))
slice = age14_users_count//class_count
sliced_users_list_age14=[age14_users_pk_list[i:i+slice] for i in range(0, len(age14_users_pk_list), slice)]
#output eg. [[1,2,3],[4,5,6],[7,8]]
#User will be distributed to rooms rationally
'''
if we loop through sliced user clusters.. we can assign
each cluster to room rationally
'''
new_class_pk_list = class_pk_list.copy()
for lst in sliced_users_list_age14:
for user_pk in lst:
user = User.objects.get(pk=user_pk)
user.room_id =new_class_pk_list[0]
user.save()
del new_class_pk_list[0] #delete the class after assigning
#from copied list
'''
Now you can distribute the other cluster of group (eg. age15_users)
like above
'''

How to add specific permission view to certain users based on their field in Django?

So basically i have to make sure Users that are from the same department field to view and create any datas in the database. Not sure how to apply it using field-based user permissions?
class Profile(AbstractUser):
class Meta:
verbose_name_plural = 'Profiles'
company = models.CharField(max_length=30, null=True)
contact = models.CharField(max_length=20, null=True)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.CharField(max_length=20)
modify_by = models.CharField(max_length=20)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
is_active = models.BooleanField(default=False, null=True,
blank=True)
is_superuser = models.BooleanField(default=False, null=True,
blank=True)
is_staff = models.BooleanField(default=False, null=True,
blank=True)
def __str__(self):
return self.username
You should use what's already implemented in Django, and you'll gain a lot of time.
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.ForeignKey(Group, on_delete=models.CASCADE)
contact = models.ForeignKey('Person', on_delete=models.CASCADE)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
even though my eyes are burning because my syntax here is not PEP8 compliant, you should get the big picture: all the permissions are already handled by User and Group.
Just create a Group that has the name of the company, and give this group access (or not) to specific tables.

Django: access list of models belong of admin from admin console

I am sure this question has been asked before but I have not found anything regarding admin console.
The database relationship is as follows: Host can have multiple students but a student has only one host (one-to-many or many-to-one depends on how we look at the problem). Below is my model setup:
from django.db import models
# Create your models here.
class Student(models.Model):
host = models.ForeignKey("Host", blank=True, null=True)
fullname = models.CharField(max_length=255, blank=True, null=True)
major = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
country = models.CharField(max_length=255, blank=True, null=True)
interests = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
attendance = models.IntegerField(blank=True, null=True)
university = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = True
db_table = 'student'
class Host(models.Model):
host_id = models.AutoField(primary_key=True)
fullname = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
address = models.CharField(max_length=255, blank=True, null=True)
max_guests = models.IntegerField(default=5, blank=True, null=True)
preference = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = True
db_table = 'person'
I can access host of a student by using .host (e.g. Student.objects.first().host) and also from a dropdown in django admin console. I can also access a list of students of a particular host like this:
list_of_students_of_first_host = Student.objects.filter(host_id=Host.objects.first().host_id)
But I cannot see from admin console list of students of a particular host. How to accomplish this if it is even possible. Any help would be appreciated.
a django admin inline will let you display all the Students associated with a Host in the Host's admin page
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.TabularInline

model design for considering multiple work schedule with number

I am trying to create convincing job hiring model. However I got stuck to show the conditions like 3 Full Time, 2 Part Time in a single job. For example, a company may post job for senior backend developer with job description and all where he may select both Full Time and Part Time work schedule. Probably he want to state how many Full Time and Part Time employer for that job. That is why I am using ManyToManyField for work schedule but I am not sure for the numbers of employeer for certain workschedule in an efficient manner.
Here is the model design that I have designed for now
class Category(models.Model):
name = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=50, unique=True)
description = models.CharField(max_length=400, blank=True, null=True)
class WorkSchedule(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
slug = models.SlugField(max_length=50, unique=True)
class Position(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
slug = models.SlugField(max_length=50, unique=True)
class Job(models.Model):
company = models.ForeignKey(
Company, related_name='jobs', on_delete=models.CASCADE)
job_title = models.CharField(max_length=200, blank=True, null=True)
category = models.ForeignKey(Category, related_name='jobs')
description = models.TextField(blank=False, null=False)
city = models.CharField(max_length=100, blank=False, null=False)
position = models.ManyToManyField(
Position, related_name='jobs', blank=False, null=False)
work_schedule = models.ManyToManyField(
WorkSchedule, related_name='jobs', blank=False, null=False)

Make a form from models using ModelForm, Models have many Foreignkeys( one class is the foreign key for the other.)

I wanted to make a form which should be showing all the fields defined in models, wether the fields include a foreign key to some other class in the models. I am using ModelForm to generate forms.
My models look like
class Employee(Person):
nickname = models.CharField(_('nickname'), max_length=25, null=True,
blank=True)
blood_type = models.CharField(_('blood group'), max_length=3, null=True,
blank=True, choices=BLOOD_TYPE_CHOICES)
marital_status = models.CharField(_('marital status'), max_length=1,
null=True, blank=True, choices=MARITAL_STATUS_CHOICES)
nationality = CountryField(_('nationality'), default='IN', null=True,
blank=True)
about = models.TextField(_('about'), blank=True, null=True)
dependent = models.ManyToManyField(Dependent,
through='DependentRelationship')
pan_card_number = models.CharField(_('PAN card number'), max_length=50,
blank=True, null=True)
policy_number = models.CharField(_('policy number'), max_length=50,
null=True, blank=True)
# code specific details
user = models.OneToOneField(User, blank=True, null=True,
verbose_name=_('user'))
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('last modified'), auto_now=True)
#models.permalink
def get_absolute_url(self):
return ('contacts_employee_detail', [str(self.id)])
class Person(models.Model):
"""Person model"""
title = models.CharField(_('title'), max_length=20, null=True, blank=True)
first_name = models.CharField(_('first name'), max_length=100)
middle_name = models.CharField(_('middle name'), max_length=100, null=True,
blank=True)
last_name = models.CharField(_('last name'), max_length=100, null=True,
blank=True)
suffix = models.CharField(_('suffix'), max_length=20, null=True,
blank=True)
slug = models.SlugField(_('slug'), max_length=50, unique=True)
phone_number = generic.GenericRelation('PhoneNumber')
email_address = generic.GenericRelation('EmailAddress')
address = generic.GenericRelation('Address')
date_of_birth = models.DateField(_('date of birth'), null=True, blank=True)
gender = models.CharField(_('gender'), max_length=1, null=True,
blank=True, choices=GENDER_CHOICES)
class Address(models.Model):
"""Street Address model"""
TYPE_CHOICES = (
('c', _('correspondence address')),
('p', _('present address')),
('m', _('permanent address')),
)
address_type = models.CharField(_('address type'), max_length=1,
choices=TYPE_CHOICES)
content_type = models.ForeignKey(ContentType,
limit_choices_to={'app_label': 'contacts'})
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
street = models.TextField(_('street'), blank=True, null=True)
city = models.CharField(_('city'), max_length=200, blank=True, null=True)
province = models.CharField(_('State/UT'), max_length=200, blank=True,
null=True)
post_code = models.CharField(_('postal code'), max_length=15, blank=True,
null=True)
country = CountryField(_('country'), default='IN')
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('date modified'), auto_now=True)
So please if anyone could help me out, or suggest me some useful links from where i can get some help. Thank You!!!
Here is the documentation...
Basic usage is:
class EmployeeForm(ModelForm):
class Meta:
model = Employee
fields = ('somefield','otherfield')
etc...
fields is a optional argument, used for defining witch fields will be presented on the form... You can also override some fields using the following
class EmployeeForm(ModelForm):
otherfield = forms.CharField(...)
class Meta:
model = Employee
fields = ('somefield','otherfield')
That means, Your form is created from Employee model, "somefield" and "otherfield" will be added as form fields, and somefield will be populated directly from your model, but otherfield will be defined as if you override it in the form class...
EDIT: Overriding is used for small changes, so ,it is not right to change the data type of the field... As far as you gave the field same name, there is no problem, it will match the related model field using the name of the form field... So:
class SomeModel(Model):
somefield = CharField()
class SomeForm(ModelForm):
somefield = Charfield(Widget=...)
class Meta:
model = SomeModel
Since field names are equivalent, there is no problem...
Basic reason for overriding is, you may wish to use a widget to change the appearance of the form field(making a TextField looks like a single line Charfield) or pass some attributes (like defining cols and rows of a text field, or addng a simlpe datepicker to a datetime field. Or you may wish to use choices parameter to populate a field with value-label pairs...
You must aviod any kind of data-based changes, if you do, you might get a database level error.

Categories

Resources