django best approach for creating multiple type users

Solution 1:

Django doesn't have multiple users - it only has one user and then based on permissions users can do different things.

So, to start off with - there is only one user type in django. If you use the default authentication framework, the model for this user is called User, from django.contrib.auth.models.

If you want to customize user behavior in django, there are three things you can do:

  1. Customize how you authenticate them. By default, authentication is done using a database where passwords are stored. You can authenticate against facebook/google etc. or against your existing user database - for example, with ActiveDirectory if you are on a Windows network.

  2. Create custom permissions, and based on these permissions, restrict what functions users can execute. By default, on every model - django will add basic permissions "can edit", "can delete", "can read". You can create your own and then check if the user has these specific permissions.

  3. You can store extra information about the user, along with whatever normally is stored by django. There are two ways to do this, depending on how much customization you need. If everything django provides by default works for you, and all you want to do is store extra information about the user you can extend the user model - in previous versions this was called creating a custom profile. The other option you have is to create your own User model, if you want deeper customization. The most common use of a custom user model is if you want to use an email address as the username.

You don't have to do all three, in fact sometimes all you want to do is store some extra information or have them authenticate using their email address; in some applications you have to modify all three places.

In your case, since all you want to do is store extra information about a user, you would need to extend the user model, by creating a model that references User (note: you don't inherit from User):

class Profile(models.Model):
    user = models.OneToOneField(User)
    department = models.CharField(max_length=200, default='Computer Science')
    is_teacher = models.BooleanField(default=False)
    is_student = models.BooleanField(default=True)
    # .. etc. etc.

Solution 2:

One approach I was following with Django 1.7 (works with 1.6 too) is to subclass AbstractUser

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    balance = models.DecimalField(default=0.0, decimal_places=2, max_digits=5)

To use your model you need to set it to be the one used for authentication in settings.py:

AUTH_USER_MODEL = 'your_app.User'

Also note that you will now have to use settings.AUTH_USER_MODEL when referencing your new User model in a relation in your models.

from django.db import models
from django.conf import settings

class Transaction(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL) # ForeignKey(User) will not work