How to do user authentication in Django

Django is a free, open-source Python web framework that supports fast development and clean, pragmatic design. It provides a ready-made infrastructure for Python web applications, allowing developers to focus on building application logic.

Django provides a robust user authentication system with support for user accounts, user groups, permissions, and cookie-based user session processing.

Although the Django authentication system has a broader scope and handles both authenticationensuring users are who they say they are and authorizationdetermining what a user can do in the system, once they are authenticated.

Prerequisites

  • Basic understanding of Python

  • Familiarity with the Django environment and setup

Setup a new Django project

Run django-admin startproject django_auth_proj on the command line.

Note: This will only work when you have Django installed on a PC. We can find more information on how to install Django from the Django Project site. For simplicity, we won't be creating an app in this project.

Create view functions

Create a file named views.py.

This is where all the logic for each view is defined. The @login_required decorator allows only a logged in user to access the dashboard page. The register function handles both POST and GET requests. It shows the registration form on the GET request, and performs logic to save and login a user on the POST request.

from django.shortcuts import render, redirect, reverse
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required
@login_required
def home(request):
return render(request, "registration/dashboard.html", {})
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username = username, password = password)
login(request, user)
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})

Map URL to view

The URL is a resource, and we need to map each URL to its appropriate view function. For the simplicity of this Answer, we will use Django's default auth_views to handle login and logout.

from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('home/', views.home, name='home'),
path('register/', views.register, name='register'),
path('admin/', admin.site.urls),
]

Setup login and logout URLs

Add the following code in the settings.py file.

# login & logout URLs
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/home/'
LOGOUT_REDIRECT_URL = '/login/'

Creating templates

Templates are HTML files or web pages that end users see; they are usually rendered from the view function. In the view function created above, a couple of templates need to be created, like the register page and dashboard page.

Create a folder named templates in the root of the project, then create another folder inside this folder named registration (because the default Django redirects expect the login to be in a folder named "registration").

Next, setup the Django project to use the templates folder by adding os.path.join(BASE_DIR, 'templates/') to the DIRS array in the settings.py file.

TEMPLATES = [
{
....
"DIRS": [os.path.join(BASE_DIR, 'templates/')],
....
},
]

Create the base.html file in the registration folder.

<html>
<head>
<title>Base </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
{% block content %} {% endblock %}
</body>
</html>

Create the login.html file in the registration folder.

{% extends 'registration/base.html' %} {% block content %}
<section class="py-8">
<div class="container mx-auto">
<div class="flex flex-col items-center">
<h1 class="mt-5 mb-3 text-3xl font-bold">Login</h1>
</div>
<div class="flex flex-col items-center">
<div class="w-full max-w-md mt-3">
<form method="post" action="{% url 'login' %}" class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
{% csrf_token %}
<div class="mb-4">
{{ form.username.label_tag }}
<input
type="text"
name="username"
class="border-2 border-gray-400 rounded-lg w-full py-2 px-4"
maxlength="150"
id="id_username"
required
/>
</div>
<div class="mb-4">
{{ form.password.label_tag }}
<input
type="password"
name="password"
class="border-2 border-gray-400 rounded-lg w-full py-2 px-4"
id="id_password"
required
/>
</div>
{% if form.non_field_errors %} {% for error in form.non_field_errors %}
<p style="font-size: 13px;">
{{ error|escape }}
</p>
{% endfor %} {% endif %}
<div class="flex justify-between items-center">
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Login
</button>
<a class="underline text-blue-600 hover:text-blue-800 visited:text-purple-600" href="/register">Register</a>
</div>
</form>
</div>
</div>
</div>
</section>
{% endblock %}

Create the register.html file in the registration folder.

{% extends 'registration/base.html' %} {% block content %}
<section class="bg-gray-100 py-10">
<div class="container mx-auto">
<div class="text-center">
<h1 class="text-3xl font-bold mt-5 mb-3">Register</h1>
</div>
<div class="w-full max-w-md mx-auto mt-3">
<form method="post" action="{% url 'register' %}">
{% csrf_token %}
{% for field in form %}
<div class="mb-4">
{{ field.label_tag }}
<input
type="{% if 'password' in field.label_tag %}password{% else %}text{% endif %}"
name="{{ field.html_name }}"
class="w-full p-3 border-2 rounded-lg"
maxlength="{% if 'username' in field.label_tag %}150{% endif %}"
id="{{ field.id_for_label }}"
required
/>
{% if field.errors %} {% for error in field.errors %}
<p class="text-red-500 text-sm">{{ error|escape }}</p>
{% endfor %} {% endif %}
</div>
{% endfor %}
<div class="flex justify-between items-center">
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded-lg mt-2">Register</button>
<a class="underline text-blue-600 hover:text-blue-800 visited:text-purple-600" href="/login">Login</a>
</div>
</form>
</div>
</div>
</section>
{% endblock %}

Create the dashboard.html file in the registration folder.

{% extends 'registration/base.html' %}
{% block content %}
<section class="bg-gray-100">
<div class="container mx-auto">
<div class="flex flex-col justify-center items-center">
<h1 class="mt-5 mb-3 text-4xl font-bold">Login Success!</h1>
<p>Dashboard</p>
</div>
<div class="flex justify-center items-center mt-3">
<a href="{% url 'logout' %}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full">Logout</a>
</div>
</div>
</section>
{% endblock %}

Code example

Here is all of the codes above as an executable example of user authentication in Django. Click the "Run" button to execute the program and visit the reflecting link on the widget to review the application

{% extends 'registration/base.html' %} 
{% block content %}
<section class="bg-gray-100">
  <div class="container mx-auto">
    <div class="flex flex-col justify-center items-center">
      <h1 class="mt-5 mb-3 text-4xl font-bold">Login Success!</h1>
      <p>Dashboard</p>
    </div>
    <div class="flex justify-center items-center mt-3">
      <a href="{% url 'logout' %}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full">Logout</a>
    </div>
  </div>
</section>
{% endblock %} 

Free Resources