Creating a Simple Login System with Django

Welcome, aspiring web developers! Building a website often means you need to know who your visitors are, giving them personalized content or access to special features. This is where a “login system” comes in. A login system allows users to create accounts, sign in, and verify their identity, making your website interactive and secure.

Django, a powerful and popular web framework for Python, makes building login systems surprisingly straightforward thanks to its excellent built-in features. In this guide, we’ll walk through how to set up a basic login and logout system using Django’s ready-to-use authentication tools. Even if you’re new to web development, we’ll explain everything simply.

Introduction

Imagine you’re building an online store, a social media site, or even a simple blog where users can post comments. For any of these, you’ll need a way for users to identify themselves. This process is called “authentication” – proving that a user is who they claim to be. Django includes a full-featured authentication system right out of the box, which saves you a lot of time and effort by handling the complex security details for you.

Prerequisites

Before we dive in, make sure you have:

  • Python Installed: Django is a Python framework, so you’ll need Python on your computer.
  • Django Installed: If you haven’t already, you can install it using pip:
    bash
    pip install django
  • A Basic Django Project: We’ll assume you have a Django project and at least one app set up. If not, here’s how to create one quickly:
    bash
    django-admin startproject mysite
    cd mysite
    python manage.py startapp myapp

    Remember to add 'myapp' to your INSTALLED_APPS list in mysite/settings.py.

Understanding Django’s Authentication System

Django comes with django.contrib.auth, a robust authentication system. This isn’t just a simple login form; it’s a complete toolkit that includes:

  • User Accounts: A way to store user information like usernames, passwords (securely hashed), and email addresses.
  • Groups and Permissions: Mechanisms to organize users and control what they are allowed to do on your site (e.g., only admins can delete posts).
  • Views and URL patterns: Pre-built logic and web addresses for common tasks like logging in, logging out, changing passwords, and resetting forgotten passwords.
  • Form Classes: Helper tools to create the HTML forms for these actions.

This built-in system is a huge advantage because it’s secure, well-tested, and handles many common security pitfalls for you.

Step 1: Setting Up Your Django Project for Authentication

First, we need to tell Django to use its authentication system and configure a few settings.

1.1 Add django.contrib.auth to INSTALLED_APPS

Open your project’s settings.py file (usually mysite/settings.py). You’ll likely find django.contrib.auth and django.contrib.contenttypes already listed under INSTALLED_APPS. If not, make sure they are there:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',  # This line is for the authentication system
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', # Your custom app
]
  • INSTALLED_APPS: This list tells Django which applications (or features) are active in your project. django.contrib.auth is the key one for authentication.

1.2 Configure Redirect URLs

After a user logs in or logs out, Django needs to know where to send them. We define these “redirect URLs” in settings.py:

LOGIN_REDIRECT_URL = '/' # Redirect to the homepage after successful login
LOGOUT_REDIRECT_URL = '/accounts/logged_out/' # Redirect to a special page after logout
LOGIN_URL = '/accounts/login/' # Where to redirect if a user tries to access a protected page without logging in
  • LOGIN_REDIRECT_URL: The URL users are sent to after successfully logging in. We’ve set it to '/', which is usually your website’s homepage.
  • LOGOUT_REDIRECT_URL: The URL users are sent to after successfully logging out. We’ll create a simple page for this.
  • LOGIN_URL: If a user tries to access a page that requires them to be logged in, and they aren’t, Django will redirect them to this URL to log in.

1.3 Include Authentication URLs

Now, we need to make Django’s authentication views accessible through specific web addresses (URLs). Open your project’s main urls.py file (e.g., mysite/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')), # This line adds all auth URLs
    # Add your app's URLs here if you have any, for example:
    # path('', include('myapp.urls')),
]
  • path('accounts/', include('django.contrib.auth.urls')): This magical line tells Django to include all the URL patterns (web addresses) that come with django.contrib.auth. For example, accounts/login/, accounts/logout/, accounts/password_change/, etc., will now work automatically.

1.4 Run Migrations

Django’s authentication system needs database tables to store user information. We create these tables using migrations:

python manage.py migrate
  • migrate: This command applies database changes. It will create tables for users, groups, permissions, and more.

Step 2: Creating Your Login and Logout Templates

Django’s authentication system expects specific HTML template files to display the login form, the logout message, and other related pages. By default, it looks for these templates in a registration subdirectory within your app’s templates folder, or in any folder listed in your TEMPLATES DIRS setting.

Let’s create a templates/registration/ directory inside your myapp folder (or your project’s main templates folder if you prefer that structure).

mysite/
├── myapp/
   ├── templates/
      └── registration/
          ├── login.html
          └── logged_out.html
   └── views.py
├── mysite/
   ├── settings.py
   └── urls.py
└── manage.py

2.1 login.html

This template will display the form where users enter their username and password.

<!-- myapp/templates/registration/login.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Log In</button>
    </form>

    {% if form.errors %}
        <p style="color: red;">Your username and password didn't match. Please try again.</p>
    {% endif %}

    <p>Forgot your password? <a href="{% url 'password_reset' %}">Reset it here</a>.</p>
</body>
</html>
  • {% csrf_token %}: This is a crucial security tag in Django. It prevents Cross-Site Request Forgery (CSRF) attacks by adding a hidden token to your form. Always include it in forms that accept data!
  • {{ form.as_p }}: Django’s authentication views automatically pass a form object to the template. This line renders the form fields (username and password) as paragraphs (<p> tags).
  • {% if form.errors %}: Checks if there are any errors (like incorrect password) and displays a message if so.
  • {% url 'password_reset' %}: This is a template tag that generates a URL based on its name. password_reset is one of the URLs provided by django.contrib.auth.urls.

