Authentication in Django using Python Decorators

In this article, we are going to talk a bit about Python Decorators, its use cases, advantages, and also we will see how we can…

The post Authentication in Django using Python Decorators appeared first on CodeSource.io.


This content originally appeared on CodeSource.io and was authored by Taminoturoko Briggs

In this article, we are going to talk a bit about Python Decorators, its use cases, advantages, and also we will see how we can use them for authentication in Django.

Prerequisite

To follow up on this tutorial, you should be familiar with Python and Django framework.

Note

All the demonstration codes were tested with Python 3.8.10 and Django 3.2 but it should work with other versions.

What is a Python Decorator

A Python Decorator is a function or class that takes in another function and modifies or adds extra functionality to the function.

Let’s look at some examples to properly understand what python Decorators are

Technical examples of Decorators

In python you can pass a function as an argument to another function. Let’s see how we can use that to create a Decorator that adds extra functionality to a function.

def decorator_function(func):
  print("adding extra functionality")
  return func()

def decorated_function():
  print("decorated function")

decorated_function = decorator_function(decorated_function)

#OUTPUT
# adding extra functionality
# decorated function

In this example we took the decorated_function as argument to our decorated_function, then we added extra functionality before returning our decorated_function. Notice we Instantiated our decorator_function with the decorated_function then assigned it to a variable called decorated_function. This is how you define can define Decorators, however this isn’t the typical Python way of defining Decorators.
Let’s see an example of how Python prefers Decorators to be defined.

def decorator_function(func):
  print("adding extra functionality")
  return func()

@decorator_function
def decorated_function():
  print("decorated function")

#OUTPUT
# adding extra functionality
# decorated function

The above codes won’t suffice when working with arguments in our decorated_function. To work with arguments, you have to modify the code to look like this:

def decorator_function(func):
  print("adding extra functionality")
  def wrapper(arg):
    return func(arg)
  return wrapper

@decorator_function
def decorated_function(name):
  print("decorated function")

# You call the function like this:
decorated_function("tammy")

but in this code we are not making use of the argument. Below is an example of how you can use the argument.

def decorator_function(func):
  def wrapper(arg):
    upper = arg.upper()
    return func(upper)
  return wrapper

@decorator_function
def decorated_function(name):
  print("your can call me", name)

decorated_function("tammy")

#OUTPUT
#TAMMY

In the above code we called the decorated_function with the argument “tammy”, then we modified or changed it to uppercase before printing it.
This is an example of how decorators can be used to modify a function. You can read more on decorators here:

https://book.pythontips.com/en/latest/decorators.html.
Let’s look at some advantages of python decorators

Advantages of Python Decorator

  1. It extends the functionality of functions without modifying the internal code of the functions.
  2. You can use any number of Decorators in on a function in any order.

Now that we know about Python Decorators, let’s see how they can be used for authentication in Django by building an authentication system.

Building an authentication system

In this section we are going to build a login system that will be used to authenticate user credentials, using a Python decorator to add the authentication logic. But first let us start by setting up a new Django project.

Setting up Django

  1. Install Django.
  2. Create a new project.
  3. Create an app inside the project.
  4. Migrate your project.
  5. Create a url.py file in your app.
  6. Create a forms.py file in your app.

You can accomplish all this with the following commands.

$ python -m pip install django==3.2
$ django-admin startproject authDecorator
$ cd authDecorator
$ python manage.py startapp authApp
$ python manage.py migrate
$ cd authApp
$ type nul > urls.py
$ type nul > forms.py

You now have an authDecorator project and authApp app setup. Now you need to tell Django about the app you created and the location of the app url.py file. You can do this by modifying the authDecorator/settings.py file. First, we will add the app by modifying the INSTALLED_APPS:

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "authApp",
]

Once you have added it, go over to the urls.py **file in the same directory and modify the *urlpatterns* by including your app urls.

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('authApp.urls'))
]

Now that we have done that, let’s start building the login system to be used for user authentication. We will first create a login form then later on we will add the authentication logic.

Creating a registration view

In this section we will create a simple view to allow user registration. Initially, we will create a form to allow the user to enter their username and password, then later on we will build the logic for the form.

