views:

718

answers:

3

For various complicated reasons[1] I need to add extra properties to the Django User class.

I can't use either Profile nor the "inheritance" way of doing this. (As in http://stackoverflow.com/questions/44109/extending-the-user-model-with-custom-fields-in-django )

So what I've been doing is including the User class in my local_settings file. And adding the property to it there.

This, perhaps surprisingly, seems to work in many cases. But not when I create a new User from UserManager.create_user(). So I need to patch an alternative to the UserManager.create_user() method. Looking at the source for this (in contrib.auth.models.py) I find that the class it uses to create the User is kept in a property called UserManager.model rather than referenced directly.

The line is this :

user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)

The problem is that this self.model (which I assume contains a reference to the User class) doesn't seem to be my patched version.

So, does anyone know where this self.model is set-up in the case of UserManager? And whether I'm correct in assuming that at that point the code hasn't gone through local_settings so my patch to the User class isn't there? And if there's a better place to patch the class?

cheers

phil

[1] To satisfy the cur ious. I need to make the User class use a different and existing table in the database, which has extra fields and constraints.

Update : For future reference, it looks like Proxy Models are the way that Django's going to support what I need : http://code.djangoproject.com/ticket/10356

+2  A: 

The usual way of the having site-specific user fields is to specify a user profile table in your settings.py. You can then retrieve the specific settings via a the u.user_profile() method. It's very well documented in the docs.

kalleh
Yes, but as I mentioned in the question, I can't do this, in this particular case.
interstar
I think you should be able to do this by using signals to create the profile when a new user is created.
kalleh
+2  A: 

You probably just need to make sure that you do the replacement/addition/monkey patch as early as you can (before the auth application is actually installed). The trouble though is that the model classes do some meta-class stuff that'd probably explain why the UserManager has the wrong class - as it will generate the original class, set the UserManager up with that class, then you'll do your stuff and things won't be the same.

So in short be brutal when you replace the class. If you can extend the original class, then replace the original with the extended version:


import django.contrib.auth.models
from django.contrib.auth.models import User as OriginalUser

class User(OriginalUser):
    pass # add your extra fields etc

# then patch the module with your new version
django.contrib.auth.models.User = User

Or if that doesn't work duplicate the User class in your new class and then patch it in.

It's all a bit dirty, but it may do what you want.

John Montgomery
+2  A: 

If Django 1.1 beta isn't too bleeding edge for you, try proxy models.

Antti Rasinen
that looks VERY promising indeed ... if it's not bleeding too badlythanks
interstar
Antti Rasinen