Extending the Django User model with inheritance
Update March 2013:
Django 1.5 includes a configurable custom user model that makes all this obsolete.
Extra fields for Users
Most of the Django projects I’ve worked on need to store information about each user in addition to the standard name and email address held by the contrib.auth.models.User
model.
The old way: User Profiles
The solution in the past was to create a “user profile” model which is associated 1-to-1 with the user. Something like:
the model
class UserProfile(models.Model): user = models.ForeignKey(User, unique=True, related_name='profile') timezone = models.CharField(max_length=50, default='Europe/London')
config in settings.py
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
usage
profile = request.user.get_profile() print profile.timezone
It works ok, but it’s an extra database query for each request that uses the profile (it’s cached during the request so each call to get_profile()
is not a query). Also, the information about the user is stored in two separate models, so you need to display and update fields from both the User
and the UserProfile
models.
The new way: Model Inheritance
As part of the great work done on the queryset-refactor by Malcolm et al, Django now has model inheritance.
If you’re using trunk as of revision 7477 (26th April 2008), your model classes can inherit from an existing model class. Additional fields are stored in a separate table which is linked to the table of the base model. When you retrieve your model, the query uses a join to get the fields from it and the base model.
Inheriting from User
Instead of creating a User Profile class, why don’t we inherit from the normal User
class and add some fields?
from django.contrib.auth.models import User, UserManager class CustomUser(User): """User with app settings.""" timezone = models.CharField(max_length=50, default='Europe/London') # Use UserManager to get the create_user method, etc. objects = UserManager()
Now each instance of CustomUser
will have the normal User
fields and methods, as well as our additional fields and methods. Pretty handy, no?
We add UserManager
as the default manager so that the standard methods are available. In particular, to create a user, we really want to say:
user = CustomUser.objects.create(...)
If we just created the user from the User
class, we wouldn’t get a row in the CustomUser
table. Creation needs to be done in the derived class.
You can still get and update the underlying User
model, no problem, but it won’t have the additional fields and methods found in our CustomUser
class.
Getting the CustomUser
class by default
So far, there’s one problem. When you get request.user
, it’s an instance of User
, not an instance of CustomUser
, so you don’t get the extra fields and methods.
What we want is for Django to retrieve the CustomUser
instance transparently. It turns out to be quite easy.
Users come from authentication backends
The default authentication backend gets the User
model from the database, checks the password is correct then returns the User
. You can write your own authentication backend, for example to check the username and password against some other data source or to use the email address instead of username.
In our case, we can use an authentication backend to return an instance of CustomUser
instead of User
.
the authentication backend in auth_backends.py
from django.conf import settings from django.contrib.auth.backends import ModelBackend from django.core.exceptions import ImproperlyConfigured from django.db.models import get_model class CustomUserModelBackend(ModelBackend): def authenticate(self, username=None, password=None): try: user = self.user_class.objects.get(username=username) if user.check_password(password): return user except self.user_class.DoesNotExist: return None def get_user(self, user_id): try: return self.user_class.objects.get(pk=user_id) except self.user_class.DoesNotExist: return None @property def user_class(self): if not hasattr(self, '_user_class'): self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 2)) if not self._user_class: raise ImproperlyConfigured('Could not get custom user model') return self._user_class
config in settings.py
AUTHENTICATION_BACKENDS = ( 'myproject.auth_backends.CustomUserModelBackend', ) ... CUSTOM_USER_MODEL = 'accounts.CustomUser'
That’s it. Now when you get request.user
, it’s an instance of the CustomUser
class with whatever additional fields or methods you have added.
P.S. Looking for Django hosting? I’d recommend WebFaction for shared hosting and Slicehost for a VPS.
this is beautiful.
Comment by Mogga — 21 August 2008 @ 9:16 pm
Instead of using a custom authentication backend a middleware could be used to replace contrib.auth’s one, i think it would be more simple. Nice example.
Comment by David Elias — 22 August 2008 @ 1:42 am
Since inheritance is implemented under the hood as a one-to-one relation, this doesn’t reduce the number of queries at all — accessing User fields from your subclass will do a query, and accessing subclass fields from a User will do a query.
Also, I *still* think this is the wrong way to go about it from a design perspective: http://www.b-list.org/weblog/2007/feb/20/about-model-subclassing/
Comment by James Bennett — 22 August 2008 @ 3:33 am
pretty easy for using the user model!
thanks
Comment by sean — 22 August 2008 @ 1:43 pm
I think I agree with James. Also, the get_profile() is almost a convention on pluggable apps already.
Comment by Eduardo Padoan — 22 August 2008 @ 7:55 pm
@David Elias
Using middleware sounds like a good idea.
@James Bennett
That’s not the behaviour I’m seeing in r8194. I’m seeing one query with an inner join when the model is retrieved, after which fields from both the base and subclass can be accessed without further queries. That’s one query, versus two queries for user + profile. Have I misunderstood you?
@Eduardo Padoan
What do the pluggable apps do with the profile? How do they know what fields it has? It’s an interesting point I hadn’t thought of.
Comment by Scott — 24 August 2008 @ 8:32 pm
I got everything modified, but had no luck getting my customuser to show up in the admin site. I’m just learning django while writing a web app, so I may be making too many assumptions. Should my customuser show up in the admin pages for users. It still looks like a user, not customuser.
Comment by Nik — 1 September 2008 @ 1:24 am
@Nik
Your CustomUser class can show up in admin as well as the User class. You just need to register it in the usual way. For example, if you have a CustomUser model, in the admin.py file you could have:
Or to set some display options:
If you don’t want User to show up in admin, you can unregister it, with something like this in your main urls.py file:
Comment by Scott — 1 September 2008 @ 9:43 am
Hello, Scott
i’ve tryed this example
——
from django.contrib import admin
from django.contrib.auth.models import User
admin.autodiscover()
admin.site.unregister(User)
——-
but get in return only exceptions like
Error while importing URLconf ‘MyProject.urls’: ‘module’ object has no attribute ‘site’
Comment by Vovk — 4 September 2008 @ 10:13 am
Hi,
What if I need *multiple* custom users, e.g., teachers, students, and staff members? Creating multiple subclasses is straightforward, obviously, but what about the authentication backend? How, for different types of users, do I plug the right class into ‘user_class’? Or, more generally, return an instance of the appropriate subclass
I’m a django newbie just trying to get this all figured out.
Thanks in advance!
Comment by Ed Hagen — 4 September 2008 @ 7:01 pm
2 Ed Hagen:
I’m in the exact situation as you described. I use another approach: create abstract base model with extra fields, common to all profiles, then derive each profile model from this base. Thus, you’ll have additional foreign keys in the Django’s User model, pointing back to your profiles. It’s up to your application logic to decide whether the user is allowed to have multiple profiles of different types or only the one. The here mentioned middleware (or backend) could check, for example, if user.teacher is not None: return user.teacher and so on. Personally, I’m not using inheritance from Django User (because my users can have profiles of different types simultaneously), but you could try it ;)
Here is sample code:
Each profile will have ‘user’ field:
In the Django User:
You could have as many profile types as you want :)
Comment by irium — 6 September 2008 @ 11:48 pm
I haven’t yet tried your solution but I think you saved my life.
In my app I made a “comments” app which allows users to comment some entities like News and other stuff. The problem is that I’m displaying, for each posted comment, the user’s avatar, which is part of its profile, which was fetched in a new SQL query for each comment. So I’m getting (comments_count) SQL queries executed, which is not a viable solution.
I think your solution will solve this problem and I thank you for that.
Comment by Sephi — 7 September 2008 @ 10:43 pm
@Vovk
Maybe you have an older version of Django.
admin.site
was added as part of the newforms-admin merge in r7967Comment by Scott — 13 September 2008 @ 8:52 pm
I’m going through a trial implementation on a branch of a site I’m developing. But I’ve run into a stumbling block. Basically, it does not seem to play well with the django-registration module. Have you tried integrating it with that module?
Comment by Paul — 19 September 2008 @ 5:53 pm
I must be missing something.. how is the table for CustomUser created?
–confused.
Comment by Mikael — 3 October 2008 @ 8:28 am
@Mikael
The table is created when you run
manage.py syncdb
. The same as the tables for any other model.If you used the
User
model, then you changed to use aCustomUser
model, theCustomUser
instances won’t automatically exist. You will need to manually create them in the database and make them point to the rows in theUser
table. When you create aCustomUser
instance in future, one row is inserted in the*_customuser
table and one in theauth_user
table.Comment by Scott — 3 October 2008 @ 9:28 am
Any Chance of getting a middleware example I’m stumped
Comment by Daniel Worth — 8 October 2008 @ 10:02 pm
@Daniel
If you have a look in the Django source in
contrib/auth/middleware.py
, you’ll see what it’s doing.I haven’t used it, but you could write a middleware function something like:
Then in your
settings.py
instead of the usual:You would have:
Hope this helps.
Comment by Scott — 9 October 2008 @ 9:49 am
@irium and @Scott
I was really tired yesterday and should have been specific.
The code example helps me understand middleware a little better. However here is the situation. The site needs to have a separate profile for male models, female models, stylists and photographers.
My plan is to implement it as suggested by irium so I can have multiple profiles.
My confusion is how to handle AUTH_PROFILE_MODULE = ?
and what would the middle ware need to look like?
Would a middleware separate from a new AuthenticationMiddleware be needed or is there something I’m missing in how profiles are being passed.
I’m reading code like a mad man but for some reason haven’t been able to wrap my head around it yet.
Comment by Daniel Worth — 9 October 2008 @ 3:43 pm
Hello Scott, thanks for an informative article.
I’m having some trouble, as I’m a django newb, first of all I have the feeling that new users created with the admin interface will not have entries created in the customuser table as well (although I hope I’m wrong on this one). Second I have some trouble creating new users from the shell. The reason for my modifications to the user model, is that I want to tie the users in to parts of my application model, not just add more metadata to each user. Currently when using the objects.create_user(username,email,pass) method, I get a database exception:
IntegrityError: (1048, “Column ‘customer_id’ cannot be null”)
Now in my models I’ve set up the following:
So the problem is obviously the fact that the UserManager can’t create the customuser table entries, because the customer_id foreign key field there can’t be null.
Now this is probably a complete newb question, but I’m wondering how I can overload the user creation so that when creating a new customuser I can pass along a customer to which it belongs?
Best,
Steinn E. Sigurðarson
Comment by Steinn — 14 October 2008 @ 5:47 pm
@Steinn
You are correct that creating a
User
in admin will not cause aCustomUser
to be created. You need to make it soCustomUser
s are created in admin. See comment #8 above for an idea of how to do that.Does
Customer
need to be a separate model fromCustomUser
? If not, you could useCustomer
as your custom user class — that’s what I’m doing in my current project.If they do need to be separate, you could make the
customer
property ofCustomUser
optional so aCustomUser
can be created first then aCustomer
can be created and assigned. That’s a bit messy, though.An alternative is to write your own manager for
CustomUser
and give it acreate_user
method that does the right thing. You can look at the source indjango/contrib/auth/models.py
to see what the default method does (not much), copy and customise.If there is always one
Customer
for eachCustomUser
, it seems like maybe they should be the same model, so that would be the first thing to consider.Comment by Scott — 15 October 2008 @ 12:46 am
Thanks Scott, I’ll take a look at these links.
Each customer is a company, and can have several users under it, so unfortunately I can’t go with the route of having the CustomUser be the Customer.
One thing I realized yesterday after posting my question here, was that when I go into the administration I can go and create a CustomUser as part of my application, and that will of course create the entries in both tables (and allows me to choose which Customer the new user belongs to). Since all the users will be created this way, I think I can manage without writing a new manager :-)
Best,
Steinn
Comment by Steinn — 15 October 2008 @ 12:59 pm
I tried your example above, but when I try to login the user explicitly through login(request, user), I get the following error message:
‘CustomUser’ object has no attribute ‘backend’
And the code is below:
When I looked into the super authenticate method, it does set the backend. Not sure why it’s not being set in my case.
Note: I am able to authenticate the user fine, but login fails with the given error message.
My settings.py has following entry for AUTHENTICATION_BACKENDS:
Any insight will be appreciated.
Comment by Ravi Hasija — 18 October 2008 @ 11:03 pm
@Ravi
I think instead of making an instance of
CustomUserModelBackend
and callingauthenticate
on it, you should just call theauthenticate
function which is indjango.contrib.auth
.If you look in the source you can see it calls the backend’s
authenticate
method and then sets thebackend
attribute on the user object.It uses the backend(s) configured in your
settings.py
, so it will be using theCustomUserModelBackend
anyway.So, more like:
Comment by Scott — 18 October 2008 @ 11:22 pm
Scott,
Thanks a million. I did look in the source and saw that authenticate method is setting the backend. Coming from Java background, I thought the child method will call super() automatically and did not know that I should call the parent directly.
It works! BEAUTIFUL! You made my day!
Thanks again for the example.
Comment by Ravi Hasija — 19 October 2008 @ 12:10 am
Thanks! You’ve saved me a lot of time!
Nice example!!
Comment by Eduardo — 29 October 2008 @ 6:16 pm
I do inheritance from User model, but i just leave the ‘django.contrib.auth.middleware.AuthenticationMiddleware’,
Since i can get access to my custom user trough user i do:
i would like to have your feedback :)
Thanks in advance,
Sergio Hinojosa
Comment by sergio — 26 November 2008 @ 3:57 am
@Sergio
If you have to add those four lines to each view, that’s a fair bit of extra code, especially if you have lots of views. You could write a custom decorator to do that and set
request.user
orrequest.custom_user
in the decorator.Another thing to consider is if you are making an extra call to the database when you get
request.user.custom_user
. The advantage to custom middleware or authentication backend is that you only need to hit the database once to get the custom user object.Comment by Scott — 26 November 2008 @ 11:03 am
Hi guys, I found a way to create my custom User model every time a auth User instance is created. I putted these lines on my models.py:
I hope this helps someone else!
– Thiago
Comment by Thiago Alves — 1 December 2008 @ 5:25 pm
The inheritance feature is great so far, but there is still a little error in the configuration.
Registration to the admin should be done this way:
[code]
from django.contrib.auth.admin import UserAdmin
admin.site.register(CustomUser,UserAdmin)
[/code]
Then, it’s also possible to set/change the password of the user
Comment by bencoder — 23 December 2008 @ 11:51 am
Hi Scott!
I am trying to use the method you have described here to extend the User model, but I get some errors when I am trying to save the User. The error is:
My custom user model looks like this:
The view that tries to save the user looks like this:
Can you please help me to find out what am I doing wrong?
Thank you!
Comment by Radu — 12 January 2009 @ 12:40 am
Scott, This is very interesting. Thanks for writing it up. I look forward to trying it. Does this break any code (Django or third-party) that references User beyond Django Auth? Or do your tweaks mean that any app that references User is actually referencing CustomUser? I’d like to use Django Groups and other User-related code without having to worry about it breaking because of this approach.
Generally, is there any reason NOT to do this versus the old CustomProfile approach? Thanks!
Comment by mc3 — 13 January 2009 @ 10:53 pm
@mc3
If you use a custom authentication backend as I have, you should find the User is always a CustomUser. I haven’t tried it with any third-party apps so I can’t say if it breaks anything but I don’t see why it would. We’re using it at Red Robot and so far it’s working well.
Comment by Scott — 14 January 2009 @ 10:23 am
Scott,
Thanks. I’m giving it a shot. I thought I had replciated all your steps correctly but I get this error.
Seems to get hung up on this line:
except self.user_class.DoesNotExist:
Not sure how to get round it.
Exception Value:
‘NoneType’ object has no attribute ‘DoesNotExist’
Exception Location: /home/ldm616/webapps/django/fabproject/auth_backends.py in authenticate, line 12
Comment by mc3 — 14 January 2009 @ 6:42 pm
@mc3
Check
CUSTOM_USER_MODEL
is set in your settings.py file. It sounds like the authentication backend is failing to get your model class (uses django.db.models.get_model).Comment by Scott — 14 January 2009 @ 6:54 pm
I think I’ve a solution to matt’s and radu’s problem.
Just use the CustomUser-Model like a normal model, save all needed data, like username, first_name, last_name, password etc.
!!ATTENTION!!
After saving the new user, you’ve to set the encrypted password!
It’s just a workaround, but it works fine here…
Comment by metty — 16 January 2009 @ 12:33 pm
@mc3
I had that problem, and I changed CUSTOM_USER_MODEL from ‘accounts.CustomUser’ to ‘mysite.CustomUser’
@metty
Is there some way to have set_password called when creating the CustomUser from that Admin interface?
Comment by Enj — 19 March 2009 @ 7:40 pm
I have been encountering an error when I try to login to the admin interface. I am using a fresh database.
FieldError at /admin/
Cannot resolve keyword ‘username’ into field. Choices are: basic, id
I am using the the original code in the post, which I think reading the comments should work in my case because I am essentially just adding one extra field to the users. Thanks for the help.
Comment by Peter — 21 March 2009 @ 7:46 pm
Hi Peter.
Check your custom user model is inheriting from
User
notmodels.Model
. Can’t think why else the username field would not be present.Comment by Scott — 22 March 2009 @ 2:25 pm
I’ve tried this with the following issues/problems:
1 — The autodiscover caused an error; so I deleted it.
2 — When I login, it didn’t let me in until I changed my customuser database table to contain a “pointer” to my auth_user table entry (in this case, a 1).
3 — Now, Site administration says: “You don’t have permission to edit anything.”
Any suggestions?
Thanks,
Ken
Comment by Ken Lerman — 1 May 2009 @ 6:03 pm
Hey Scott,
Thank you very much for such a informative article. This really helped.
I have the same question as Enj had. (Comment no. 37)
I got it to working till the point, where I can see my CustomUser Object in admin page.
But, when I try to add user using admin site on CustomUser object. I get a plain django form, where password field is plain textbox.( with change password link beside)
Is there any way, where I can add a user using admin site with CustomUser object? And It asks for username and password initially(like when I add a normal user with User object). And then adds a entry into User and CustomUser table.
( I tried many things but not much success,one them was to use django signals and handle post_save() event, Also tried playing around with UserAdmin object…but no success)
Thanks,
Sujit
Comment by Sujit — 11 June 2009 @ 5:37 pm
Hi Sujit.
Sorry, I’m not adding users in admin, so I’m not sure what the problem would be. A couple of things you might look at:
1. Is this a problem with User/CustomUser only, or do you get similar behaviour with other model inheritance? e.g. create one model then another that inherits from it and see what model instance gets created in admin.
2. Does it make a difference what manager CustomUser has? i.e. if it doesn’t have User’s manager.
3. Could you work around it using a ModelAdmin for CustomUser?
Good luck.
Scott
Comment by Scott — 12 June 2009 @ 9:40 am
Hello Scott,
Thank you very much for your reply. I did try many other options but things didn’t quite work according to my requirement. However, I want to use the model inheritance in admin site. Below is the thing I want to achieve. Kindly provide your advise of the same.
1. In my project, There are two types of users, namely Controller and WebUser.
class Controller(User):
#more controller related fields
pass
class WebUser(User):
#more webuser related fields
pass
2. In admin site I register these two classes
admin.site.register(Controller)
admin.site.register(WebUser)
3. I want to add and delete Controllers and WebUsers.
And don’t really want to manage User Objects. Requirement is to keep the semantics for the users
clean. As controllers are devices which logs in periodically and do some stuff and Webusers are
normal human users which interact with the system.
Problems:
1. I do get the Add form for both Controller and WebUser joined with retrospective User object.
The problem is in password field is displayed as plain text( when saved saves it in plain text as opposed to with save_password() method).
2. Also, “change password” link doesn’t work as well
Questions:
1. What is the best method to achieve something like above?
2. Any pointers on the similar topics. I have gone through most of the threads available but to no avail.
Thanks,
Sujit
Comment by Sujit — 6 July 2009 @ 5:19 pm
@Sujit
Sorry, this is way outside of anything I’ve tried, so I don’t have any advice to offer.
Comment by Scott — 6 July 2009 @ 7:35 pm
[…] 20:39 Прочитал тут о расширении модели User с помощью наследования. Решил […]
Pingback by Расширение модели User — 8 July 2009 @ 5:39 pm
NameError: name ‘models’ is not defined
When I extend the User object in version 1.0.2 of django using the instructions provided in this post, I get this error.
my code is simple:
from django.contrib.auth.models import User
class TestUser(User):
foo=models.CharField(max_length=40)
I have a feeling that Django Version 1.1’s Proxy Class definition will address this issue, but I wanted to check with your community to see if this is a common problem.
Comment by bartosz — 22 July 2009 @ 9:23 pm
@bartosz
Do you also have
from django.db import models
? It looks like you are usingmodels.CharField
, without importingmodels
.Comment by Scott — 23 July 2009 @ 10:33 am
This idea is actually great. Thanks, and I think it would be nice to promote this method as much as possible.
Yet I failed to apply this method successfully.
First, the changes I’ve made:
— Added to settings.py bottom:
— Added to urls.py top:
— settings.py INSTALLED_APPS:
— profiles/models.py:
I’ve tried with and without AUTH_PROFILE_MODULE = ‘profiles.CustomUser’, but with no luck.
Any suggestions?
Forgot to add, it gives me 403 CSRF.
Comment by Necmettin Begiter — 26 July 2009 @ 4:23 pm
@Necmettin Begiter
If the 403 CSRF error is the problem you are having I suggest you remove
django.contrib.csrf.middleware.CsrfMiddleware
from yourMIDDLEWARE_CLASSES
and find out what the problem really is.Comment by Scott — 26 July 2009 @ 9:28 pm
Hi all.
I tried to create a form from CustomUser model. Everything is fine except that fields from customUser model can’t be saved.
Sorry for my bad English
Comment by Masarliev — 11 August 2009 @ 6:07 pm
I just wanted to say thank you. This is an elegant solution to a common problem.
Comment by Jason — 9 September 2009 @ 7:44 am
Hacked this a bit to allow the backend to assign a user subclass based on the user’s group attribute.
http://steps.ucdavis.edu/People/jbremson/extending-the-user-model-in-django
Comment by Joel — 9 September 2009 @ 9:30 pm
$ python manage.py createsuperuser does not ‘obey’ this configuration it stills create the user in User model. Is that a support lack or is there something I’m doing wrong?
Comment by MarioGonzalez — 1 October 2009 @ 11:43 pm
I found a hack to fix the createsuperuser and other problems when one creates a user instead of the custom user. Just use a sql trigger(I use mysql). Something like
delimiter //
create trigger trigger_custom_user
after insert on auth_user
for each row
begin
insert into myapp_customuser (user_ptr_id) values(NEW.id);
//
It’s at the sql level and therefore not ideal, but it works.
Comment by Bufke — 28 November 2009 @ 1:37 am
[…] other things we wanted, so it made sense for us to use it. The next question is whether we try the inheritance approach or do we treat our legacy users table as a sort of User Profile and utilize the User module using […]
Pingback by Django: Model Inheritance or Related Tables wrt AMO at Spindrop — 15 December 2009 @ 9:12 pm
I have found one problem with apply this new extension to the User class. Maybe there is a simple solution to it..
When I create a foreign key to the new CustomUser class and specify “to_field = ‘username'” it works fine with validation and saving but the moment you try and do a order_by on the new model which references a field in the User model it fails with customuser__username field not found.
Example:
I use auto complete fields in my forms that use the username as a value so if I don’t specify to_field in my model the validation will fail as it’s expecting the CustomUser.id.
Maybe there is a way to tell the ModelForm to validate using the username?
Comment by Karol Joc — 21 December 2009 @ 12:42 pm
Hi,
thank you for this article.
Unfortunately i’m having an issue; i’m able to create a CustomUser through the admin interface (like described in comment #8).
But the CustomUsers will appears in admin/auth/user/ (without the custom fields) and nothing will appear in admin/myapp/customuser/.
Is there a clean way to fully add/list/edit extended users through the admin interface or must i make my own admin interface?
Comment by bufh — 20 January 2010 @ 5:12 pm
[…] 0 0 Хочу узнать как лучше регистрировать пользователей на сайте, которым будет закрыт доступ к админке, но с использованием джанговской идентификации.Есть такое приложение — django-registration http://code.google.com/p/django-registration/. Оно предоставляет все необходимое для регистрации пользователей с активацией аккаунта через почту.Все зарегистрированные пользователи будут вперемешку с администраторами в списке ПользователиВ админке есть фильтры =) Поставьте фильтрацию по «Статусу персонала».Модель User имеет ограниченный набор полейДа, можно воспользоваться расширением через UserProfile, а некоторые наследуют от стандартного User свой класс — http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/. […]
Pingback by Регистрация и идентификация пользователей — 8 April 2010 @ 7:46 am
[…] Original Source […]
Pingback by Extending the Django User model < WebIT.ca — 6 May 2010 @ 3:33 am
Hi Scott,
thanx for the solution – it is exactly what i was seraching for – but somehow it is not working.
When trying to log in the admin site for example, i get the
The auth_backends.py is exactly the same you showed, and the CustomUser is just different in it’s fields (not timezone for example)
My Settings is configured like this:
Any ideas? I want to feel the magic pony ;)
Regards,
Kalle
Comment by Kalle — 16 May 2010 @ 8:01 pm
[…] already seen a few ways to do it, but can't decide on which one is the […]
Pingback by Extending the User model with custom fields in Django — HTMLCoderHelper.com — 14 November 2010 @ 11:46 am
Huge thanks! Very useful! I struggled a bit because at first I was calling an Abstract class as for my UserProfile.. but once I figured it out and replaced it by a proper class, your code worked beautifully!
Comment by Cocobuster — 29 November 2010 @ 7:26 am
Hallo,
can someone tell me the easiest way to get the Groups tol return my custom user in their user_set?
I want do do something like that:
u_set = Group.objects.get(name=’Groupname’).customuser_set.all()
instead of
u_set = Group.objects.get(name=’Groupname’).user_set.all()
Can someone help me?
Comment by Josch — 18 December 2010 @ 9:22 pm
@Josch
Off the top of my head, you could get custom users for a group with something like:
group = Group.objects.get(name=’Groupname’)
u_set = CustomUser.objects.filter(groups__contains=group)
Comment by Scott — 18 December 2010 @ 10:38 pm
[…] 我已经看到了一些 办法来做到这一点,但不能决定哪一个是最好的。 This entry was posted in 技术难题 and tagged […]
Pingback by 用自定义的字段在Django的用户模型 | IT技术问答论坛IT技术问答论坛 — 10 February 2011 @ 7:07 pm
[…] would like each shop to be able to login to my application. Following as best I can the guide at http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ and various other googlings, I’ve got part of the way there, but I’ve run into a […]
Pingback by Creating Custom User Backends in Django | Coding Answers — 25 February 2011 @ 5:04 pm
This looks like a great way to extend the User model class. As your original article was way back in 2008, I’m just wondering if any key issues have come to light over that time -esp with new releases of django – which have altered how you feel about this solution? For my part, I think this is a very elegant solution.
Comment by Michael — 4 April 2011 @ 12:17 am
@Michael
I don’t recall any changes in django releases that caused problems. It works and I have used it in some projects, though I still use the ‘old way’ of user profiles as well. Inheriting from the User model can be slightly more awkward in admin. It depends what you’re doing – there’s definitely scope for both approaches.
Comment by Scott — 4 April 2011 @ 10:46 am
Hello Scott – thanks for quick the reply. By the way, I had a look at your company site Red Robot – very impressive stuff you’re doing. I’m going to experiment with your technique and see how it pans out. Really appreciate that people like you are supportive and open with their knowledge.
Comment by Michael — 4 April 2011 @ 11:42 am
Very good your article, congratulations to you and your work.
But I have a doubt.
Below is the code for you to see and error message.
Thank you very much if you can help me.
Thanks!
models.py
forms.py
views.py
Error
Cannot resolve keyword ‘cpf’ into field. Choices are: _message_set, cupon_adquirido, date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, meuuser, password, user_permissions, username
Comment by jhoni — 29 April 2011 @ 8:49 pm
@jhoni
Strange, it works ok for me. Try
print type(user)
after you callcreate_user
and check if it is anMeuUser
instance.Comment by Scott — 29 April 2011 @ 10:27 pm
[…] 0 0 http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ нашёл такой пост. На сколько оно актуально в […]
Pingback by AUTH_PROFILE_MODULE — 30 April 2011 @ 7:27 pm
Scott, you are right, i’am wrong in other details about my code.
Once on more thank you very much,
[]’s
Comment by jhoni — 2 May 2011 @ 1:50 pm
Hi all!
As the user comment 36, i got the problem with the passwords. They are not encryptated, so i had to override the save method.
Btw, i´m adding users only in admin interface, so, i´ve created a defaultAdmin to this.
In admin.py:
Thanks ! ;)
Comment by Fred Chevitarese — 28 June 2011 @ 2:20 pm
[…] Outro artigo muito bom (inglês) é este aqui. http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance […]
Pingback by Extendendo User do Django « Fred Chevitarese … — 28 June 2011 @ 2:31 pm
[…] already seen a few ways to do it, but can’t decide on which one is the […]
Pingback by Extending the User model with custom fields in Django - Programmers Goodies — 4 July 2011 @ 6:46 pm
I have used the inheritence method to build a CustomUser class. Apparently its working absolutely fine but when I create a new user from admin, its password is not being encoded and as a result, I am unable to login with the newly created user. However, login action do not produce any error on the screen but the user is not being redirected to its home page. When I try to update the user from admin site. the password is being displayed in plain text and not in the encded format.
thanks in advance for any help. I am really stuck!!!
Comment by Ammara — 18 July 2011 @ 3:20 am
Ammara – see this post for a variation that deals with the Pasword not being encrypted and also the admin user not using this class but instead the original User.
http://www.kolios.dk/2010/01/22/how-to-extend-django-user-class-and-change-authentication-middleware/
Also see here for a more elegant solution for User override using User classname instead of CustomUser and Admin fix.
http://nigel.jp/2011/06/django-user-authentication-and-extending-the-user-model/
However you need to mix all three approaches to solve the problems in any one of them.
Would be great if this post was updated (or a new post replacing it) to reflect the best way to do all of this… (IMHO)
Thanks Scott for getting this started… Please consider doing an update and straighteneing all the wiggles out…
Comment by mark — 29 July 2011 @ 11:30 am
[…] codice l’ho rubacchiato da un blog. from django.contrib.auth.models import User, UserManager class CustomUser(User): […]
Pingback by Come estendere la classe User in Django — 9 August 2011 @ 4:22 pm
[…] referencia y tienen algunos de estos ejemplos: Documentación en DJango para múltiples sitios Extending the django user model with inheritance Doing more with the Django admin Add a button to Django admin to login as a user […]
Pingback by Django con Admin MultiSite « developer.cl — 26 September 2011 @ 5:04 am
Hi Scott, liked the inheritance but can anyone suggest how I can make an attribute of the child model required, if it is inheriting the User class without saving the user if the instance of the child model is not saved? eg.
If in the admin.py, model Customer is registered, on execution, we get the user creation form, with password after saving it, we exit from the module. We are able to see that the user exists in the django Auth, even if the Customer is not yet created. How do I override the save of the User class. Also I need to create other users for the application the normal way. Please suggest
Comment by mghs — 30 December 2011 @ 10:30 am
i get this error when i try to access my version of ‘CustomUser’ model on the admin site(i have shortened it for clarity):
no such column: app_name_publicprofile.user_ptr_id.
Here is my model:
but i can add users in the admin site.
Any ideas?
Comment by Mwai — 16 January 2012 @ 8:22 pm
So, old post, but I found it so this might be helpful for someone. Similar to #74, but if you are saving your Profile outside of the admin you can override your CustomUser’s save class. It could look something like this:
https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods
Comment by Andy — 28 March 2012 @ 6:19 am
I have a solution for those of you who have not been able to create super users with manage.py (either through syncdb or createsuperuser):
Add this near your CustomUser class in models.py:
Whenever a user is created it will also create an entry in the CustomUser table of the database.
Comment by Dylan — 16 May 2012 @ 9:44 pm
Thanks for the article, but I was stumped by something for a while and I thought I should share the solution.
I had made a custom user that logged in via email instead of username, and I had the login working fine for my own view that I controlled, but the admin site would not let me log in anymore. I assume it was because it was trying to use my custom authentication backend to try and log into the admin site, but that doesn’t make sense because it asks for a username and password, not a email and password like how my custom authentication backend worked.
Therefore, I had to add ‘django.contrib.auth.backends.ModelBackend’ to the end of my AUTHENTICATION_BACKENDS (under my custom backend) so that when my custom authentication failed, it would have the default django method to fall back on.
If any one has a more elegant solution to the problem I had, I’d be happy to hear it.
Comment by Tyler — 5 June 2012 @ 6:39 pm
This seems to work fine.
However, i cannot get the field “timezone” to appear when I am editing a CustomUser.
It will appear in the display_list fine.
But not in the edit page for a Custom User.
If i define a fieldset to include it eg:
It throws an error saying “invalid syntax” on the line where I have included “timezone”).
Any ideas?
Comment by Mark — 16 August 2012 @ 3:42 pm
[…] extending the user model according to this. […]
Pingback by Django: how to store subdomain-based authentication usernames? — 17 August 2012 @ 3:15 pm
[…] already seen a few ways to do it, but can’t decide on which one is the […]
Pingback by Extending the User model with custom fields in Django — 29 September 2012 @ 1:55 am
Hello Scott,
I am working on a project where a User can be associated to either one profile or the other (individual || corporate). At a loss, I must confess.
This is what I have (on a file basis):
Which creates two separate tables, both pointing at the auth_user table. Fine.
Now the whole thing works – up to a point. Django throws the following:
The user is created. The profile is too – but in both the profile tables (individual AND company).
Any idea?
Many thanks!
Comment by Plop — 22 October 2012 @ 11:13 pm
@Plop
I think you’ll need to override
get_profile()
or use some other way of getting the right type of profile (e.g. get user profile if it exists else get company profile). Not sure why both profiles are being created.Comment by Scott — 23 October 2012 @ 11:04 am