Make login and registration forms using Django

Task

Implement a user authentication system. For this purpose, a registration form and login form are created on the website timthewebmaster.com.
The registration form must contain the following elements:
The login form should consist of only two fields:
There should also be a button that would allow you to exit the authenticated user mode.

Solution

Including jQuery to pages templates

For solving such case I need to include one JS library jQuery . This is a popular and simple library. And I need to change security settings of website developed on django. That means change a little bit of settings.py

Setup django for register new users

If be honest it is a not necessary step. But for security sake and for to be sure none of the hackers couldn’t broke up database of server and gain access to credentials of users.
In a file settings.py just add:

CSRF_USE_SESSIONS = True
			
In the app that main goal to register an user, open urls.py and add 2 more paths.

from django.urls import path
from .views import signup, signup_verify


urlpatterns = [
	…
# Это путь на страницу которая будет видна пользователю
    path('signup/', signup, name='signup'), 
# Это путь/адрес который мы будем использовать чтобы общаться с сервером
    path('signup/verify-signup/', signup_verify, name='signup_verify'),
]
			

Let’s create ajax request for user registration

Now it is a time of JS-script with POST request.

function OnSignup(){
	var form_data = new FormData();
	form_data.append("csrfmiddlewaretoken", csrftoken);
	form_data.append("username", $("#username").val())
	form_data.append("email", $("#email").val())
	form_data.append("password",  $("#password").val())
	form_data.append("repeated_password", $("#repeated_password").val())
	form_data.append("about", $("#about").val())
	form_data.append("file", document.getElementById('file').files[0]);
	$.ajax({
		type: "POST",
		// Path that we describe in urls.py
		url: "verify-signup/",
		// Which data to send
		data: form_data,
		processData: false,
		contentType: false,
		headers: {'X-CSRFToken': csrftoken},
		mode: 'same-origin', 
		// Function that gonna be execute if code eaqual 200
		success: function(result) {
			$(".hint-required").css("color","green")
			$("#common-error").text(result.common)	
			$("#username-error").text(result.username)	
			$("#email-error").text(result.email)	
			$("#password-error").text(result.password)	
			$("#repassword-error").text(result.password)	
		// Function that gonna be execute if code eaqual 200
			setTimeout(function(){
				window.location.href =  '/login/'
			},3000)
		},
		// Function that gonna be executed if error accure
		error: function(jqXHR, textStatus, errorThrown){
			$(".hint-required").css("color","red")
			$("#common-error").text(jqXHR.responseJSON.common)	
			$("#username-error").text(jqXHR.responseJSON.username)	
			$("#email-error").text(jqXHR.responseJSON.email)	
			$("#password-error").text(jqXHR.responseJSON.password)	
			$("#repassword-error").text(jqXHR.responseJSON.password)	
		}
	});
}

// Document ready and loaded
$(document).ready( function(){
	$("#signup").on('click',OnSignup)
})
		
If successful, that is, if all checks are passed, such as password length or existing email, I will give a feedback and redirect to the login page.
If unsuccessful, I will notify the user about this too.

Write down function to register new user to mysql database

In the pre-configuration chapter, we imported the signup_verify function in urls.py, let's define it

from django.shortcuts import render
from django.http import JsonResponse, HttpResponseRedirect
from django.template.defaultfilters import slugify
import re
from MyBlog import settings
from .models import User

...

def signup_verify(request):
    message = {
        'common': '',
        'username': 'обязательно',
        'email': 'обязательно',
        'password': 'обязательно',
        'repassword': 'обязательно',
    }
    status = 200
