Django: Including standard User table as foreign key in my models? - python

I am designing a Django 1.8 application in which I have the concept of trials and assessors. I will have six assessors, who will use the Django admin to log in and make assessments.
I want each trial to have two attached assessors. How can I use the Django User model in models.py to ensure that the assessors are Users, and can be managed using the full power of Users?
Right now I have this, in which the assessors are not Users, but are just ordinary models:
class Assessor(models.Model):
name = models.CharField(max_length=200)
class Trial(models.Model):
title = models.CharField(max_length=800)
publication_date = models.DateField()
first_assessor = models.ForeignKey(assessor)
second_assessor = models.ForeignKey(assessor)
I want the assessors to be Users, so that I can manage them in the usual way through the User tables, but I don't know how to make this change.
They probably don't need any custom fields on top of the standard User attributes.
(NB: I don't need full-on permissions management within the admin, it's OK for any assessor to be able to edit the trial.)
UPDATE: Apologies, this is rather hard to explain! I don't care about the Django front-end at all, only the admin. I want a user to be able to log into the admin, see all the trials on which they are a primary assessor, and edit those trials. I'm not sure if it's best to do this with the User model, or not.

Instead of two foreign keys add a manytomany relation from Trail to user. Later, if you want you can add more assessors to a trail.
You can do like:
from django.contrib.auth.models import User
class Trial(models.Model):
title = models.CharField(max_length=800)
publication_date = models.DateField()
assessors = models.ManyToManyField(User,related_name="trials")
You can add assessors to Trial like:
trial = Trial.objects.get(id=give-trial-id)
user = User.objects.get(id=give-assessor-id)
trail.assessors.add(user)
You can get more info about manytomany here
I just saw your UPDATE. Any one who logs in to admin will have access to all objects of all models.
In your case all assessors who login to admin will have access to all trails irrespective of they are assigned to it or not.
If you want Filter django admin by logged in user then refer this question

Related

Updating user information from separate model Django

I'm creating a simple weight management application where users can register, login and update information such as weight, body measurements etc. I've not used Django for a little while and slowly learning best practices from where i left off a little while ago.
I'm using the django-allauth to manage the user registration as this allows people to login with Facebook etc.
I've created a simple app called 'Stats' with a ForignKey to the Users.
class Stat(models.Model):
user = models.ForeignKey(User, default=False)
height = models.CharField(max_length=20)
weight = models.CharField(max_length=20)
waist = models.CharField(max_length=20)
hips = models.CharField(max_length=20)
upperleg = models.CharField(max_length=20)
upperleg = models.CharField(max_length=20)
calf = models.CharField(max_length=20)
bodyfat = models.CharField(max_length=20)
What i would like the user to be able to do is login and update stats on a daily / weekly basis. Then to be able review previous stats. This will probably be done via a model form based on the above approach. I will add more complexity as time goes on.
Is there another way to do that would have any advantages? If the best approach is the best? Is there a way i can list all the objects from that model inside the users page in the admin to be able to reviews users stats easily enough?
Thanks in advance.
It is recommended that you create a separate user profile model for app-specific functionality that relates to a User of your app. It's best to create a UserProfile model which has a OneToOneField link to User object. Then, your Stat model can ForeignKey to UserProfile instead of User. This is to provide abstraction to the User object and give flexibility if you decide to create another Django app in the same project that requires different specifications for the user. Also, with UserProfile you can add customised fields that are app specific.
Another thing you can do to improve this modelling is create separate entities for each stat. For example, HeightWeightStat, WaistStat. But, this is not completely necessary and totally depends on your preference.
To display all of the user related Stat instances in the admin page, use Django Admin inlines: https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#inlinemodeladmin-objects

User roles schema on Django

