How to handle multiple user type in Django

2019-06-02 08:20发布

问题:

I'm trying to make a small website which has three types of users ["client" , "volunteer" , "coordinator"]. Each type of user has restrictions on what views it can access. All three users have different login pages.

Approach 1 : To achieve this, I've added a key to the session category, assign one of the above given userTypes during login and, whenever a view is called, check whether that user can access that view.

login.html:

{% extends "base.html" %}
{% block content %}

{% if form.errors %}
    <p class="error"> Sorry , invalid</p>
{% endif %}

    <form action="/login_volunteer/authenticate/" method="post">{% csrf_token %}
    <label for="username"> Username : </label>
    <input type="text" name="username" value="" id="username">
    <label for="password"> Password : </label>
    <input type="password" name="password" value="" id="password">
    <input type="hidden" name="category" value="volunteer" id="category">
    <input type="submit" value="login" />
    </form>

{% endblock %}

view.py:

def hello(request):
    name = "abhishek"
    if request.session.session_key is None:
        html = '<html><body>Session is expired</body></html>'
        return HttpResponse(html)
    try:
        if not request.POST.get('category') == 'volunteer
            html = '<html><body>You are Not allowed here</body></html>'
            return HttpResponse(html)
    except :
        print "error"
    html = '<html><body>Hi this is awesome</body></html>' 
    return HttpResponse(html)

Approach 2 : I thought I could create a custom User class rather than just using the default User provided by Django and assign the CustomUser to the request.user during login. Then when the view is called, I check is_Client or is_Volunteer.

customUser.py:

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

class VolunteerUser(AbstractBaseUser):
    """
    Custom user class.
    """
    email = models.EmailField('email address', unique=True, db_index=True)
    joined = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True)
    is_volunteer = models.BooleanField(default=False)

class ClientUser(AbstractBaseUser):
    """
    Custom user class.
    """
    email = models.EmailField('email address', unique=True, db_index=True)
    joined = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True)
    is_Client = models.BooleanField(default=False)

So my question is, which of these approaches is the best way to accomplish the task at hand? Is there any other method that solves this?

I'm also concerned about security and I feel that the first method is more insecure than the second.

回答1:

The better approach for achieving your requirement is to use the inbuilt Group and Permissions model in Django. But since Permissions can be a little tricky, an alternative approach is to create a UserProfile model like below:

from django.contrib.auth.models import User
class UserProfile(models.Model):
    user = models.ForeignKey(User)
    type = models.CharField(max_length=15)

Then use the @user_passes_test decorator for controlling access to the views like this:

from django.contrib.auth.decorators import user_passes_test
@user_passes_test(lambda u: u.get_profile().type == 'client')
def view_for_client(request):         
    ...

The UserProfile model will also be useful to save all of the preferences of your user. Also you would need to set the following setting:

AUTH_PROFILE_MODULE = 'accounts.UserProfile'