Django Authentication

Django Unchained Wallpapers, Pictures, Images (hdwallpaper.nu)

I’m working with Django – a framework for python web applications. It helps streamline writing new applications that use databases, forms, and authorisation.

You create a model of your data, a matching form, and with minimum coding you can then produce forms and use a backend database with – well lets say more ease than you would otherwise.

Simplifying authorisation and authentication means that by just adding a few lines you can make sure users are logged in (authenticated) and have the right assigned permissions (authorised) above every relevant view. (A view is a python function that accepts a web request.) So above my function register, I can make sure people are logged in and have permissions to add and view the data in the MyUser database.

@login_required
@permission_required("users.add_myuser")
@permission_required("users.view_myuser")
def register(request,id):

That’s easier than checking everywhere for authorisation and authentication.

I wanted to extend the default Django provided User table, with a field called “role”. So the roles are “ADMIN” – someone is authorised to add additional users and “USER” – someone who is really just adding/deleting records elsewhere (certificate records in my example).

from django.db import models
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
    ROLES = ( ( "ADMIN", "Admin"), ("USER", "User"))
    role= models.CharField(max_length=10, 
                           choices=ROLES,
                           default="USER", 
                           blank=True)

So now I have a model called MyUser in my “users” app. It inherits the parent characteristics from the Django provided AbstractUser model.

In my users/forms.py file I list what selected fields I need to show.

from django import forms
from django.db import models
from django.contrib.auth.forms import UserCreationForm
from .models import MyUser

class RegistrationForm(UserCreationForm):
    email = forms.EmailField(required=True)
    first_name = forms.CharField(max_length=32,required=True)
    last_name = forms.CharField(max_length=32,required=True )
    role = models.CharField(max_length=10, blank=True)
    class Meta:
        model = MyUser
        fields = ["username", "role", "password1", "password2", "first_name", "last_name", "email"  ]

The index page for Myuser is going to display all the users. So I just need to obtain all the records and pass them to a jJnga2 html file.

@login_required
@permission_required("users.view_myuser")
def UserIndex(request):
    queryset = MyUser.objects.order_by("username")
    context = {"user_list": queryset}
    return render(request, "index.html", context)

.The jinja2 html file has a code section to display the users.

 <table class="table">
        <thread>
            <tr>
                <th>Username</th>
                <th>Email&nbsp;</th>
                <th>First Name&nbsp;</th>
                <th>Last Name&nbsp;</th>
                <th>Role</th>
            </tr>
        </thread>
        <tbody>
        {% for user in user_list %}
        <tr>
            <td>
             <a href="/users/detail/{{user.id}}">{{ user.username}}</a>
            </td>
            <td> {{user.email}} </td>
            <td> {{user.first_name}} </td>
            <td> {{user.last_name}} </td>
            <td>{{ user.role }}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>

The function to register a user starts like this:

@login_required
@permission_required("users.add_myuser",raise_exception=False)
@permission_required("users.view_myuser",raise_exception=False)
def register(request):
    if request.method == 'POST':
        try:
            form = RegistrationForm(request.POST)
        except:
            pass
        if form.is_valid():
            form.save()
            messages.add_message(
                    request,
                    messages.SUCCESS,
                    f"Record {form.cleaned_data['username']} added successfully!",
            )

So if the form is valid then write the data into the table. I can then pick out the role.

u = form.cleaned_data["username"]
myuser = MyUser.objects.get(username=u)
role=myuser.role

On the first run, if there is no “ADMIN” group setup (which you can create easily using the Django admin GUI), then I can programmatically create and populate with all the permissions available taken from the Myuser model. These will be “add”, “view”, “change”, “delete”.

 u_group="ADMIN"
 myuser_content_type = ContentType.objects.get_for_model(MyUser)
 myusers_permissions = Permission.objects.filter ( 
         content_type = myuser_content_type
          )
 for p in myusers_permissions:
           u_group.permissions.add(p)

Now you can continue by merely putting the user in that group.

 u = form.cleaned_data["username"]
 myuser = MyUser.objects.get(username=u)
 myuser.groups.add(u_group)
 myuser.save()

Is that enough Gist?

I often write these posts for myself. One thing I had trouble with was working out the correct names for permissions. So my app is called users and my data Model is called MyUser. The permissions come out such as users.add_myuser. It was only by printing out all the permissions from a user did I realise the proper permission codenames.

print(myuser.get_all_permissions())
{ 'certs.add_certificate', 'certs.change_certificate', 
'users.change_myuser', 'users.delete_myuser', 
'users.view_myuser', ' 'certs.delete_certificate', 'users.add_myuser', 'certs.view_certificate'}