# We will only process POST requests
    if request.method == 'POST':
        # General mail pattern for comparison
        regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
	# We collect the data that was sent
        username = request.POST['username']
        email = request.POST['email']
        password = request.POST['password']
        repeated_password = request.POST['repeated_password']
        about = request.POST['about']
        avatar = None
        try:
            avatar = request.FILES['file']
        except:
            avatar = None

        message['common']='✖ I can't register a new user'
        # Name, email, password are empty
        if len(username) == 0:
            message['username']='⚠user field is empty'
            status = 406
        if len(email) == 0:
            message['email']='⚠ email field is empty'
            status = 406
        if len(password) == 0:
            message['password']='⚠ password field is empty’
            status = 406
        # Checking if the user already exists
	if User.objects.filter(name=username).exists() or User.objects.filter(slug=slugify(username)).exists():
            message['username']='⚠a user with the same name already exists'
            status = 406
        # User already exist
        if User.objects.filter(email=email).exists():
            message['email']='⚠This email is already in use'
            status = 406
        if len(username) < 3:
            message['username']='⚠the entered name is too short'
            status = 406
        if len(username) > 25:
            message['username']='⚠ the entered name is too long'
            status = 406
        # Check if password is long enough
        if len(password) < 6:
            message['password']='⚠the entered password is too short'
            status = 406
        # Are the passwords the same?
        if password != repeated_password:
            message['password']='⚠password does not match'
            message['repassword']='⚠ password does not match'
            status = 406
        # Is the mail format correct?
        if not re.fullmatch(regex, email):
            message['email']='⚠ Wrong mail format'
            status = 406
        if status == 200:
            message['common'] = '✔you have successfully registered, redirect'
            message['username'] = '✔ Ok'
            message['email'] = '✔ Ok'
            message['password'] = '✔ Ok'
            message['repassword'] = '✔ Ok'
# Saving data from the submitted form
            user = User(name=username, about=about, avatar=avatar, email=email, password=password)
            user.save()

        return JsonResponse(message, status=status)
    else:
        status = 403
        return JsonResponse(message, status=status)
		
This is how I identify form “errors” in Django.

Gather all together in registration page

Now, for everything to work, I need to create a template that would load the appropriate script and styles, use the token. Here is the form code

    {% csrf_token %}
	
<div class="form">
	<form enctype="multipart/form-data" class="form_form" id="toSignup" action="send_new_user" method="get">
		<div>
			<input class="form_el" placeholder="name" type="text" name="username" id="username">
			<div class="hint-container">
				<p id="username-error" class="hint-required">required</p>
				<p class="hint-error">from 3 to 25 letters</p>
			</div>
		</div>
		<div>
			<input class="form_el" placeholder="email" type="email" name="email" id="email">
			<div class="hint-container">
				<p id="email-error" class="hint-required">required</p>
				<p class="hint-error">right address of email</p>
			</div>
		</div>
		<div>
			<input class="form_el" placeholder="password" type="password" name="password" id="password">
			<div class="hint-container">
				<p id="password-error" class="hint-required">required</p>
				<p class="hint-error">at least 6 letters</p>
			</div>
		</div>
		<div>
			<input class="form_el" placeholder="repeat a password" type="password" name="repeated_password"  id="repeated_password">
			<div class="hint-container">
				<p id="repassword-error" class="hint-required">required</p>
				<p class="hint-error">has to match with password</p>
			</div>
		</div>
		<textarea class="form_el__about" placeholder="Tell me about yourself" name="about" rows=4  id="about"></textarea>
	</form> 
</div>
<div class="sel_file">
	<label for="texta">Choose your avatar.</label>
	<input class="form_el__file" placeholder="Choose a file" type="file" name="file" id="file">
</div>
<div class="buttons">
	<div id="signup" class="button button-middle">
		<a>Registration</a>
	</div>
</div>
	
							
And at the very bottom before the body tag, insert a script written in advance


	
<!-- Loading jQuery --> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
{% csrf_token %}
<!-- csrftoken has to be saved in JS variable, for later use -->
<script>
	const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
</script>
<!-- Loading a previously written registration request script -->
<script src="{% static 'User/js/signup.js' %}"></script>
	


							

Setup urls.py for user authentication

Need to add 2 additional paths and import corresponding functions

from .views import login, login_verify, logout


urlpatterns = [
# This function will clear the session of previously created variables
    path('logout/', logout, name='logout'),
# This function will display a login form for the user
    path('login/', login, name='login'),
# This function will set the appropriate session variables for the corresponding user and decide whether he can log in or not
    path('login/verify-login/', login_verify, name='login_verify'),
]
							

Writing down ajax request for login page with email

The principle is the same as during registration. We indicate the request type, request url and data that we want to transfer. And in addition, of course, feedback for the user. So that he knows about the mistakes he made when filling out the form. All this is in a separate file login.js

