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:
# 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:
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:
# 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:
# 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:
# 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:
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 implementationGroup Management
Groups are an effective way to manage user permissions:
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:
<!-- 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:
- ✅ Built-in User model handles basic user information
- ✅ Supports extending User model to meet specific needs
- ✅ Built-in authentication views simplify login/logout processes
- ✅ Access control based on permissions and groups
- ✅ 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.