Thursday, April 26, 2007

[EN] Django extending User, custom User methods

Django doesn't allow to subclass the User model yet.

Each Django model lets you easily create model methods.
Behind the scene, each django model has its own methods, f.e. save()
which saves the model data into the database.

Django provides the lightweight User framework in "django/contrib/auth/",
where "User" model is defined with fields:

username, password, is_staff, first_name, last_name, email, date_joined, last_login,
is_superuser, is_active

What if we need the user model with additional data like: age, location ?

The answer is: "extending the User model" by creating a new model
and linking it with "User" model via ForeignKey.


from django.contrib.auth.models import User

class Userprofile(models.Model):
user = models.ForeignKey(User, unique=True)
age = models.IntegerField()
location = models.CharField(maxlength="100", verbose_name"Country")

To create a new user, django comes with a special "create_user" method.
user = User.objects.create_user('robert', 'rsome@email', 'somepassword')

You could do this also using the standard model create like:
user = User(username='someusername', is_active=True, email='some@email', first_name='john', last_name='doe')

As we have a new User record, to create a new "linked" UserProfile you would:
user = User.objects.get(name='someusername')
user.userprofile_set.create(age=22, location='Poland')

Django will automagically create the new UserProfile with "user" ForeignKey pointing
to the right User instance. Cool !

Question! How do I work on two separated models? Do I need to grab the UserProfile
instance for each request.user I operate in my views ?

Answer: Normally, you woule have to use the code below:
userprofile = Userprofile.objects.get(user=request.user)

Django comes with a special variable "AUTH_PROFILE_MODULE' which should point to your Userprofile model.

AUTH_PROFILE_MODULE = 'yourapp.Userprofile'

which lets you easily get into the "UserProfile" by using the "get_profile()" method.

Example: (in your either or template):

location = request.user.get_profile().location
{{ user.get_profile.location }}

user_profile() does not only allows you to get the model data.
It allows you to get the model methods as well.


class Userprofile(models.Model):
user = models.ForeignKey(User, unique=True)
age = models.IntegerField()
location = models.CharField(maxlength="100")

def __str__(self):
return self.location

def is_of_age(self):
if self.age < 18:
return False
return True

This lets you do some conditioning in your views:
if request.user.get_profile().is_of_age():
print "Yes, I will sell you this beer"


Another +1 for Django !

Links for reading:

No comments: