Create Authentication System in Django - Login and Signup Forms

Faraz

By Faraz - July 30, 2024

Learn how to create a simple and secure authentication system in Django. Follow this step-by-step guide for login and registration. Perfect for beginners.


create-authentication-system-in-django-login-and-registration-forms.webp

Creating an authentication system in Django is essential for any web application that requires user accounts. This guide will walk you through the process of setting up a simple and secure login and registration system using Django. Whether you're a beginner or looking to refresh your skills, this step-by-step tutorial will help you implement user authentication in your Django project effortlessly.

Prerequisites

Before we dive in, make sure you have a basic understanding of Django and web development. You'll need the following tools and libraries installed on your machine:

  • Python (version 3.6 or higher)
  • Django (version 3.0 or higher)
  • A text editor or IDE (such as VS Code or PyCharm)
  • Basic knowledge of HTML and CSS

Setting Up the Development Environment

Installing Django

Before starting, ensure you have Python installed. You can install Django using pip:

pip install django

Creating a new Django project

Create a new Django project using the following command:

django-admin startproject auth_system

Setting up the project structure

Navigate into your project directory:

cd auth_system

Create a Django App

Create a new app within your project:

python manage.py startapp accounts

Adding the app to the project

In auth_system/settings.py, add accounts to the INSTALLED_APPS list:

INSTALLED_APPS = [
    'accounts',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Creating the Authentication System

Create Forms

In accounts, create a new file named forms.py and add the following function:

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class RegisterForm(UserCreationForm):
    email = forms.EmailField(required=True)

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

Creating the Views

Next, we’ll create views to handle registration and login system. Open accounts/views.py and add the following:

from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import RegisterForm

def register(request):
    if request.method == 'POST':
        form = RegisterForm(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('auth_login')
        else:
            messages.error(request, 'Registration failed. Please correct the errors below.')
    else:
        form = RegisterForm()
    return render(request, 'register.html', {'form': form})

def user_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)
                return redirect('auth_welcome')
            else:
                messages.error(request, 'Invalid username or password.')
        else:
            messages.error(request, 'Invalid username or password.')
    else:
        form = AuthenticationForm()
    return render(request, 'login.html', {'form': form})

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

def logout_view(request):
    logout(request)
    return redirect('auth_login')

Set Up URL Routing

Add a URL pattern for your view. In accounts/urls.py (create this file if it doesn't exist), add:

from django.urls import path
from django.shortcuts import redirect
from . import views

urlpatterns = [
    path('', lambda request: redirect('auth_login')),
    path('register/', views.register, name='auth_register'),
    path('login/', views.user_login, name='auth_login'),
    path('welcome/', views.welcome, name='auth_welcome'),
    path('logout/', views.logout_view, name='auth_logout'),
]

Include the app's URLs in your project's URL configuration. Open auth_system/urls.py and include the auth app URLs:

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('accounts.urls')),
]

Create Templates

Create templates for registration, login, and welcome in accounts/templates/.

register.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #1f1d2b;
            font-family: 'Poppins', sans-serif;
            margin: 0;
        }
        .form-container {
            background: #fff;
            padding: 3rem;
            border-radius: 15px;
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
            animation: bounceIn 1s ease-out;
            width: 400px;
        }
        .form-container h2 {
            text-align: center;
            margin-bottom: 2rem;
            color: #333;
            font-weight: bold;
            text-transform: uppercase;
        }
        .form-container form {
            display: flex;
            flex-direction: column;
        }
        .form-group {
            position: relative;
            margin-bottom: 1.5rem;
        }
        .form-group input {
            width: -webkit-fill-available;
            padding: 1rem;
            padding-left: 2rem;
            border: 1px solid #ddd;
            border-radius: 5px;
            transition: all 0.3s ease;
        }
        .form-group input:focus {
            border-color: #007bff;
            box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
        }
        .form-group label {
            position: absolute;
            top: 50%;
            left: 2rem;
            transform: translateY(-50%);
            color: #aaa;
            font-size: 1rem;
            pointer-events: none;
            transition: all 0.3s ease;
        }
        .form-group input:focus + label,
        .form-group input:not(:placeholder-shown) + label {
            top: 0;
            left: 1rem;
            transform: translateY(-50%);
            background: #fff;
            padding: 0 0.25rem;
            color: #007bff;
            font-size: 0.8rem;
        }
        .form-group i {
            position: absolute;
            top: 50%;
            left: 0.75rem;
            transform: translateY(-50%);
            color: #aaa;
        }
        button {
            padding: 1rem;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 1rem;
            transition: background 0.3s ease;
        }
        button:hover {
            background: #0056b3;
        }
        @keyframes bounceIn {
            from {
                opacity: 0;
                transform: scale(0.5);
            }
            to {
                opacity: 1;
                transform: scale(1);
            }
        }
        .error {
            color: red;
            font-size: 0.9rem;
            margin-bottom: 1rem;
        }
        .error ul{
            margin: 0;
        }
    </style>
