User registration and authentication can be a tricky process in development for many developers, and especially beginners.
In this article, I'll take you step by step on how to go about the same in Django. This project's code can be found on GitHub
# This tutorial assumes you have Python and Django installed, and have basic understanding of the two.
To start navigate to your preferred directory where you will store your Django project with:
# In your cmd
cd <my_directory>
Run the commands:
django-admin startproject <project_name> .
django-admin startapp <app_name>
In your preferred code editor, navigate to your project's directory.
We can start coding our system; open the settings.py
file in the project directory and add the name of our app in the INSTALLED APPS
setting.
# Application definition
INSTALLED_APPS = [
'jazzmin', # (optional)
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'name_of_the_app', # replace with the name of the app you created
]
Open the models.py
file in your app and write the code below:
# models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
We are importing three modules; AbstractBaseUser
BaseUserManager
PermissionsMixin
. These will be extended from when creating our user models.
Let's define our first model:
class UserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
if not email:
raise ValueError("You need to provide an email to register!")
if not first_name:
raise ValueError("You must provide your last name!")
if not last_name:
raise ValueError("You must provide your last name!")
user = self.model(
email = self.normalize_email(email),
first_name = first_name,
last_name = last_name,
password = password,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, first_name, last_name, password=None):
user = self.create_user(
email = self.normalize_email(email),
first_name=first_name,
last_name = last_name,
password = password,
)
user.is_admin = True
user.is_active = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
We can then define the model for our user, and the fields we prefer them to have:
class RegularUser(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True)
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True, null=True)
last_login = models.DateTimeField(auto_now_add=True, null=True)
created_date = models.DateTimeField(auto_now_add=True, null=True)
modified_date = models.DateTimeField(auto_now_add=True, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = UserManager()
def __str__(self):
return f"{self.first_name} {self.last_name}"
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
Run our app's migrations by running:
# Windows
python manage.py makemigrations
python manage.py migrate
In our settings.py
file, add this code at the bottom:
AUTH_USER_MODEL = '<name_of_your_app>.RegularUser'
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']
Then comment out this part of code in the same file:
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
# AUTH_PASSWORD_VALIDATORS = [
# {
# 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
# },
# ]
Create a forms.py
file in the same directory as the models.py
file:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import RegularUser
class SignUpForm(UserCreationForm):
email = forms.EmailField()
class Meta():
model = RegularUser
fields = [
'email',
'first_name',
'last_name',
'password1',
'password2',
]
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput())
In the views.py
file, include this code:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, logout, authenticate
from .forms import SignUpForm, LoginForm
from django.contrib import messages
@login_required
def homepage(request):
user = request.user
first_name = request.user.first_name
last_name = request.user.last_name
context = {
'user': user,
'first_name': first_name,
'last_name': last_name,
}
return render(request, "homepage.html", context)
def signup_view(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.save()
return redirect("login")
else:
form = SignUpForm()
return render(request, "registration/signup.html", {'form': form})
def login_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect("dashboard")
else:
messages.error(request, "Invalid login credentials!")
else:
form = LoginForm()
return render(request, "registration/login.html", {'form': form})
@login_required
def logout_view(request):
logout(request)
messages.success(request, "You have been logged out!")
return redirect('login')
Create another file; urls.py
in the same directory as the views.py
and include this code:
from django.urls import path
from . import views
urlpatterns = [
path('', views.homepage, name="dashboard"),
path('signup/', views.signup_view, name="signup"),
path('login/', views.login_view, name="login"),
path('logout/', views.logout_view, name="logout"),
]
In the app directory
, create a folder named templates
alongside a file named homepage.html
with this code:
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<p>Hey {{ user.first_name }} {{ user.last_name }}!</p>
<h2>You are viewing the dashboard</h2>
</body>
</html>
In the templates directory, create another directory named registration
and create two HTML files:
signup.html
# signup.html
<!DOCTYPE html>
<html>
<head>
<title>Sign Up</title>
</head>
<body>
<h1>Sign Up</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
</body>
</html>
login.html
# login.html
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Log In</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Log In</button>
</form>
</body>
</html>
Open the urls.py
file in the project directory, and modify the code to include:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('<app_name>.urls')),
]
Save all the files and run the server with:
# Windows
python manage.py runserver
Fire up your browser and navigate to http://127.0.0.1:8000/
.
Users can signup for an account, and log in to your app!
*This article will continue to be updated for the better and ease of read*