Django User Authentication

Almost every website needs users to be able to create an account, log in, and log out. Django comes with a powerful, ready-made Authentication System built right in. You do not need to build login logic from scratch — Django handles password hashing, session management, and security for you.

What is Django Authentication?

Django's authentication system manages everything related to user identity — who a user is, whether they are logged in, what they are allowed to do, and how to keep them secure. It includes a built-in User model, login and logout views, password hashing, and permission management.

Example: Think of a library membership system. A person walks up to the counter, shows their library card (login), browses books, and returns the card when leaving (logout). The library keeps records of who is a member and what they borrowed. Django's auth system is exactly this — a complete membership management system built into your web app.

The Built-in User Model

Django provides a ready-made User model in django.contrib.auth. It comes with these fields out of the box:

  • username — Unique identifier for the user.
  • password — Stored as a secure hash (never plain text).
  • email — User's email address.
  • first_name and last_name — Optional name fields.
  • is_active — Whether the account is active.
  • is_staff — Whether the user can access the admin panel.
  • is_superuser — Whether the user has all permissions.
  • date_joined — When the account was created.

Setting Up Authentication URLs

Django ships with pre-built authentication views for login and logout. Add them to your project's urls.py:


# myschool/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')),  # <-- Built-in auth URLs
    path('', include('school.urls')),
]

This single line gives you all these URLs automatically:


/accounts/login/           <-- Login page
/accounts/logout/          <-- Logout
/accounts/password_change/ <-- Change password
/accounts/password_reset/  <-- Reset forgotten password

Creating Login and Logout Templates

Django's built-in auth views look for templates in a folder called registration/ inside your templates folder. Create this folder and add the login template:


templates/
└── registration/
    └── login.html

Create templates/registration/login.html:


{% extends 'base.html' %}

{% block content %}
<h2>Login</h2>

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
</form>

<p>Don't have an account? <a href="{% url 'register' %}">Register here</a></p>
{% endblock %}

Redirect After Login

By default, Django redirects to /accounts/profile/ after a successful login. Change this by adding to settings.py:


LOGIN_REDIRECT_URL = '/'          # Redirect to home page after login
LOGOUT_REDIRECT_URL = '/accounts/login/'  # Redirect to login page after logout

Building a User Registration View

Django's built-in auth URLs do not include a registration page — you build that yourself. First, create a registration form using Django's built-in UserCreationForm:


# school/views.py

from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, 'Account created! You can now log in.')
            return redirect('login')
    else:
        form = UserCreationForm()
    return render(request, 'registration/register.html', {'form': form})

Add the URL in school/urls.py:


from django.urls import path
from . import views

urlpatterns = [
    path('register/', views.register, name='register'),
]

Create templates/registration/register.html:


{% extends 'base.html' %}

{% block content %}
<h2>Create an Account</h2>

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Register</button>
</form>

<p>Already have an account? <a href="{% url 'login' %}">Login here</a></p>
{% endblock %}
Example: UserCreationForm is like a pre-printed membership application form from the library. It already has all the right fields — username, password, confirm password — and it already knows how to validate them. You just drop it into your page and it works.

Protecting Pages — Login Required

Some pages should only be accessible to logged-in users. Django provides a simple decorator called @login_required that redirects non-logged-in users to the login page automatically:


from django.contrib.auth.decorators import login_required
from django.shortcuts import render

@login_required
def dashboard(request):
    return render(request, 'dashboard.html')

If a non-logged-in user tries to visit /dashboard/, they are automatically sent to the login page. After logging in, they are returned to the page they originally tried to visit.

Example: @login_required is like a security guard at a company entrance. Anyone without an employee badge (not logged in) is turned away and pointed to the HR desk (login page) to get a badge first.

Accessing the Logged-in User in a View

Inside any view, you can access the currently logged-in user through request.user:


@login_required
def dashboard(request):
    current_user = request.user
    print(current_user.username)    # e.g., "rahul123"
    print(current_user.email)       # e.g., "rahul@school.com"
    print(current_user.is_staff)    # True or False
    return render(request, 'dashboard.html', {'user': current_user})

Displaying User Info in a Template

Django automatically makes the current user available in all templates via the user context variable (no need to pass it manually from the view):


{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}!</p>
    <a href="{% url 'logout' %}">Logout</a>
{% else %}
    <a href="{% url 'login' %}">Login</a>
    <a href="{% url 'register' %}">Register</a>
{% endif %}
Example: user.is_authenticated is like checking if someone is wearing an entry wristband at an event. If they have the wristband (authenticated), show them the VIP lounge. If not, point them to the ticket counter.

Login and Logout Using Built-in Views Manually

If you want to handle login and logout with your own views instead of Django's built-in ones, you can use authenticate() and login():


from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect

def custom_login(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            return redirect('dashboard')
        else:
            return render(request, 'login.html', {'error': 'Invalid username or password.'})
    return render(request, 'login.html')

def custom_logout(request):
    logout(request)
    return redirect('login')

Full Authentication Flow Summary


User visits /register/
    └── Fills UserCreationForm → account saved → redirect to /login/

User visits /login/
    └── Enters credentials → authenticated → redirect to home or dashboard

User visits a @login_required page without logging in
    └── Redirected to /accounts/login/ → after login, sent back to original page

User clicks Logout
    └── Session cleared → redirect to login page

Quick Recap

  • Include django.contrib.auth.urls in your project URLs for built-in login/logout views.
  • Set LOGIN_REDIRECT_URL and LOGOUT_REDIRECT_URL in settings.py.
  • Use UserCreationForm to build a registration page quickly.
  • Use @login_required to protect pages from non-logged-in users.
  • Use request.user in views and {{ user }} in templates to access the logged-in user.
  • Use user.is_authenticated in templates to show/hide content based on login status.

Leave a Comment

Your email address will not be published. Required fields are marked *