Most convenient way to get related object in Django - django

I need to render different templates for logged in user depending on its "type":
I have a custom User called Users to store the general fields, and three different user types, called Admins, Publishers and Copywriters, linked to the Users table with One-To-One relation
class Users(AbstractUser):
# fields
class Admins(models.Model):
user = models.OneToOneField(Users, on_delete=models.CASCADE)
# extra fields for admins...
class Publishers(models.Model):
user = models.OneToOneField(Users, on_delete=models.CASCADE)
# extra fields for publishers...
class Copywriters(models.Model):
user = models.OneToOneField(Users, on_delete=models.CASCADE)
# extra fields for copywriters...
Which is the most convenient way tho retrieve the related fields of the logged user? Or in other words, how can i retrieve the admins or publishers or copywriters object related to the logged user?
My original idea was to add a column in the Users table called user_type but it seems to me a redundant field since there's a One-To-One relation

Related

django ManyToManyField unique

class Building(models.Model):
address = models.CharField(max_length=20, primary_key=True)
employers = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name="employers",
blank=True)
Suppose n users of model type User and m buildings of model type Building (m << n). I would like in the Admin page to be able to put users into building in the unique way:
a user can be in maximum one building.
a building can have many employers. It can be empty too.
in the Admin page, in the Employers selection widget, in the UPDATE
mode, exclude users that belong to another building. In the CREATE
mode, show only users without a building.
Stack: Django, MySQL.
So, basically you need inside User model one field with Foreign key relationship with Building and you can query it with related name.
example:
class User(AbstractUser):
"""
Your user model
"""
building = models.ForeignKey(Building, related_name='building_employers', on_delete...)
...
Later you can query employers with building_object.building_employers.all()
For question number 3, please check:
https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#django.contrib.admin.TabularInline

Different model field requirements for superuser vs normal user? django

Example(not true example):
I want the superusers to have to save on register their username and email.
and the normal users to save username, email, and a number(unique=True).
I wanted to use the user models django has, but I don't see how when the number has to be unique? or rather I originally wanted it to be the primary key, but only for normal users. Do I have to manually make two different user classes along with the permissions, authentication etc.? or is there separate user models for admin/user in django?
I tried(as a complete amateur, new to oop and django)... after gave up on using it as primary key, bc AbstractUser is fly.
Tried with onetoonefield, but couldn't make a combined form with UserCreationForm, bc "too many fields error". Also weird to have an important part of the user table be in a different table (or is it?).
something like (not 100% accurate):
#in models.py
class AdminUser(AbstractUser):
username
email
class NormalUser():
ontoonefield(AdminUser)
number(unique=True)
#in forms.py
class NormalUserForm(UserCreationForm):
class meta:
fields
class onetoonefieldForm(NormalUserForm):
class meta:
add_field += (number)
tried playing with required_fields, but again... number is unique
tried making two abstractUsers... permissions errors
thought about just making it non-unique and just checking on db insert that it's unique, but that seemed like a risk to the database, when it's vital it's unique.
Thank you for listening:)
Have a great day
Do I have to manually make two different user classes along with the permissions, authentication etc.? or is there separate user models for admin/user in django?
Django uses one built in User model and distinguishes three types of users using the attributes is_staff and is_superuser.
Normal user: is_staff=False, is_superuser=False
Staff user (can access the admin interface): is_staff=True
Super user (can do everything): is_superuser=True
If the default user model does not work for you, you can extend it or replace it.
Having the user decide their primary key, is not the intended default. The primary key is usually decided by the database, which also handles the uniqueness. If you would like to assign a unique number to each user, such as a customer number, I suppose it is easiest to extend the user model with a user profile.

Django Multiple Users can view single model object

How to define a condition where we can set multiple users access for that single model object.
Let's suppose we have the following model.
class Project(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
name = models.TextField()
And i have 2 users: admin and jobert
Since user field in above model is single one to one field which means either admin or jobert are saving that object.
if that object created by admin then jobert can't see that object and vice-versa for jobert.
How do i made that user field to accept or allow multiple users to access that object. i want adminand jobert users to access that model object.

Identify type of logged in user

I have a custom user setup like this:
class CustomUser(AbstractUser):
pass
class Employee(CustomUser):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
# other fields
In settings.py, I then add the following key:
AUTH_USER_MODEL = 'myapp.CustomUser'
I want to identify who logged in redirect them to appropriate views or urls.
In my account activation view, after the logging them in I redirect them to their appropriate page like this
if hasattr(user, 'employee'):
return redirect('edit_employee', slug=user.employee.slug)
else:
return redirect('index')
But this doesn't feel that right as I need to use this in other places like showing a different profile page link in the templates.
How do I better identify the regular user and employee in views and templates?
AFAIK you should not store different types of users in different tables. It will make your life pretty hard when defining relationships between other models and your users model.
My suggested approach would be having different profile models for different types of users and using a generic FK or some sort of other similar approaches to find out the user type and get their profile.
class CustomUser(AbstractUser):
USER_TYPE_EMPLOYEE = 'employee'
USER_TYPES = (
(USER_TYPE_EMPLOYEE, _('Employee')),
)
user_type = models.CharField(max_length=max(map(len, map(operator.itemgetter(0), CustomUser.USER_TYPES))), choices=CustomUser.USER_TPYES)
#property
def profile_model(self):
return {
USER_TYPE_EMPLOYEE: EmployeeProfile
}[self.user_type]
#property
def profile(self):
return self.profile_model.objects.get_or_create(user_id=self.pk)
class EmployeeProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='employee_profile')
The idea of extending the User Model to create an Employee Model doesn't seem good to me. Instead of this, you can use Django Group Model and add the user to the employee group. In this way, you can easily check if a user belongs to Employee group or not.
Additionally, you can also use django permissions here.
Assign your custom permissions to the employee group and restrict other users to view employee pages.

Django: model.ForeignKey referring to field type

I try to build a model, e.g. Userprofile, in which fields will be chosen in the admin panel.
class UserProfile(models.Model):
user = models.OneToOneField(User)
regfield = models.ForeignKey(Regfields)
This model refers to a second model Regfields:
class Regfields(models.Model):
field_name = models.CharField(max_length = 256, unique=True, blank=False)
field_type = models.ForeignKey(FOREIGNKEY_TO_DATATYPES)
I want to choose the Fieldname and the Fieldtype (e.g. Char_field ...) to use this in a second model Userprofile, to refer to the field names and field types in the Regfields model. What is the best approach to realize this?
Edit:
I don't seek to have a kind of dynamic database for the user profile. I think I could achive something like this by using a "static" choice list, e.g.:
FIELD_TYPE_CHOICES = (
(BigIntegerField,'Long Int'),
(BooleanField,'Boolean'),
(CharField,'Char'),
...
)
field_type = models.CharField(max_length=20, choices=FIELD_TYPE_CHOICES, default=CharField)
However, this way I can have the required registration fields to be choosen from a given set, but I only get the fieldtypes as strings, which in turn might lead to complicated data validation.
Example of what i try to achive:
In the admin panel I want the admin to have they choice what kind of data is required (additionally to username and password) at the registration page. The admin might like to ask for (username, password and email) but might also ask for (username, password, email, first_name, last_name, company, department)
Allowing users to customize forms via forms is not that simple, and will probably drag you into more non standard problems... How about trying out a ready made django package that helps building forms?
https://www.djangopackages.com/grids/g/form-builder/