2.2 logged_out.html

This simple template will display a message after a user successfully logs out.

<!-- myapp/templates/registration/logged_out.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Logged Out</title>
</head>
<body>
    <h2>You have been logged out.</h2>
    <p><a href="{% url 'login' %}">Log in again</a></p>
</body>
</html>
  • {% url 'login' %}: Generates the URL for the login page, allowing users to quickly log back in.

Step 3: Adding Navigation Links (Optional but Recommended)

To make it easy for users to log in and out, you’ll want to add links in your website’s navigation or header. You can do this in your base template (base.html) if you have one.

First, create a templates folder at your project root (mysite/templates/) if you haven’t already, and add base.html there. Then, ensure DIRS in your TEMPLATES setting in settings.py includes this path:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'], # Add this line
        'APP_DIRS': True,
        # ...
    },
]

Now, create mysite/templates/base.html:

<!-- mysite/templates/base.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    <nav>
        <ul>
            <li><a href="/">Home</a></li>
            {% if user.is_authenticated %}
                <li>Hello, {{ user.username }}!</li>
                <li><a href="{% url 'logout' %}">Log Out</a></li>
                <li><a href="{% url 'protected_page' %}">Protected Page</a></li> {# Link to a protected page #}
            {% else %}
                <li><a href="{% url 'login' %}">Log In</a></li>
            {% endif %}
        </ul>
    </nav>
    <hr>
    <main>
        {% block content %}
        {% endblock %}
    </main>
</body>
</html>
  • {% if user.is_authenticated %}: This is a Django template variable. user is automatically available in your templates when django.contrib.auth is enabled. user.is_authenticated is a boolean (true/false) value that tells you if the current user is logged in.
  • user.username: Displays the username of the logged-in user.
  • {% url 'logout' %}: Generates the URL for logging out.

You can then extend this base.html in your login.html and logged_out.html (and any other pages) to include the navigation:

<!-- myapp/templates/registration/login.html (updated) -->
{% extends 'base.html' %}

{% block title %}Login{% endblock %}

{% block content %}
    <h2>Login</h2>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Log In</button>
    </form>

    {% if form.errors %}
        <p style="color: red;">Your username and password didn't match. Please try again.</p>
    {% endif %}

    <p>Forgot your password? <a href="{% url 'password_reset' %}">Reset it here</a>.</p>
{% endblock %}

Do the same for logged_out.html.

Step 4: Protecting a View (Making a Page Require Login)

What’s the point of a login system if all pages are accessible to everyone? Let’s create a “protected page” that only logged-in users can see.

4.1 Create a Protected View

Open your myapp/views.py and add a new view:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required # Import the decorator


def home(request):
    return render(request, 'home.html') # Example home view

@login_required # This decorator protects the 'protected_page' view
def protected_page(request):
    return render(request, 'protected_page.html')
  • @login_required: This is a “decorator” in Python. When placed above a function (like protected_page), it tells Django that this view can only be accessed by authenticated users. If an unauthenticated user tries to visit it, Django will automatically redirect them to the LOGIN_URL you defined in settings.py.

4.2 Create the Template for the Protected Page

Create a new file myapp/templates/protected_page.html:

<!-- myapp/templates/protected_page.html -->
{% extends 'base.html' %}

{% block title %}Protected Page{% endblock %}

{% block content %}
    <h2>Welcome to the Protected Zone!</h2>
    <p>Hello, {{ user.username }}! You are seeing this because you are logged in.</p>
    <p>This content is only visible to authenticated users.</p>
{% endblock %}

4.3 Add the URL for the Protected Page

Finally, add a URL pattern for your protected page in your myapp/urls.py file. If you don’t have one, create it.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'), # An example home page
    path('protected/', views.protected_page, name='protected_page'),
]

And make sure this myapp.urls is included in your main mysite/urls.py if it’s not already:

urlpatterns = [
    # ...
    path('', include('myapp.urls')), # Include your app's URLs
]

Running Your Application

Now, let’s fire up the development server:

python manage.py runserver

Open your web browser and go to http://127.0.0.1:8000/.

  1. Try to visit http://127.0.0.1:8000/protected/. You should be redirected to http://127.0.0.1:8000/accounts/login/.
  2. Create a Superuser: To log in, you’ll need a user account. Create a superuser (an admin user) for testing:
    bash
    python manage.py createsuperuser

    Follow the prompts to create a username and password.
  3. Go back to http://127.0.0.1:8000/accounts/login/, enter your superuser credentials, and log in.
  4. You should be redirected to your homepage (/). Notice the “Hello, [username]!” message and the “Log Out” link in the navigation.
  5. Now, try visiting http://127.0.0.1:8000/protected/ again. You should see the content of your protected_page.html!
  6. Click “Log Out” in the navigation. You’ll be redirected to the logged_out.html page.

Congratulations! You’ve successfully implemented a basic login and logout system using Django’s built-in authentication.

Conclusion

In this guide, we’ve covered the essentials of setting up a simple but effective login system in Django. You learned how to leverage Django’s powerful django.contrib.auth application, configure redirect URLs, create basic login and logout templates, and protect specific views so that only authenticated users can access them.

This is just the beginning! Django’s authentication system also supports user registration, password change, password reset, and much more. Exploring these features will give you an even more robust and user-friendly system. Keep building, and happy coding!

Comments

Leave a Reply