A great greetings community
My question is related with the kind of manage users and the schema users in Django, In beginning I ask to you apologize just in case that my questions can will be too "newbies" or without sense, I am starting to related me with the Django Users schemas and their different possibilities of work in the projects.
I have the following situation.
I am building an application in which I will have three differents user types:
Medical
Patient
Physiotherapist
I am using the default Django authentication scheme (django.contrib.auth).
Initially, I did think in this scheme of entities in which the User table is the auth_user table in where Django save the users created:
I have the is_patient, is_medical and is_physiotherapist fields like boolean attributes in the User table.
Like a particular detail I understand that in the Django default model User is not possible modify or add attributes or fields.
This is an important and powerful reason to I cannot add the is_patient, is_medical and is_physiotherapist boolean fields in User table.
A classic recommendation is extend the User model with a Userprofile table in which I add fields or attributes to User Model through of OneToOne relationship. A basic sample is such as follow:
Is of this way that I get that my users in Django can have the field photo and upload one in a given moment ...
Taking advantage of the previous,
The following schema can be suited or can be an alternative for manage user roles (patient, medical and physiotherapist user types) ?
I will have relationships between:
User medical and user patients
user physiotherapist and user patients
and so between them and other tables ...
With this approach these relationships don't will be affected?
The different users will be saved between the Users and UserProfile table.
Is this a good practice in the scalability sense? My tables could be crash or my database?
In addition, I also have seen other alternatives such as:
Role Table/Model
I will have a role table/model independent or separate and that this can be related with the Django User model (One User can will have many roles by example)
This approach can be useful when I want store exclusive information about of a role in specia?
Django Permissions and Authorization
I ignore or unknown the granularity grade that let will me work. Of a single way I have been see that the permissions and authorizations system let will me work with create and edit and remove operations ....
Here, can I see the groups creation?
For example a medical group and allocate them permissions and linked this permissions to the users that compose the group ? Is this another good alternative?
This option seem more single although I don't know if an user could make some operations according to the group privileges that have ... I don't know if this thinking is correct/right
AUTH_USER_MODEL Creating a Custom User model
My requirements for patient, medical and physiotherapist users, require build a custom user model?
In this situation, especially if you want to store different infos for Patients, Medics and Physiotherapists you can create a Model for each and have a OneToOne field for each to the User model.
class Medic(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
class Physio(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
class Patient(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
This way you can give different permissions/roles implicitly in your application logic for each type of user (and still use the groups and permissions that Django offers if you need them for special cases, eg ChiefMedical...).
You will have to define some methods for your application logic like
def user_is_patient(user):
...
If you follow this path it is a good idea to have good tests to make sure that you don't get unexpected things like a user who is a Medic and a Physio...
Django lets you subclass the user model as well. Under the covers it would do the same thing as the code above, so it is probably better to do it explicitly as shown above (this way it is less probable that you access attributes that don't exist in that object!)
Taking advantage of the previous, The following schema can be suited or can be an alternative for manage user roles (patient, medical and physiotherapist user types) ?
The schema you show isn't great because it makes you store the information for all user types in the same table (and with the same fields). For example, Medics and Physios will have a blood type field type like Patients which will probably not be defined.
The different users will be saved between the Users and UserProfile table. Is this a good practice in the scalability sense? My tables could be crash or my database?
There should be no scalability problems with this solution (as long as you don't have millions new entries writes every day) and you can always optimise the database at a further point. However, you will have to make sure that your app doesn't accept 'forbidden' entries (e.g. users with no Medic, Physio or Patient profile)
Here, can I see the groups creation? For example a medical group and allocate them permissions and linked this permissions to the users that compose the group ? Is this another good alternative? This option seem more single although I don't know if an user could make some operations according to the group privileges that have ... I don't know if this thinking is correct/right
You can (should) use Django's permission system to give permissions to your users. You can use them to give different rights to users of the same type (for example Medics that have more permissions than others... or have groups for chief physios...)
Django lets you assign permissions to a group.
But I don't think groups can replace the custom models for each user, since you want to store information for them. Having custom models and groups would be redundant and make your app harder to maintain.
My requirements for patient, medical and physiotherapist users, require build a custom user model?
This option wouldn't be great (unless it is your only option) because your app won't be reusable and you might have problems with some packages as well.
You can create a custom User model or not, in any case, you could have three separate models for storing pertinent data, depending on whether the user is patient, medical, physiotherapist, or any combination of these.
If your permissions scheme is determined solely by the role (patient, medical, physiotherapist) then you don't need to use Django's permissions system, because you know the role(s) of any user and you can, in the worst scenario, hardcode authorization rules.
I gave a glance at question's comments and I view some issues:
()
I realized that your user model does not match with the original data model since having get_medical_profile, get_patient_profile and get_physiotherapist_profile functions inside user model, with that you are assuming that any user could have multiple profiles at the same time, which isn't reflected neither in your profile models (Medical, Patient and Physiotherapist) using OneToOneField nor in original data model of the question, it's an important thing about abstraction and class-responsibility. The requirement (according the model below) seems to say "one user can have only one profile".
So.. I think this can be solved in a straightforward and clean way, you don't need to involve in overall authentication esquema like groups and permissions or adding additional attributes to user model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
# common fields shared by medical, patient and physiotherapist profiles
class MedicalUser(models.Model):
profile = models.OneToOneField(UserProfile)
# medical fields here
class PatientUser(models.Model):
profile = models.OneToOneField(UserProfile)
# patient fields here
class PhysiotherapistUser(models.Model):
profile = models.ForeignKey(UserProfile)
# patient fields here
As you see, you can have a profile which contains common fields shared by all profiles. and each profile has an specific model.
In addition, you can check if user is medical by this small function below, then if there is no an medical profile associated with profile then it will raise exception and it means it's a profile unspecified:
def is_medical_profile(profile):
try:
profile.medical_user
return True
except:
return False
You can also use it in your templates (as a custom template tag) in this way:
{% if profile | is_medical_profile %}
With this approach you don't need to setup AUTH_USER_MODEL
I hope this improves your solution.
Additional notes:
Just in case you decide to have a custom user model, setup settings.AUTH_USER_MODEL and use it for foreign keys to User.
On a piece of text of awesome book Two scoops of Django says:
From Django 1.5 onwards, the official preferred way to attach
ForeignKey, OneToOneField, or ManyToManyField to User
Therefore, your user profile model would change as follows:
from django.conf import settings
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
Yes, it looks a bit strange, but that's what the official Django docs advice.
#geoom #Ire #lorenzo-peña I 've created an user through Django admin site and I checked their attributes (is_medical, is_patient, is_physiotherapist) via python shell
In [6]: User.objects.filter(username='agarcial').values('is_medical','is_patient','is_physiotherapist')
Out[6]: [{'is_physiotherapist': True, 'is_patient': True, 'is_medical': True}]
For the moment in my views.py I am doing that an user sign in only when this be one of three user types (medical, patient or physiotherapist)
# Create your views here.
class ProfileView(LoginRequiredMixin, TemplateView):
template_name = 'profile.html'
def get_context_data(self, **kwargs):
self.request.session['Hi'] = True
context = super(ProfileView, self).get_context_data(**kwargs)
is_auth = False
name = None
# Check if in the request goes the user
user = self.request.user
# Check about of possible cases (For now is one profile)
if user.is_medical:
#if self.request.user.is_authenticated():
print (user.is_medical)
is_auth = True
profile=user.get_medical_profile()
#name = self.request.user.username
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile, 'data':data})
elif user.is_patient:
print (user.is_patient)
is_auth=True
profile=user.get_patient_profile()
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile,'data':data})
elif user.is_physiotherapist:
print (user.is_physiotherapist)
is_auth=True
profile=user.get_physiotherapist_profile()
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile,'data':data})
return context
def get_userprofile(self):
return self.request.user.userprofile
If I check the other possible combinations (User patient,medical and physiotherapist) this could work?
I think create groups for (Medicals, Patients, Physiotherapists) and binding users for the authorization topic, although I should review other things for authorization process such as django guardian for example?
How about this?