Creating a registration form
We are going to user the UserCreationForm provided to us by Django. This form handles the creation of a new user. It has three default fields namely username, password1 and password2. To use this form you have to first import it from django.contrib.auth.forms like this:

from django.contrib.auth.forms import UserCreationForm

Unfortunately, Django doesn’t provide any logic to handle this form, so we have to manually create the logic.

Creating registration logic
Edit the views.py file of the authApp application and add the following code to it:
authApp/views.py

from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect

def register_view(request):
    if request.method == 'POST':
        register_form = UserCreationForm(request.POST)
        if register_form.is_valid():
            register_form.save()
            return redirect('login')
    else:
        register_form = UserCreationForm()
    return render(request, 'register.html', {'register_form': register_form})

this is what our register_view does: when the register_view is called with a GET request, we instantiate a new registration form with register_form = UserCreationForm() to be displayed in the template. When the user submits the form via POST we do the following:

  • Instantiate the form with the submitted data with register_form = UserCreationForm(request.POST).
  • Check if the form is valid. If it is not valid, the form will be re-rendered.
  • Once the form is valid we will save the form and redirect to the login page.

Now that we have created the logic for the registration view, we need to add the URL pattern for this view. In the urls.py file of the authApp application, add the following code:

from django.urls import path
from . import views
urlpatterns = [
    path('register/', views.register_view, name='register'),
]

The registration view can now be accessed by a URL. It is time to create a template for this view. Create a templates directory and a register.html file in the templates directory. You can do this with the following command:
authDecorator/authApp

$ mkdir templates
$ cd templates
$ type nul > register.html

Now, let’s create a template for the registration view. Open the register.html file and add the following lines of code:
authApp/templates/register.html

<!Doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Register</title>
    </head>
    <body>
       <div class="wrapper">
            <form method="POST">
                {{register_form.as_p}}
                <button type="submit">Register</button>
                {% csrf_token %}
            </form>
        </div>
    </body>
</html>

This template includes the form that is instantiated in the view. Since our form will be submitted via POST, we included the {% csrf_token %} template tag for CSRF protection.

Now run the development server and open http://127.0.0.1:8000/register/ in your browser. You will see the registration page we created, it will look something like this:

Creating a login view

In this section we will use the Django authentication framework to allow users to log in to our website. Instead of using the conventional way of handling both authentication and login in one function, we will be using Python Decorator to handle the authentication then handle the login in our view function. But first we will start by creating a login form.

Creating a login form
Open forms.py or the authApp directory and add the following lines of code:

authApp/forms.py

