I created a model ExtendedUser to extend the User Django built-in model class using the approach described in the official documentation:
https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#extending-the-existing-user-model
so that I can benefit from the existing authentication features provided by Django.
That works all fine however I wonder now, whenever I want to create a new ExtendedUser, that means for every ExtendedUser, I also need to create an original User to fullfill the one-to-one relationship?
Or what else does it mean the following:
Assuming an existing Employee Fred Smith who has both a User and Employee model, you can access the related information using Django’s
standard related model conventions[...]
In a script to create objects, would this mean the following:
u1 = User.objects.create_user(username="u_1", email="u_1#abc.com", password="pw_u_1")
ext_u_1 = ExtendedUser.objects.create(id=u1.id, user=u1, prop_1="XYZ")
where
class ExtendedUser(models.Model):
user = models.OneToOneField(User, ...)
# More properties...
Yes, if you extend using OneToOne field, it will require to create both objects i.e. User as well as ExtendedUser to fulfil the one to one relationship.
But I would suggest to not use OneToOne field instead override the AbstractUser model provided by Django to create the ExtendedUserModel, even if you don't need anything extra in ExtendedUserModel now. It will help you to add any new fields, methods easily to your user model in future as well as you won't be needed to create two object for a single User.
Same has been suggested in Django docs as well. Reference:- https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
Related
I'm starting a whole new project using Django 2.0 and python, so I'm at the beginning of deciding how to implement the Multiple User Types.
What I've read so far is that I can extend the User built-in model for django so that I would get use of django's authentication process, and create another models that links one-to-one with that user model. But actually I can't understand a little bit.
My application has three user types: Participant, Admin, Judge, each of them will view certain pages(templates) and as well as permissions.
Can someone provide me with the best practice/approach to start working on those user types.
Note: In the future, each user may have different fields than the other, for ex. Judge may have Join date while participant won't...etc
If you haven't already, the documentation seems to mention what you are trying to do.
Here is an example which creates custom user models. But I think you are essentially right. You can create an abstract base user with the standard information (name, email, etc). Then you can create a separate class which is just a model class, then set a foreign key to your abstract base user, and add additional data for that user.
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
# etc
class Judge(models.Model):
user = models.ForeignKey(User)
# User specific data
Hope this helps.
I'm creating an app in Django and so far I have been using an extended user model like so:
class MyUser(AbstractBaseUser):
...
with all the user and profile info, but I see a lot of people creating different models for the profile and the user itself on stack overflow, using OneToOneField, although those are mostly old questions.
My question is: which is better and, if there isn't a best among them, what are the advantages for each solution?
thanks!
It depends on what you want to do -- if you're happy with the User model as it stands in the latest version of Django you should just use that -- it's easy and you'll get a lot functionality that goes along with it -- for example a pretty good permission system, and you can be sure to be compatible with all third party modules. But if you thing you'll need to expand on the User model, it's pretty straightforward how to do it. You might find that in the future you need to add more methods to your model than you expected.
The examples that you see with separate UserProfile / User model are mostly a legacy of django < 1.5, where that was the recommended way to extend the User model. There's no reason to follow that pattern any more -- it's a lot more work to have to use two models where you just want one model
**2019 Update**
If you are starting a new Django project, you should always create your own custom user model that inherits from AbstractUser, as per the Django documentation, i.e.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
even if you don't need any additional functionality. The reason for this is that for very low effort, you are making it easy to customize your user object in the future. It's very laborious to replace the built-in User object with your own after you have run the initial migrations, unless you're able to delete all of your data and migrations and start over.
I find some useful information in Django docs:
Extending Django’s default User¶
If you’re entirely happy with Django’s User model and you just want to
add some additional profile information, you could simply subclass
django.contrib.auth.models.AbstractUser and add your custom profile
fields, although we’d recommend a separate model as described in the
“Model design considerations” note of Specifying a custom User model.
AbstractUser provides the full implementation of the default User as
an abstract model.
And:
Model design considerations
Think carefully before handling information not directly related to
authentication in your custom User Model.
It may be better to store app-specific user information in a model
that has a relation with the User model. That allows each app to
specify its own user data requirements without risking conflicts with
other apps. On the other hand, queries to retrieve this related
information will involve a database join, which may have an effect on
performance.
So if I reads it correctly, it means if the fields are related to authentication, then you should consider substitute the original User model. But if it's not related, like profile fields, such birthday, or profile_image, then you might want to create a standalone app that reference the original User model.
And a good tutorial I found: http://riceball.com/d/content/django-18-tutoria-52-adding-user-profile
A ForeignKey is to create a one-to-many relationship. In other words, it will return a queryset. For example, a single car has many wheels, but one wheel isn't attached to several different cars.
A OneToOneField will create a relationship between strictly two objects. For example, the rim belongs to the front-left tire, and only that tire has that rim.
Does that make sense?
In Django you have some naturally defined User class. My app also has a User class defined (they dont conflict, that's not the question)
My question is, since these two User classes conceptually represent the same thing (well, users) then it would be natural to integrate them. That is, have a single User class that contains all methods and variables of both classes.
What is the best way to achieve this?
There are (at least) two possibilities:
1) Use the 'custom user' functionality of Django (since Django 1.5), or
2) Use a OneToOneField to the django.contrib.auth User from your own user class.
The first allows you to customize more, but you might get some problems if you try to use third-party-apps that are either not ready for custom users or need specific properties of the stock User. For example, Django Guardian doesn't work if you remove the User-Group relationship.
The second is less intrusive, but doesn't allow you to customize the existing fields of User. Also, you need to manually create the instance of your own user class at registration time.
You should read the documentation about Extending the existing User model.
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user. For example you might create an Employee (note: called MyUser below) model:
from django.contrib.auth.models import User
class MyUser(models.Model):
user = models.OneToOneField(User)
newfield1 = models.CharField(...)
AUTH_USER_MODEL = 'myapp.MyUser'
Django 1.5+ allows us to add custom fields to a User. I want to use this fact, but I don't necessarily know what is good practice. Here is a situation I am confused on how to handle the models.
Given the option to add fields to User, if a project only has one type of User, lets say a Student model, can I simply add student-specific fields to User? I am new to Django, but I believe the alternative would be to set up general User settings, and create a Student model, and a one-to-one unique field in it call user.
Should you ever expand a Django User's fields to mimic that of a model, even if the project is guaranteed only to have one type of user?
If you only have one type of user and are using Django 1.5+, I would recommend taking advantage of the new AbstractUser. Extending Django's default user
As an example where you want to add date of birth and favorite color:
#myusers/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class MyUser(AbstractUser):
dob = models.DateField()
favorite_color = models.CharField(max_length=32, default='Blue')
If you need more flexibility you can extend the AbstractBaseUser instead of AbstractUser, but for most basic cases you should only need AbstractUser.
Also note that in either case, you'll need to reference your user model by using settings.AUTH_USER_MODEL.
Using out example above and assuming the app it was defined in is called myusers:
#settings.py
AUTH_USER_MODEL = 'myusers.MyUser'
The method you mention of creating a Student model with a one-to-one field to the User model still works, but is not as clean (there are still cases where it makes sense if you have multiple kinds of users).
I don't normally like to reference books in answers, but I found that Two Scoops of Django's, Chapter 16 on the User model gave a much clearer explanation of where the different options are appropriate than the current version of the online Django docs. The book is overall a very useful intro to Django and was written based on 1.5. You'd have to buy the book or find someone who has it, though... (FYI: I don't get any money recommending this).
You could also take a look at this SO question/answer: https://stackoverflow.com/a/14104748/307293
You shouldn't touch the django contributed User model (from the authentication framework). This will break upgrades and you do not know what other consequences it might have.
There are two basic ways to do this:
If you just need to store additional information about a user, but don't need to change how the authentication/authorization mechanism works, create a model and add a OneToOneField to the User model. In this model, store any other miscellaneous information.
If you want to change how authentication works you can create your own User model and have django use that (1.5+ only).
I have a field Foo with a ForeignKey that points to User. I need to create filter in the admin that only displays User that have at least one Foo. This would be easy with the development version of Django, but I am stuck with the 1.3.
I have seen here how to add a custom filter using the undocumented FilterSpec class. My problem is that it requires to modify the User model. I could inherit from User, but I already ave a setup where additional data is put into a Profile model wiith a one-to.one link to User.
Is there a less intrusive way to add a custom filter to the User model?
You can actually use the foreign key relation backwards in an ORM query.
User.objects.filter(foo__isnull=False)