function OnLogin(){
	var username = $("#username").val()	
	var password = $("#password").val()	
	$.ajax({
		type: "POST",
		url:  'verify-login/',
		data: {
			'username': username,
			'password': password,
		},
		headers: {'X-CSRFToken': csrftoken},
		mode: 'same-origin', 
		success: function(result){
			$(".hint-required").css("color","green")
			$("#common-error").text(result.common)	
			$("#username-error").text(result.username)	
			$("#password-error").text(result.password)	
			setTimeout(function(){
				window.location.href = '/' 
			},1000)
		},
		error: function(jqXHR, textStatus, errorThrown){
			$(".hint-required").css("color","red")
			$("#common-error").text(jqXHR.responseJSON.common)	
			$("#username-error").text(jqXHR.responseJSON.username)	
			$("#password-error").text(jqXHR.responseJSON.password)	
		}
	})
}

$(document).ready( function(){
	$("#login").on('click',OnLogin)
})
							

Writing down function for managing user login

Here are ready-made functions for processing and checking data entered by the user

def login_verify(request):
    message = {
        'common': '',
        'username': 'required',
        'password': 'required',
    }
    status = 200
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        message['common']='✖ I can not enter'
        if len(username) == 0:
            message['username']='⚠username fiels is empty'
            status = 406
        if len(password) == 0:
            message['password']='⚠ password fiels is empty'
            status = 406
        required_user = User.objects.filter(name=username)
	# User already exist
        if required_user.exists():
        # The entered password matches the saved one
	if required_user.first().password == password:
                status = 200
		# Set the status of the current session as registered
                request.session["is_auth"] = True
		# We save the username in the current session variable
		#This may be useful for displaying information intended
		# Only for user
                request.session["username"] = username
                message['common'] = '✔ You have successfully logged in, redirect ... '
                message['username'] = '✔ Ok'
                message['password'] = '✔ Ok'
            else:
                message['password'] = '⚠ Wrong password'
                status = 406
        else:
            message['username'] = '⚠This user does not exist'
            status = 406

        return JsonResponse(message, status=status)
							
User exit function. I'm simply clearing the current user session on my site. And I redirect to the site login page.

def logout(request):
    request.session.flush()
    return HttpResponseRedirect("/login")
		

Template for authentication on website

And of course my template for logging into the site


	
<div id="common-error" class="hint-container hint-required hint-common_error"></div>
{% csrf_token %}
<div class="form">
	<form  class="form_form form_login" id="toLogin" action="send_new_user" method="get">
		<div>
			<input class="form_el" placeholder="username" type="text" name="username" autocomplete="off" id="username"><br><br>
			<div class="hint-container">
				<p id="username-error" class="hint-required">required</p>
			</div>
		</div>
		<div>
			<input class="form_el" placeholder="password" type="password" name="password" autocomplete="off" id="password"><br><br>
			<div class="hint-container">
				<p id="password-error" class="hint-required">required</p>
			</div>
		</div>
	</form> 
</div>
<div class="buttons">
	<div id="login" class="button button-middle">
		<a>Login</a>
	</div>
	<div class="button button-middle">
		<a href="{% url 'signup' %}">
		Registration
		</a>
	</div>
</div>
	
	
							
And of course, don’t forget to insert the script into the template. The login.js and jQuery library we wrote



 	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    {% csrf_token %}
    <script>
        const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    </script>
    <script src="{% static 'User/js/login.js' %}"></script>


		

In Conclusion

In this case, I demonstrated two main forms for a user authentication system. Registration form and login form. Not the most difficult thing, especially if you know what you're doing.
I want to make a reservation right away: I did not add a captcha or email verification here for one simple reason. This is authentication on my site and I didn't need it. In my activities, it is not the number of users that is important, but their quality. That is, if a person wants to contact me, he will contact me, if not, well, that’s his business.

Additional content

Github repository

The repository that I use to develop this site
Specifically in this case, you will be interested in the following files:

Content that I’ve used to learn


heart 1
3 connected dots 0

Comments

(0)
Avatar by default
None
Leave a comment
Leave a comment