django best approach for creating multiple type users

I want to create multiple users in django. I want to know which method will be the best..
class Teachers(models.Model):
user = models.ForeignKey(User)
is_teacher = models.BooleanField(default=True)
.......
or should I use..
class Teacher(User):
is_teacher = models.BooleanField(default=True)
.......
or I have to make custom user model...
Which will be good on creating multiple type users...??
Django doesn't have multiple users - it only has one user and then based on permissions users can do different things.
So, to start off with - there is only one user type in django. If you use the default authentication framework, the model for this user is called User, from django.contrib.auth.models.
If you want to customize user behavior in django, there are three things you can do:
Customize how you authenticate them. By default, authentication is done using a database where passwords are stored. You can authenticate against facebook/google etc. or against your existing user database - for example, with ActiveDirectory if you are on a Windows network.
Create custom permissions, and based on these permissions, restrict what functions users can execute. By default, on every model - django will add basic permissions "can edit", "can delete", "can read". You can create your own and then check if the user has these specific permissions.
You can store extra information about the user, along with whatever normally is stored by django. There are two ways to do this, depending on how much customization you need. If everything django provides by default works for you, and all you want to do is store extra information about the user you can extend the user model - in previous versions this was called creating a custom profile. The other option you have is to create your own User model, if you want deeper customization. The most common use of a custom user model is if you want to use an email address as the username.
You don't have to do all three, in fact sometimes all you want to do is store some extra information or have them authenticate using their email address; in some applications you have to modify all three places.
In your case, since all you want to do is store extra information about a user, you would need to extend the user model, by creating a model that references User (note: you don't inherit from User):
class Profile(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=200, default='Computer Science')
is_teacher = models.BooleanField(default=False)
is_student = models.BooleanField(default=True)
# .. etc. etc.
One approach I was following with Django 1.7 (works with 1.6 too) is to subclass AbstractUser
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
balance = models.DecimalField(default=0.0, decimal_places=2, max_digits=5)
To use your model you need to set it to be the one used for authentication in settings.py:
AUTH_USER_MODEL = 'your_app.User'
Also note that you will now have to use settings.AUTH_USER_MODEL when referencing
your new User model in a relation in your models.
from django.db import models
from django.conf import settings
class Transaction(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL) # ForeignKey(User) will not work

get user profile in django

hello i'm new in python and django
I need a view that get current user profile I know I shoud use get_profile from User but I don't know how to use it . i read the django document and It didn't help me.
this is what I found from doc:
from django.contrib.auth.models import User
profile=request.user.get_profile()
Django's documentation says it all, specifically the part Storing additional information about users. First you need to define a model somewhere in your models.py with fields for the additional information of the user:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
Then, you need to indicate that this model (UserProfile) is the user profile by setting AUTH_PROFILE_MODULE inside your settings.py:
settings.py
...
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
...
You need to replace accounts with the name of your app. Finally, you want to create a profile every time a User instance is created by registering a post_save handler, this way every time you create a user Django will create his profile too:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Accessing the Profile
To access the current user's profile in your view, just use the User instance provided by the request, and call get_profile on it:
def your_view(request):
profile = request.user.get_profile()
...
# Your code
Basically django User models will provide access only for the fields ( firstname,lastname,email,password,is_staff,is_active,last_login).
However if we want to add any extra fields to this model, say we need to add a new column named dateofbirth for every user, then we need to add a column named DOB into User model. But this is not possible as we aren't able to edit django User models.
To achieve this either
1.We can have a separate new table with email id & DOB column, such that a column in User model is mapped with a column in the new table. But this will create a new db instance for every db request. Say if u want to find the DOB of a customer,
First we need to fetch the value of mapped id of a customer from the
User table.
WIth the above value, get DOB from the new table.
In the second method,
Instead of using django User model, use your own customize model with all the fields needed. However if any updation related to security or some enhancement made to django User model we can't use it directly. We need to do more code changes at our end( wherever we use our customize models.) This will be a bit pain for a developer to identify the code & make changes.
To overcome the above issues, django introduce django profile which is very simple and more flexible. The advantages are
Updation/enhancement to the User model can be applied without modifying the code much
No need of creating new db instance to fetch the extra values.
Since the field has onetoone mapping deletion of data from one table will delete others also.
More secure, since we use django models ( no sql injection)
How to Use this:
In settings.py create a variable AUTH_PROFILE_MODULE = "appname.profiletable"
In models.py, create a new table with the fields needed and make sure that the id in User model is onetoone mapped with new table.
create a signal which inserts a row into the new table whenever a new entry is added into User model.
The value in the new table can be accessed using User object itself.
Say, we created a new table extrauser which has DOB, emailid. To find the DOB of a customer, use
a=User.objects.get(email='x#x.xom')
a.get_profile().DOB will give the dateofbirth value from extrauser table.
Hope the above details make you clear in understanding django profile. Incase of any help further, let me know. I have used django profile in my project.
Old question but I thought anyone seeing it today may benefit from this:
Django 1.5 adds the ability to - easily - extend the User model. This may be preferable as you now only got one object to deal with rather than two! Seems the more modern way.
https://hurricanelabs.com/blog/django-user-models/
You need to specify which class is your "Profile" by setting AUTH_PROFILE_MODULE = 'accounts.UserProfile' (for example)
https://docs.djangoproject.com/en/1.4/topics/auth/

Referencing Django login name from within a model

I'll start by saying that my database skills are weak, and it's quite possible I'm just designing this wrong.
I'm working on a Django 1.3 application that would allow customers to log in to view various aspects of their "account". One of the models is "Customer", and it makes sense to me that I add a field in that model for "username" so that I can show projects, payments etc that belong to each customer.
I've got much of my schema set up but I can't figure out how to make a "username" field that references the django login name. You average field looks something like
projects = models.ManyToManyField('Project')
website = models.URLField()
updates to clarify
what I think I need is:
username = models.ForeignKey(WhereverDjangoKeepsTheUserModel)
SOLVED
I needed
from django.contrib.auth.models import User
and
username = models.ForeignKey(User)
Accepting Jack M's answer because it helped me find the specific piece I needed.
You are probably looking for a ForeignKey relationship.
projects = models.ManyToManyField('Project')
website = models.URLField()
user = models.ForeignKey('User')
Then from within your view:
project = Project.objects.all()[0]
username = project.user.username ## Or whatever you want to do with it.
To read more about this, check out the "Your First Model" section in chapter 5 of The Django Book.

Categories

Resources