5

I want to use two different models for django.contrib.auth module. The first one is the default User model provided by Django which is completely suitable for admin access (groups, permissions etc.) but the other one is customer model which has a lot of different attributes (city, locale, address etc.) compared to default User model. These user groups must use different tables and mustn't have any relation.

I created a Customer model inherited from AbstractBaseUser and a middleware class called ChangeBaseUser like this:

class ChangeBaseUser(object):
    def process_request(self, request):  
        match = resolve(request.path)
        if match.app_name == "myapp":
            settings.AUTH_USER_MODEL = 'myapp.Customer'
        else:
            settings.AUTH_USER_MODEL = 'auth.User'

It's working but I'm not sure whether this is the proper way to do it because in documentation there is a section (link) that implies the convenient way is to assign a static value for default user model.

If this is not the proper way, do you have any suggestions for having multiple user models per module basis?

burak emre
  • 1,501
  • 4
  • 22
  • 46
  • why can the extended user (`customer`) not have any relation to the built in user? – dm03514 Oct 08 '13 at 17:03
  • Although it seems like there are common fields like username, password, last_login etc. there are fields that are used in admin users like groups, permissions etc. but not used in customers, and the other way around is also possible. The other thing is that it doesn't seem a good idea to keep customers and admins in same table with different type values in a b2c project. – burak emre Oct 08 '13 at 17:11

1 Answers1

2

If your requirement is to keep admin users and customers separate, I don't see anything wrong with having multiple user models. At this point, the customer model is like any model, except it is very similar to the user model and that is perfectly fine if that works for you. The only disadvantage is that you will have to possibly duplicate many helpers django gives you for the Django user model such as auth backend or sessions for users. If you are willing to do all that, this seems perfectly fine.

If you wish however to utilize many of the django helpers you might want to create a very basic user model which will serve as a base for both admins and customers:

class User(AbstractBaseUser):
    # use this for auth and sessions

class Admin(models.Model):
    user = models.OneToOneField(UserBase, related_name='admins')
    # ... other admin-specific fields

class Customer(models.Model):
    user = models.OneToOneField(UserBase, related_name='admins')
    # ... other customer-specific fields

This will allow you to reuse many of the things Django provides out of the box however it will incur some additional db overhead since more joins will have to be calculated. But then you can cache things for customers so you can get some of the performance back.

miki725
  • 27,207
  • 17
  • 105
  • 121
  • Thanks for the answer. As I said in comment section, I want to seperate tables for customers and admins. It's working fine but there is one thing that worries me; A static setting attribute is changed each time a visitor visits a page, so when an admin user and a customer visit a page at the same time, I think they may encounter some problems due to accessing same attribute from different threads. – burak emre Oct 08 '13 at 21:16
  • 2
    There are actually a bunch of more scenarios where things can go sideways. I think the only way so solve all the issues is to make your own auth and session backends for your customers (which probably will end up being painful). Then you can essentially end up with two static settings - `AUTH_USER_MODEL` and `MYAPP_USER_MODEL` which will not interfere with each other. – miki725 Oct 08 '13 at 21:28