from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(label='')
    password = forms.CharField(label='',widget=forms.PasswordInput)

    def __init__(self,*args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['username'].widget.attrs.update({'placeholder':'Username'})
        self.fields['password'].widget.attrs.update({'placeholder':'Password'})

what we did here was this:

  • We created a username and password field.
  • We set the labels for both fields to an empty string.
  • We gave them placeholder values related to their field names.

Authentication with Python Decorators**
In the authApp, create a decorator.py file with this command:
authDecorator/authApp

$ type nul > decorator.py

Open the decorator.py file and add the following code:
authApp/decorator.py

from django.contrib.auth import authenticate
from django.shortcuts import render
from .forms import LoginForm
from django.http import HttpResponse
from django.contrib import messages

def authenticate_user(login_func):
    def wrapper(request, user=None):
        if request.user.is_authenticated:
            return HttpResponse('You have been Authenticated')
        if request.method == 'POST':
            login_form = LoginForm(request.POST)
            if login_form.is_valid():
                cd = login_form.cleaned_data
                user = authenticate(username=cd['username'], password=cd['password'])
                if user is not None:
                    if user.is_active:
                        return login_func(request,user)
                    else:
                        messages.error(request, 'User is disabled')
                else:
                    messages.error(request, 'User does not exit')
            else:
                messages.error(request, 'Invalid username of passoword')
        else:
            login_form = LoginForm()
        return render(request, 'login.html', {'login_form': login_form})
    return wrapper

This is what our Decorator does: when our Decorator function is called with a GET request, we instantiate a new log in with login_form = LoginForm() to display it in the template. When the user submits the form via POST, we perform the following actions:

  • Instantiate the form with the submitted data with login_form = LoginForm(request.POST).
  • Check if the form is valid. If it is not valid, we will display the form error in our template using Django’s message framework.
  • If the submitted data is valid, we authenticate the user against the database by using the authenticate() method.
  • If the user has not been authenticated, we will return an error message.
  • If the user was successfully authenticated, we check if the user is active by accessing its is_active attribute. This is an attribute of Django’s User model. If the user is not active, it will return an error message.
  • If the user is active, we return login_func, this is the view function that is responsible for user login. We Instantiated the function with the request and user object, they are required for the login process.

Now that we have defined our Decorator lets create a login view.
In the authApp directory, open view.py and add the following lines of code:
authApp/views.py

from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.http import HttpResponse
from .decorator import authenticate_user

def register_view(request):
    #...

@authenticate_user
def login_view(request, user=None):
    login(request, user)
    return HttpResponse('{} you have logged in successfully'.format(request.user))  

What this view does is to login a user then return a HttpResponse telling the user that the login was successful.
Notice how we placed @authenticate_user before our function, this is how we decorate our login_view with our already created Decorator function.

Now let’s add the URL for the views. In authApp/url.py add the following lines of code:
authApp/url.py

from django.urls import path
from . import views
urlpatterns = [
    #...
    path('login/', views.login_view, name='login'),
]

The login view can now be accessed by a URL

Now, let’s create a template for the login view. Navigate to authApp/templates and create a login.html file. You can do this with the command
authApp/templates

$ type nul > login.html

Now, pen the login.html file and add the following lines of code:
authApp/templates/login.html

<!Doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Login</title>
    </head>
    <body>
       <div class="wrapper">
            {% if messages %}
                <ul class="messages">
                    {% for message in messages %}
                    <li>{{ message }}</li>
                    {% endfor %}
                </ul>
            {% endif %}
            <form action="{% url 'login' %}" method="POST">
                {{login_form.as_p}}
                <button type="submit">Login</button>
                {% csrf_token %}
            </form>
        </div>
    </body>
</html>

what we did here was this:

  • We checked if there were messages attached to the request, if there was, we iterate through all the messages and displayed them in a list.
  • We created a form that sends a post request to our view when it is submitted.
  • We rendered the form which was instantiated in the login view.
  • We also included the {% csrf_token %} template tag for CSRF protection

With this, we are done building the authentication app. Run the development server and open http://127.0.0.1:8000/login/ in your browser. You will see the login page we created, it will look something like this:

Testing our app

You can test the app by creating a new user on the registration page, then login with the user credentials on the login page.

Conclusion

It’s been quite a journey. We started by looking at Python Decorators, what they are, how they can be used and also some advantages, then looked at how they can be used in Django to handle authentication. you can find source code on Github.

The post Authentication in Django using Python Decorators appeared first on CodeSource.io.


This content originally appeared on CodeSource.io and was authored by Taminoturoko Briggs


Print Share Comment Cite Upload Translate Updates
APA

Taminoturoko Briggs | Sciencx (2021-07-15T08:34:48+00:00) Authentication in Django using Python Decorators. Retrieved from https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/

MLA
" » Authentication in Django using Python Decorators." Taminoturoko Briggs | Sciencx - Thursday July 15, 2021, https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/
HARVARD
Taminoturoko Briggs | Sciencx Thursday July 15, 2021 » Authentication in Django using Python Decorators., viewed ,<https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/>
VANCOUVER
Taminoturoko Briggs | Sciencx - » Authentication in Django using Python Decorators. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/
CHICAGO
" » Authentication in Django using Python Decorators." Taminoturoko Briggs | Sciencx - Accessed . https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/
IEEE
" » Authentication in Django using Python Decorators." Taminoturoko Briggs | Sciencx [Online]. Available: https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/. [Accessed: ]
rf:citation
» Authentication in Django using Python Decorators | Taminoturoko Briggs | Sciencx | https://www.scien.cx/2021/07/15/authentication-in-django-using-python-decorators/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.