More than one profile in Django?
Question: Is it possible to use Django's user authentication features with more than one
profile?

Currently I have a settings.py file that has this in it:

    
    
    AUTH_PROFILE_MODULE = 'auth.UserProfileA'
    

and a models.py file that has this in it:

    
    
    from django.db import models
    from django.contrib.auth.models import User
    
    class UserProfileA(models.Model):
        company = models.CharField(max_length=30)
        user = models.ForeignKey(User, unique=True)
    

that way, if a user logs in, I can easily get the profile because the User has
a get_profile() method. However, I would like to add UserProfileB. From
looking around a bit, it seems that the starting point is to create a
superclass to use as the AUTH_PROFILE_MODULE and have both UserProfileA and
UserProfileB inherit from that superclass. The problem is, I don't think the
get_profile() method returns the correct profile. It would return an instance
of the superclass. I come from a java background (polymorphism) so I'm not
sure exactly what I should be doing.

Thanks!

Edit:

Well I found a way to do it via something called an "inheritance hack" that I
found at this site <http://djangosnippets.org/snippets/1031/>

It works really well, however, coming from a java background where this stuff
happens automatically, I'm a little unsettled by the fact that someone had to
code this up and call it a "hack" to do it in python. Is there a reason why
python doesn't enable this?


Answer: So the issue you're going to have is that whatever you want for your profile,
you need to persist it in a database of some sort. Basically all of the back-
ends for django are relational, and thus every field in a persisted object is
present in every row of the table. there are a few ways for getting what you
want.

Django provides some support for
[inheritance.](http://docs.djangoproject.com/en/dev/topics/db/models/#model-
inheritance) You can use the techniques listed and get reasonable results in a
polymorphic way.

The most direct approach is to use multiple table inheritance. Roughly:

    
    
    class UserProfile(models.Model):
        # set settings.AUTH_PROFILE_MODULE to this class!
        pass
    
    class UserProfileA(UserProfile):
        pass
    
    class UserProfileB(UserProfile):
        pass
    

To use it:

    
    
    try:
        profile = user.get_profile().userprofilea
        # user profile is UserProfileA
    except UserProfileA.DoesNotExist:
        # user profile wasn't UserProfileB
        pass
    try:
        profile = user.get_profile().userprofileb
        # user profile is UserProfileB
    except UserProfileB.DoesNotExist:
        # user profile wasn't either a or b...
    

**Edit:** Re, your comment.

The relational model implies a number of things that [seem to
disagree](http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx)
with object oriented philosophy. For a relation to be useful, it requires that
every element in the relation to have the same dimensions, so that relational
queries are valid for the whole relation. Since this is known a-priori, before
encountering an instance of a class stored in the relation, then the row
cannot be a subclass. django's orm overcomes this impedance mismatch by
storing the subclass information in a different relation (one specific to the
subclass), There are other solutions, but they all obey this basic nature of
the relational model.

If it helps you come to terms with this, I'd suggest looking at how
persistence on a RDBMs works for applications in the absence of an ORM. In
particular, relational databases are more about collections and summaries of
many rows, rather than applying behaviors to data once fetched from the
database.

The specific example of using the profile feature of `django.contrib.auth` is
a rather uninteresting one, especially if the only way that model is ever used
is to fetch the profile data associated with a particular
`django.contrib.auth.models.User` instance. If there are no other queries, you
don't need a `django.models.Model` subclass at all. You can pickle a regular
python class and store it in a blob field of an otherwise featureless model.

On the other hand, if you want to do more interesting things with profiles,
like search for users that live in a particular city, then it will be
important for _all_ profiles to have an index for their city property. That's
got nothing to do with OOP, and everything to do with relational.

