User Authentication
In django there are many ways to authenticate users. Here are some of the most common ways to authenticate users in django:
We are assuming to use built-in User
model or (Create a custom user model using AbstractBaseUser
and BaseUserManager
classes.)
- No built-in function used (Own Data Cleaning Process)
- Using built-in
form
- Use third-party packages like
django-allauth
,django-rest-auth
,django-rest-framework
, etc. - Use
UserCreationForm
.
The most common way is to use the built-in authentication system. This system is based on the User
model and provides a way to authenticate users and manage their permissions.
1. No built-in function used
Register & Login Views
Create a view to register, login and logout a new user.
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth import logout, login, authenticate
def register(request):
if request.method == 'POST':
first_name = request.POST['first_name']
last_name = request.POST['last_name']
username = request.POST['username']
email = request.POST['email']
password = request.POST['password']
password2 = request.POST['password2']
if password == password2:
if User.objects.filter(username=username).exists():
messages.error(request, 'Username is already taken')
return redirect('register')
else:
if User.objects.filter(email=email).exists():
messages.error(request, 'Email is already taken')
return redirect('register')
else:
user = User.objects.create_user(username=username, email=email, password=password, first_name=first_name, last_name=last_name)
user.save()
# Login after register
# auth.login(request, user)
# messages.success(request, 'You are now logged in')
# return redirect('index')
messages.success(request, 'Account created successfully')
return redirect('login')
else:
messages.error(request, 'Passwords do not match')
return redirect('register')
else:
return render(request, 'users/register.html')
def 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('index')
else:
messages.error(request, 'Invalid username or password')
return render(request, 'users/login.html')
def logout(request):
"""
Handles the logout of the user.
If the request method is POST, it logs out the user and redirects to the index page.
If the request method is GET, it renders the logout page.
"""
if request.method == 'POST':
logout(request)
messages.success(request, f'You have been logged out!')
return redirect('index')
return render(request, 'users/logout.html')
Register & Login Templates
<h2>Register</h2>
<form method="post">
{% csrf_token %}
<div>
<label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name" required>
</div>
<div>
<label for="last_name">Last Name</label>
<input type="text" id="last_name" name="last_name" required>
</div>
<div>
<label for="username">Username</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<label for="password2">Confirm Password</label>
<input type="password" id="password2" name="password2" required>
</div>
<button type="submit">Register</button>
</form>
<small>Already have an account? <a href="{% url 'login' %}">Login</a></small>
<h2>Login</h2>
<form method="post">
{% csrf_token %}
<div>
<label for="username">Username</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Login</button>
<a href="{% url 'password_reset' %}">Forgot Password?</a>
</form>
Need an account? <a href="{% url 'register' %}">Register</a>
Adding Views to URLs
Add the following urls to the urls.py
file.
from django.urls import path
from . import views
urlpatterns = [
path('register/', views.register, name='register'),
path('login/', views.login, name='login'),
path('logout/', views.logout, name='logout'),
]
2. Use third-party packages
You can also use third-party packages like django-allauth
, django-rest-auth
, django-rest-framework
, etc.
3. Create a custom user model
4. Use UserCreationForm
Create a user registration form
- We are using default
User
model, but you can also create a custom user model usingAbstractBaseUser
andBaseUserManager
classes. See
Creating a user registration form using UserCreationForm
and UserChangeForm
is very easy. You can use these forms to create and update users.
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class UserForm(UserCreationForm):
# You can add additional fields here
class Meta:
model = User
# fields to be displayed in the form
fields = ['username', 'email', 'password1', 'password2']
# With UserChangeForm
class UserUpdateForm(UserChangeForm):
class Meta:
model = User
fields = ['username', 'email']
# Without UserChangeForm
class UserUpdateForm(forms.ModelForm):
# You can add additional fields here
class Meta:
model = User
# fields to be displayed in the form
fields = ['username', 'email', 'first_name', 'last_name']
Creating views
Create a view to register, logout and delete_user a new user.
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserForm, UserUpdateForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout, login, authenticate
def register(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('login')
else:
form = UserForm()
return render(request, 'users/register.html', {'form': form})
@login_required
def logout(request):
"""
Handles the logout of the user.
If the request method is POST, it logs out the user and redirects to the index page.
If the request method is GET, it renders the logout page.
"""
if request.method == 'POST':
logout(request)
messages.success(request, f'You have been logged out!')
return redirect('index')
return render(request, 'users/logout.html')
@login_required
def delete_user(request):
"""
Handles the deletion of the user.
If the request method is POST, it deletes the user and redirects to the index page.
If the request method is GET, it renders the delete user page.
"""
if request.method == 'POST':
request.user.delete()
messages.success(request, f'Your account has been deleted!')
return redirect('index')
return render(request, 'users/delete_user.html')
Add urls
- Add the following urls to the
urls.py
file.
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
urlpatterns = [
path('register/', views.register, name='register'),
path('logout/', views.logout, name='logout'),
path('delete_user/', views.delete_user, name='delete_user'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html'), name='password_reset'),
path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'), name='password_reset_done'),
path('password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'), name='password_reset_confirm'),
path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'), name='password_reset_complete'),
]
Creating templates
Create a template for login, password reset, etc to render the form.
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
<small>Already have an account? <a href="{% url 'login' %}">Login</a></small>
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
<a href="{% url 'password_reset' %}">Forgot Password?</a>
</form>
Need an account? <a href="{% url 'register' %}">Register</a>
<h2>Password Reset</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Request Reset Password</button>
</form>
<h2>Password Reset Done</h2>
<p>We have sent you an email with a link to reset your password.</p>
<h2>Password Reset Confirm</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Reset Password</button>
</form>
<h2>Password Reset Complete</h2>
<p>Your password has been reset successfully.</p>
<a href="{% url 'login' %}">Login</a>
<h2>Delete User</h2>
<p>Are you sure you want to delete your account?</p>
<p><strong>Username:</strong> {{ user.username }}</p>
<p><strong>Email:</strong> {{ user.email }}</p>
<form method="post">
{% csrf_token %}
<button type="submit">Delete</button>
<a href="{% url 'index' %}">Cancel</a>
</form>
<h2>Logout</h2>
<p>Are you sure you want to logout?</p>
{% if request.user.is_authenticated %}
<form method="post">
{% csrf_token %}
<button type="submit">Logout</button>
<a href="{% url 'index' %}">Cancel</a>
</form>
{% else %}
<a href="{% url 'login' %}">Login Again</a> |
<a href="{% url 'register' %}">Register</a>
{% endif %}
Custom login view
- You can also add custom login view, password reset view, etc.
from django.contrib.auth import views as auth_views
def 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('index')
else:
messages.error(request, 'Invalid username or password')
return render(request, 'users/login.html')
Add settings
Add the following settings to the settings.py
file.
# Redirect to home page on login
LOGIN_REDIRECT_URL = 'index'
# Login URL for login_required decorator when user is not logged in
LOGIN_URL = 'login'
# Logout URL for logout view when user is logged in
LOGOUT_URL = 'logout'
# Email Password Reset Settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASS')
Add above environment variables to the .env
file.
EMAIL_USER = username
EMAIL_PASS = password