Skip to content

Chapter 9: User Authentication System ​

9.1 Django Authentication Framework ​

User Model ​

Django has a built-in powerful user authentication system with the User model at its core. The User model contains the following fields:

python
# Main fields of Django's built-in User model
class User(models.Model):
    username = models.CharField(max_length=150, unique=True)
    first_name = models.CharField(max_length=150, blank=True)
    last_name = models.CharField(max_length=150, blank=True)
    email = models.EmailField(blank=True)
    is_staff = models.BooleanField(default=False)  # Can access admin
    is_active = models.BooleanField(default=True)  # Is active
    is_superuser = models.BooleanField(default=False)  # Is superuser
    last_login = models.DateTimeField(blank=True, null=True)
    date_joined = models.DateTimeField(default=timezone.now)

Basic operations using the User model:

python
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout

# Create user
user = User.objects.create_user(
    username='john',
    email='john@example.com',
    password='secret'
)

# Create superuser
superuser = User.objects.create_superuser(
    username='admin',
    email='admin@example.com',
    password='secret'
)

# Authenticate user
user = authenticate(username='john', password='secret')
if user is not None:
    print("User authentication successful")
else:
    print("Username or password incorrect")

# Modify user attributes
user.first_name = 'John'
user.last_name = 'Doe'
user.save()

# Set password
user.set_password('newpassword')
user.save()

# Check password
if user.check_password('newpassword'):
    print("Password correct")

Extending the User model:

python
# Method 1: One-to-one relationship (recommended)
from django.contrib.auth.models import User
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)
    avatar = models.ImageField(upload_to='avatars/', blank=True)

# Signal handler to create user profile
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.userprofile.save()

# Method 2: Custom User model
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

# Set in settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'

Authentication Views ​

Django provides built-in authentication views to handle common authentication tasks:

python
# urls.py
from django.urls import path, include
from django.contrib.auth import views as auth_views

urlpatterns = [
    # Use Django's built-in authentication views
    path('accounts/', include('django.contrib.auth.urls')),
    
    # Or define each view separately
    path('login/', auth_views.LoginView.as_view(), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
    path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
    path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
    path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

Custom login view:

python
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages

def custom_login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                messages.info(request, f"Welcome, {username}!")
                return redirect('home')
            else:
                messages.error(request, "Username or password incorrect")
        else:
            messages.error(request, "Username or password incorrect")
    else:
        form = AuthenticationForm()
    
    return render(request, 'registration/login.html', {'form': form})

# Custom login template registration/login.html
"""
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
</form>
"""

Permission System ​

Django's permission system is based on the user, group, and permission model:

python
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType
from myapp.models import Article

# Create permission
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.create(
    codename='can_publish_article',
    name='Can Publish Article',
    content_type=content_type,
)

# Assign permission to user
user = User.objects.get(username='john')
user.user_permissions.add(permission)

# Assign permission to group
group = Group.objects.get(name='Editors')
group.permissions.add(permission)

# Add user to group
user.groups.add(group)

# Check user permission
if user.has_perm('myapp.can_publish_article'):
    print("User has permission to publish articles")

# Check if user belongs to a group
if user.groups.filter(name='Editors').exists():
    print("User is an editor")

# Check permission in views
from django.contrib.auth.decorators import permission_required

@permission_required('myapp.can_publish_article')
def publish_article(request):
    # Only users with publish permission can access
    pass

# Check permission in class-based views
from django.contrib.auth.mixins import PermissionRequiredMixin

class PublishArticleView(PermissionRequiredMixin, CreateView):
    permission_required = 'myapp.can_publish_article'
    # View implementation

Group Management ​

Groups are an effective way to manage user permissions:

python
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType

# Create groups
editors_group = Group.objects.create(name='Editors')
writers_group = Group.objects.create(name='Writers')

# Get permissions
content_type = ContentType.objects.get_for_model(Article)
add_article_perm = Permission.objects.get(
    content_type=content_type,
    codename='add_article'
)
change_article_perm = Permission.objects.get(
    content_type=content_type,
    codename='change_article'
)
delete_article_perm = Permission.objects.get(
    content_type=content_type,
    codename='delete_article'
)

# Assign permissions to group
editors_group.permissions.add(
    add_article_perm,
    change_article_perm,
    delete_article_perm
)

# Add user to group
user = User.objects.get(username='john')
user.groups.add(editors_group)

# Check if user belongs to group
if user.groups.filter(name='Editors').exists():
    print("User is an editor")

# Remove user from group
user.groups.remove(editors_group)

# Delete group
editors_group.delete()

Using permissions in templates:

html
<!-- Check if user is authenticated -->
{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}!</p>
    <a href="{% url 'logout' %}">Logout</a>
{% else %}
    <a href="{% url 'login' %}">Login</a>
{% endif %}

<!-- Check user permissions -->
{% if perms.myapp.add_article %}
    <a href="{% url 'article_create' %}">Create Article</a>
{% endif %}

<!-- Check if user belongs to specific groups -->
{% if user.groups.all %}
    <p>Your groups:
    {% for group in user.groups.all %}
        {{ group.name }}{% if not forloop.last %}, {% endif %}
    {% endfor %}
    </p>
{% endif %}

With Django's authentication framework, you can easily implement common authentication features such as user registration, login, and permission management.

Summary ​

Django's authentication framework provides a complete user management system:

  1. ✅ Built-in User model handles basic user information
  2. ✅ Supports extending User model to meet specific needs
  3. ✅ Built-in authentication views simplify login/logout processes
  4. ✅ Access control based on permissions and groups
  5. ✅ Permission checking in templates

Mastering the authentication framework is the foundation for building secure web applications.

Next ​

We will learn about the specific implementation of user registration and login.

9.2 User Registration →

Contents ​

Back to Course Outline

Released under the [BY-NC-ND License](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.en).