User Authentication: Registration, Login & Logout
1. Django’s Built-In Authentication System
Django ships with a complete, battle-tested authentication system. It handles user accounts, passwords (hashed with PBKDF2 by default), sessions, and permissions. You rarely need to build authentication from scratch. The django.contrib.auth app (already in INSTALLED_APPS) provides all the tools.
2. Setting Up Auth URLs
Django provides pre-built views for login and logout. Wire them into your project’s urls.py:
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
# Provides: /accounts/login/, /accounts/logout/, /accounts/password_change/
path('accounts/', include('django.contrib.auth.urls')),
]
Tell Django where to redirect users after login and logout in settings.py:
# mysite/settings.py
LOGIN_REDIRECT_URL = '/' # After successful login, go to homepage
LOGOUT_REDIRECT_URL = '/' # After logout, go to homepage
LOGIN_URL = '/accounts/login/' # Where @login_required sends unauthenticated users
3. Creating the Login Template
Django’s built-in login view looks for a template at registration/login.html. Create it:
<!-- templates/registration/login.html -->
{% extends "blog/base.html" %}
{% block title %}Log In{% endblock %}
{% block content %}
<h1>Log In</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Log In</button>
</form>
<p>Don't have an account? <a href="{% url 'register' %}">Register here</a></p>
{% endblock %}
4. Building User Registration
Django does not provide a registration view, but it does provide UserCreationForm — a ModelForm for creating new users. Build a registration view using it:
# blog/views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
from django.shortcuts import render, redirect
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save() # Create the new user in the database
login(request, user) # Log them in immediately
return redirect('post_list')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
<!-- templates/registration/register.html -->
{% extends "blog/base.html" %}
{% block title %}Register{% endblock %}
{% block content %}
<h1>Create an Account</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
{% endblock %}
# blog/urls.py — add the register URL
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('blog/<slug:slug>/', views.post_detail, name='post_detail'),
path('register/', views.register, name='register'),
]
5. Protecting Views with @login_required
The @login_required decorator is the simplest way to restrict a view to authenticated users only. If an unauthenticated user tries to access a protected URL, they are automatically redirected to the login page:
# blog/views.py
from django.contrib.auth.decorators import login_required
@login_required # Add this decorator above any view you want to protect
def create_post(request):
# Only logged-in users reach this code.
# request.user is always available and contains the authenticated user.
...
6. Accessing the Current User in Templates
Django’s template context processors make request.user available in every template as the user variable. Use it to show different content to logged-in and anonymous users:
<nav>
{% if user.is_authenticated %}
<span>Hello, {{ user.username }}!</span>
<a href="{% url 'logout' %}">Log Out</a>
<a href="{% url 'create_post' %}">New Post</a>
{% else %}
<a href="{% url 'login' %}">Log In</a>
<a href="{% url 'register' %}">Register</a>
{% endif %}
</nav>