Multiple Profiles

4 views
Skip to first unread message

Mi Reflejo

unread,
May 8, 2007, 12:49:26 AM5/8/07
to django-d...@googlegroups.com
Hi,

I have a project with multiple user types. That means: Multiple profiles.

Since i don't have one AUTH_PROFILE_MODULE i can't use get_profile(). I think i could do a intermediate M2M table but i don't want this overload and i loose user_profile cache (Because in this scenery M2M table is cached but not profile)

To solve this issue i wrote a simple patch for contrib/auth/models.py. [Patch is attached] that add one var to get_profile so you can choose your profile table dinamically.

Is there another solution for this?

Regards,
--
Martín Conte Mac Donell
http://www.catartico.com
auth.models.patch

Amit Upadhyay

unread,
May 8, 2007, 9:42:50 AM5/8/07
to django-d...@googlegroups.com
I would recommend you take a look at lost-theories.com source code. One anti pattern that django docs seems to recommend is use django.contrib.auth.models.User as your main user model, and put rest of user info in yourapp.accounts.models.UserProfile or something.

I propose, django officially recommends it as a bad approach. What we should tell new comers to django is:
  • create a FooUser in the yourapp.accounts.models , something like this:
class FooUser(models.Model):
    duser = models.ForeignKey(User) # django.contrib.auth.models.User
    address = models.TextField()
    _get_username(self): return self.duser.username
    _get_email(self): return self.duser.email
    _set_email(self, email):
          self.duser.email = email
          self.duser.save()
    username = property(_get_username)
    email = property(_get_email, _set_email)
  • throughout your code base, use a foreign key to yourapp.accounts.models.FooUser instead of django.contrib.auth.models.User
  • infact for clarity, use variable name fuser whenever referring to FooUser, and duser when referring to django's User instance.
  • go as far as set wrong value for AUTH_PROFILE_MODULE to catch some code calling get_profile()
  • set up a middle ware:
    class FooUserMiddleware(object):
        def process_request(self, request):
            if request.user.is_authenticated():
                request.fuser = FooUser.objects.get(duser=request.user)
            else: request.fuser = None
    => use request.fuser in all your views.
  • use the context_processor:
    def context_processor(request):
        d['fuser'] = request.fuser
        return d
    and use fuser in all your templates. You can access both fuser.username /email and fuser.address.
This will go a long way making life of a lot of developers easier. You can have as many types of Users as you wont, not having to worry how to hack .get_profile() etc.

And it is actually correct. Imagine if I have to have a friendship relationship between users, I can not obviously monkeypath django contrib auth app, so I would put that many to many in UserProfile as per current django recommendation, and user.get_profile().friends.all() sounds wrong. With this you can say fuser.friends.get(). Natural.
--
Amit Upadhyay
Vakao!
+91-9820-295-512

Rob Hudson

unread,
May 9, 2007, 10:14:27 AM5/9/07
to Django developers
I'd like to hear what others think of this approach b/c it makes a lot
of sense to me and does seem much easier in that:

1) The newly defined user object is in request
2) There's one place to get user info

Thanks for sharing,
Rob

Reply all
Reply to author
Forward
0 new messages