</head>
<body>
    <div class="form-container">
        <h2>Register</h2>
        {% if messages %}
            {% for message in messages %}
                <div class="error">{{ message }}</div>
            {% endfor %}
        {% endif %}
        <form method="post">
            {% csrf_token %}
            <div class="form-group">
                <input type="text" id="username" name="username" required placeholder=" ">
                <label for="username">Username</label>
                <i class="fas fa-user"></i>
            </div>
                {% if form.username.errors %}
                    <div class="error">{{ form.username.errors }}</div>
                {% endif %}
            <div class="form-group">
                <input type="email" id="email" name="email" required placeholder=" ">
                <label for="email">Email</label>
                <i class="fas fa-envelope"></i>
            </div>
            {% if form.email.errors %}
                    <div class="error">{{ form.email.errors }}</div>
                {% endif %}
            <div class="form-group">
                <input type="password" id="password1" name="password1" required placeholder=" ">
                <label for="password1">Password</label>
                <i class="fas fa-lock"></i>
            </div>
            {% if form.password1.errors %}
                    <div class="error">{{ form.password1.errors }}</div>
                {% endif %}
            <div class="form-group">
                <input type="password" id="password2" name="password2" required placeholder=" ">
                <label for="password2">Confirm Password</label>
                <i class="fas fa-lock"></i>
            </div>
            {% if form.password2.errors %}
                <div class="error">{{ form.password2.errors }}</div>
            {% endif %}
            <button type="submit">Register</button>
        </form>
    <p>Have an Account? <a href="http://127.0.0.1:8000/login/">Login Here</a>
    </div>
</body>
</html>

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #1f1d2b;
            font-family: 'Poppins', sans-serif;
            margin: 0;
        }
        .form-container {
            background: #fff;
            padding: 3rem;
            border-radius: 15px;
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
            animation: slideIn 1s ease-out;
            width: 400px;
        }
        .form-container h2 {
            text-align: center;
            margin-bottom: 2rem;
            color: #333;
            font-weight: bold;
            text-transform: uppercase;
        }
        .form-container form {
            display: flex;
            flex-direction: column;
        }
        .form-group {
            position: relative;
            margin-bottom: 1.5rem;
        }
        .form-group input {
            width: -webkit-fill-available;
            padding: 1rem;
            padding-left: 2rem;
            border: 1px solid #ddd;
            border-radius: 5px;
            transition: all 0.3s ease;
        }
        .form-group input:focus {
            border-color: #28a745;
            box-shadow: 0 0 5px rgba(40, 167, 69, 0.5);
        }
        .form-group label {
            position: absolute;
            top: 50%;
            left: 2rem;
            transform: translateY(-50%);
            color: #aaa;
            font-size: 1rem;
            pointer-events: none;
            transition: all 0.3s ease;
        }
        .form-group input:focus + label,
        .form-group input:not(:placeholder-shown) + label {
            top: 0;
            left: 1rem;
            transform: translateY(-50%);
            background: #fff;
            padding: 0 0.25rem;
            color: #28a745;
            font-size: 0.8rem;
        }
        .form-group i {
            position: absolute;
            top: 50%;
            left: 0.75rem;
            transform: translateY(-50%);
            color: #aaa;
        }
        button {
            padding: 1rem;
            background: #28a745;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 1rem;
            transition: background 0.3s ease;
        }
        button:hover {
            background: #218838;
        }
        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateX(-100px);
            }
            to {
                opacity: 1;
                transform: translateX(0);
            }
        }
        .error {
            color: red;
            font-size: 0.9rem;
            margin-bottom: 1rem;
        }
        .error ul {
            margin: 0;
        }
    </style>
</head>
<body>
    <div class="form-container">
        <h2>Login</h2>
        {% if messages %}
            <div class="error">
                {% for message in messages %}
                    <p>{{ message }}</p>
                {% endfor %}
            </div>
        {% endif %}
        <form method="post">
            {% csrf_token %}
            <div class="form-group">
                <input type="text" id="username" name="username" required placeholder=" ">
                <label for="username">Username</label>
                <i class="fas fa-user"></i>
            </div>
                {% if form.username.errors %}
                    <div class="error">{{ form.username.errors }}</div>
                {% endif %}
            <div class="form-group">
                <input type="password" id="password" name="password" required placeholder=" ">
                <label for="password">Password</label>
                <i class="fas fa-lock"></i>
            </div>
            {% if form.password.errors %}
                    <div class="error">{{ form.password.errors }}</div>
                {% endif %}
            <button type="submit">Login</button>
        </form>
        <p>Not a member? <a href="http://127.0.0.1:8000/register/">Sign up now</a>
    </div>
</body>
</html>

welcome.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #1f1d2b;
            color: #fff;
            font-family: 'Poppins', sans-serif;
            margin: 0;
        }
        .welcome-container {
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="welcome-container">
        <h1>Welcome, {{ user.username }}!</h1>
        <p>You have successfully logged in.</p>
        <a href="{% url 'auth_logout' %}" style="color: #007bff; text-decoration: none;">Logout</a>
    </div>
</body>
</html>

Run Your Server

Apply migrations and run your server:

python manage.py migrate
python manage.py runserver

Open your browser and go to http://127.0.0.1:8000/ to see your authentication application in action.

Full Authentication App Project Structure

auth_system/
├── auth_system/
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── accounts/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations/
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   ├── views.py
│   └── templates/
│           ├── login.html
│           ├── register.html
│           └── welcome.html
├── manage.py
└── requirements.txt

Conclusion

By following this guide, you have successfully created a basic authentication system in Django. This includes user registration and login functionality. With these foundations in place, you can further customize and expand your system to meet the specific needs of your application. Secure user authentication is a crucial aspect of web development, and mastering it will make your Django projects more robust and user-friendly.

That’s a wrap!

I hope you enjoyed this article

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