Django Custom Authentication | Registration, Login, Logout, ResetPassword, UserProfile And AdminProfile
Start a project
django-admin startproject registrationForm
Project directory
![](https://miro.medium.com/v2/resize:fit:865/1*eW-mLXTqvbe3UO0ODy7imQ.png)
registration/settings.py
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
# Used for authentication
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Custom app
'enroll',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
# Used for authentication
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
# Used for authentication
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
registration/urls.py
from django.contrib import admin
from django.urls import path
from enroll import views
urlpatterns = [
path('admin/', admin.site.urls),
path('signup/', views.sign_up, name='signup'),
path('login/', views.user_login, name='login'),
path('profile/', views.user_profile, name='profile'),
path('logout/', views.user_logout, name='logout'),
path('changepassword/', views.user_change_password,
name='changepassword'),
path('changepassword2/', views.user_change_password2,
name='changepassword2'),
path('userdetail/<int:id>', views.user_detail,
name='userdetail'),
]
enroll/forms.py
from django.contrib.auth.models import User
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class SignUpForm(UserCreationForm):
password2 = forms.CharField(label='Confirm Password (again)',
widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email']
labels = {'email': 'Email'}
class EditUserProfileForm(UserChangeForm):
password = None
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email',
'date_joined', 'last_login']
labels = {'email': 'Email'}
class EditAdminProfileForm(UserChangeForm):
password = None
class Meta:
model = User
fields = '__all__'
labels = {'email': 'Email'}
enroll/views.py
from django.shortcuts import render, HttpResponseRedirect
from .forms import SignUpForm, EditUserProfileForm, \
EditAdminProfileForm
from django.contrib import messages
from django.contrib.auth.forms import AuthenticationForm, \
PasswordChangeForm, SetPasswordForm, UserChangeForm
from django.contrib.auth import authenticate, login, logout, \
update_session_auth_hash
from django.contrib.auth.models import User
def sign_up(request):
if request.method == "POST":
fm = SignUpForm(request.POST)
if fm.is_valid():
messages.success(request, 'Account created successfully')
fm.save()
return HttpResponseRedirect('/login/')
else:
fm = SignUpForm()
return render(request, 'enroll/signup.html', {'form': fm})
def user_login(request):
if not request.user.is_authenticated:
if request.method == "POST":
fm = AuthenticationForm(request=request, data=request.POST)
if fm.is_valid():
user_name = fm.cleaned_data['username']
user_password = fm.cleaned_data['password']
user = authenticate(username=user_name, password=user_password)
if user is not None:
login(request, user)
messages.success(request, 'Logged in successfully !!')
return HttpResponseRedirect('/profile/')
else:
fm = AuthenticationForm()
return render(request, 'enroll/userlogin.html', {'form': fm})
else:
return HttpResponseRedirect('/profile/')
def user_profile(request):
if request.user.is_authenticated:
if request.method == "POST":
if request.user.is_superuser == True:
fm = EditAdminProfileForm(request.POST, instance=request.user)
users = User.objects.all()
else:
fm = EditUserProfileForm(request.POST, instance=request.user)
users = None
if fm.is_valid():
messages.success(request, 'Profile updated')
fm.save()
else:
if request.user.is_superuser == True:
fm = EditAdminProfileForm(instance=request.user)
users = User.objects.all()
else:
fm = EditUserProfileForm(instance=request.user)
users = None
return render(request, 'enroll/profile.html',
{'name': request.user.username, 'form': fm, 'users': users})
else:
return HttpResponseRedirect('/login/')
def user_logout(request):
logout(request)
return HttpResponseRedirect('/login/')
# Change password with old password
def user_change_password(request):
if request.user.is_authenticated:
if request.method == "POST":
fm = PasswordChangeForm(user=request.user, data=request.POST)
if fm.is_valid():
fm.save()
# Update user session
update_session_auth_hash(request, fm.user)
messages.success(request, 'Password changed successfully')
return HttpResponseRedirect('/profile/')
else:
fm = PasswordChangeForm(user=request.user)
return render(request, 'enroll/changePassword.html', {'form': fm})
else:
return HttpResponseRedirect('/login/')
# Change password without old password
def user_change_password2(request):
if request.user.is_authenticated:
if request.method == "POST":
fm = SetPasswordForm(user=request.user, data=request.POST)
if fm.is_valid():
fm.save()
# Update user session
update_session_auth_hash(request, fm.user)
messages.success(request, 'Password changed successfully')
return HttpResponseRedirect('/profile/')
else:
fm = SetPasswordForm(user=request.user)
return render(request, 'enroll/changePassword2.html', {'form': fm})
else:
return HttpResponseRedirect('/login/')
def user_detail(request, id):
if request.user.is_authenticated:
pi = User.objects.get(pk=id)
fm = EditAdminProfileForm(instance=pi)
return render(request, 'enroll/userdetail.html',
{'name': request.user.username,'form': fm})
else:
return HttpResponseRedirect('/login/')
![](https://miro.medium.com/v2/resize:fit:853/1*vMMKlO7YgwDGmlpRAF5Y3Q.png)
templates/signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration form</title>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<style>
/* Custom styles if needed */
body {
}
.custom-form {
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.success {
color: green;
}
</style>
</head>
<body>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6 custom-form">
<form action="" method="post" novalidate class="needs-validation">
{% csrf_token %}
{% for fm in form %}
<div class="form-group">
{{ fm.label_tag }}
{{ fm }}
<small class="text-danger">{{ fm.errors|striptags }}</small>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">SignUp</button>
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="er">{{error}}</p>
{% endfor %}
{% endif %}
</form>
<br>
<!-- <a class="btn btn-outline-primary" href="{% url 'login' %}">Login</a> -->
{% if messages %}
{% for message in messages %}
<small class="d-block mt-2 {% if message.tags %}{{ message.tags }}{% endif %}">{{ message }}</small>
{% endfor %}
{% endif %}
</div>
</div>
</div>
<!-- Include Bootstrap JS and Popper.js (optional) -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
templates/uselogin.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User login</title>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<style>
body {
}
.login-container {
max-width: 400px;
margin: auto;
padding: 20px;
margin-top: 100px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.er {
color: red;
}
</style>
</head>
<body>
<div class="login-container">
<form action="" method="post" novalidate>
{% csrf_token %}
{% for fm in form %}
<div class="form-group">
{{ fm.label_tag }}
{{ fm }}
<small class="form-text text-danger">{{ fm.errors|striptags }}</small>
</div>
{% endfor %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="er">{{ error }}</p>
{% endfor %}
{% endif %}
<button type="submit" class="btn btn-primary">Login</button>
</form>
<br>
<!-- <a class="btn btn-outline-primary" href="{% url 'signup' %}">SignUp</a> -->
</div>
<!-- Include Bootstrap JS and Popper.js (optional) -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
templates/profile.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User profile</title>
<!-- Bootstrap CSS link (make sure to include it) -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body class="bg-light">
<div class="container mt-5">
<div class="jumbotron">
<div style=" padding: 20px; color: #fff; border-radius: 10px;">
<h2 class="display-4 text-sm mt-2" style="font-size: 2.5rem;font-weight: bold;">User Profile</h2>
<h5 style="color: #ecf0f1;">Welcome {{name}}</h5>
{% if users != None %}
<h5 style="color: #ecf0f1;">List of users</h5>
{% for user in users %}
<a href="{% url 'userdetail' user.id %}" style="color: #ffffff;">{{user.username}}</a><br>
{% endfor %}
{% endif %}
</div><br>
{% if messages %}
{% for message in messages %}
<div class="alert {% if message.tags %} alert-{{message.tags}}" {% endif %} role="alert">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form action="" method="post">
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p>{{error}}</p>
{% endfor %}
{% endif %}
{% for fm in form %}
{{ fm.label_tag }} {{ fm }} {{ fm.errors|striptags }}<br><br>
{% endfor %}
<input type="submit" value="Save" class="btn btn-primary">
</form><br>
<a class="btn btn-primary" href="{% url 'changepassword' %}">Change Password</a>
<a class="btn btn-primary" href="{% url 'changepassword2' %}">Change Password2</a>
<a class="btn btn-primary" href="{% url 'logout' %}">Logout</a>
</div>
</div>
<!-- Bootstrap JS and Popper.js (optional) -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
templates/changepassword.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Change Password</title>
</head>
<body class="bg-light">
<form action="" method="post" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p>{{error}}</p>
{% endfor %}
{% endif %}
{% for fm in form %}
{{ fm.label_tag }} {{ fm }} {{ fm.errors|striptags }}<br><br>
{% endfor %}
<input type="submit" value="Save">
</form><br><br>
<a href="{% url 'logout' %}">Logout</a><br><br>
<a href="{% url 'profile' %}">Profile</a><br><br>
</body>
</html>
templates/changepassword2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Change Password</title>
</head>
<body class="bg-light">
<form action="" method="post" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p>{{error}}</p>
{% endfor %}
{% endif %}
{% for fm in form %}
{{ fm.label_tag }} {{ fm }} {{ fm.errors|striptags }}<br><br>
{% endfor %}
<input type="submit" value="Save">
</form><br><br>
<a href="{% url 'logout' %}">Logout</a><br><br>
<a href="{% url 'profile' %}">Profile</a><br><br>
</body>
</html>
templates/userdetail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Detail</title>
<!-- Bootstrap CSS link (make sure to include it) -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body class="bg-light">
<div class="container mt-5">
<div class="jumbotron" style=" color: #fff; padding: 20px; border-radius: 10px;">
<h3 class="display-4 text-sm mt-2 font-weight-bold" style="font-size: 2.5rem;">User Profile</h3>
<h3 style="font-size: 1.5rem;">Welcome {{name}}</h3>
</div>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="mt-3">
<a class="btn btn-primary" href="{% url 'profile' %}">Profile</a>
<a class="btn btn-primary" href="{% url 'logout' %}">Logout</a>
</div>
</div>
<!-- Bootstrap JS and Popper.js (optional) -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
Perform migration
python manage.py makemigrations
python manage.py migrate
Run server
python manage.py runserver
![](https://miro.medium.com/v2/resize:fit:873/1*KRonsSf1YrpsAmP_5PMBdQ.png)
Output
User registration
![](https://miro.medium.com/v2/resize:fit:875/1*kEVl-ap4fw9_nWueHwH6ug.png)
User login
![](https://miro.medium.com/v2/resize:fit:875/1*PMg0IVooJtFj8yQZ-f6nMg.png)
User profile
![](https://miro.medium.com/v2/resize:fit:875/1*nnbEJd7PA9zTqiJpN6B1pA.png)
![](https://miro.medium.com/v2/resize:fit:875/1*6h-xM_WR_dqAKyIXak1Wpw.png)
User details
![](https://miro.medium.com/v2/resize:fit:875/1*2HeYicTpDRm47KLvkHEBRw.png)
![](https://miro.medium.com/v2/resize:fit:875/1*JhFOIbs9M4bBf503PBMg8Q.png)
Chane password with old password
![](https://miro.medium.com/v2/resize:fit:875/1*S1pUTF4hfA7qj211Gvsf1A.png)
Chane password without old password
![](https://miro.medium.com/v2/resize:fit:875/1*qaFuWPjycLhq0in-ukq14Q.png)
Show and update user profile
![](https://miro.medium.com/v2/resize:fit:855/1*LwBTPGo5_RiteLkREwa6aw.png)
Django Login Form
Django Login