Contact Information

KodeBlog

We're Available 24/ 7. Drop us an email.

Django Authentication

In the last tutorial, we created some pages using templates and views. In the next tutorials, we want to create new pages to create and update objects. However, It won't be rational if we let everyone do such operations. We won't limit it to only authenticated users.

Topics to be covered

We will cover the following topics in this lesson

  • Authentication URLs
  • Login Template
  • Login and Logout Redirect URLs
  • Modifying the base template
  • Logging In and Out
  • Protected Pages
  • Summary

Authentication URLs

So, we should have authentication. Users could log in and log out.

As mentioned before, we have an auth app in our Django application enabled. So, we won't need to develop models and views related. However, we should develop the needed templates.

Add auth/ URLs:

we add this path to our root URLs so, it detects the path related to auth.

path('auth/', include('django.contrib.auth.urls')),

HERE,

  • The above URL pattern matches the path auth/ to URLs module that is defined in the package django.contrib.auth.urls.

Currently, we need these two paths

  • auth/login/ [name='login'] used to present the user with the login form.
  • auth/logout/ [name='logout'] provides us with a link that the user should click to logout.

Login Template

We should add templates to our root template in BASE_DIR

So we create a new folder templates/registration:

Create a new file login.html inside the folder templates/registration

Add the following code to login.html

{% extends "base.html" %}

{% block content %}
<div class="container col-md-6">
<h3 class="mt-2">User Login</h3>
<form id="login-form" method="post" action="{% url 'login' %}">
    {% csrf_token %}
    <div class="form-group">
      <label for="username">Username</label>
      <input type="text" class="form-control" id="username" name="username" placeholder="Enter your username">
    </div>
    <div class="form-group">
      <label for="exampleInputPassword1">Password</label>
      <input type="password" class="form-control" id="password" name="password" placeholder="Enter your password">
    </div>
    {% if form.errors %}
    <div class="form-group">
        <p class="text-danger">
            <strong>Your username and password didn't match.Please try again.</strong>
        </p>
    </div>
    {% endif %}
    <button type="submit" class="btn btn-primary">Login</button>
    <input type="hidden" name="next" value="{{ next }}" />
  </form>
</div>
{% endblock %}

HERE,

  • {% csrf_token %} adds a Cross-site request forgery security token to our form
  • {% url 'login' %} sets the form action method to the named urlpattern login
  • {% if form.errors %} checks to see if the form has some errors using the if statement to display some error messages.
  • <input type="hidden" name="next" value="{{ next }}" /> Imagine a page like books/create. Login is required to access this page. If the user is not logged in, he/she will be redirected to the login page while the next variable is last URL books/url, so after login is successful, they will be redirected to books/create instead of the default.

Login and Logout Redirect URLs

 We also need to define a default URL for after login. In settings, add the following line

LOGIN_REDIRECT_URL = '/'

HERE,

  • LOGIN_REDIRECT_URL = '/' redirects the user to the home page after login

We also need a redirect URL for logging out. Logout does not need a form or template. We just need to add it link to our base template so that, if the user is logged in he/she can log out. 

LOGOUT_REDIRECT_URL = '/'

HERE,

  • LOGOUT_REDIRECT_URL = '/' redirects the user to the home page after logout

If you do not set the login and logout redirects, the Django will redirect the user to the Admin panel app.

Modifying the base template

Let's update base template:

{% load static %}
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{title}}</title>
        <link rel="shortcut icon" href="{% static "images/favicon.png" %}">
        <!-- Bootstrap core CSS -->
        <link href="{% static "vendor/bootstrap/css/bootstrap.min.css" %}" rel="stylesheet">
        <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link href="{% static "css/style.css" %}" rel="stylesheet">
    </head>
    <body>
        <!-- Navigation -->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
            <div class="container">
                <a class="navbar-brand" href="{% url 'home' %}">KODEBLOG Bookstore</a>
                <button class="navbar-toggler" type="button"
                    data-toggle="collapse" data-target="#navbarResponsive"
                    aria-controls="navbarResponsive" aria-expanded="false"
                    aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarResponsive">
                    <ul class="navbar-nav ml-auto">
                        <li class="nav-item active">
                            <a class="nav-link" href="{% url 'home' %}">Home
                                <span class="sr-only">(current)</span>
                            </a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'books.index' %}">Books</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'authors.index' %}">Authors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'categories.index' %}">Categories</a>
                        </li>
                        {% if user.is_authenticated %}
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'books.create' %}">Add Book</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'authors.create' %}">Add Author</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'categories.create' %}">Add Category</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="/auth/logout">Log out</a>
                        </li>
                        {%else%}
                        <li class="nav-item">
                            <a class="nav-link" href="/auth/login">Log in</a>
                        </li>
                        {% endif %}

                    </ul>
                </div>
            </div>
        </nav>
        <!-- Page Content -->
        <div class="container">
            {% block content %}{% endblock %}
        </div>
        <!-- Bootstrap core JavaScript -->
        <script src="{% static "vendor/jquery/jquery.slim.min.js" %}"></script>
        <script src="{% static "vendor/bootstrap/js/bootstrap.bundle.min.js" %}"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
        {% block scripts %}{% endblock %}
    </body>
</html>

HERE,

  • {% if user.is_authenticated %} checks to see if the user is authenticated so that we can create links for creating authors, books and categories.
  • {%else%} the else block is used to display a login link if the user is not authenticated.

Logging In and Out

In the lesson on the admin panel, we created a super user account and set a password. We will use the same details to login into our application.

Load the following URL into your web browser.

dfdf

You should be able to see the following page.

Django Authentication Login

Enter a random username and password.

You should be able to see the following error message

Django Authentication Failed

Let's now try it with the correct username and password.

You should be able to see the navigation menu include the following links.

Django Authentication

The links for adding books, authors, categories and logout are only visible to users who have successfully logged in.

If you click on Log out link, then the nave menu will change to the following

Django Authentication Logout

You should be able to see the Log in link and the others would have disappeared.

Protected Pages

Protected pages are those pages that should be accessed only by users who are logged in. For now, we are simply hiding links from users who have not logged in. But if the user where to directly enter the URL for say creating a ne author, they can still access it.

To fix this situation, mixins. All we have to do is pass LoginRequiredMixin function to the generic view like in the example below

from django.contrib.auth.mixins import LoginRequiredMixin

class BookCreateView(LoginRequiredMixin, CreateView):
    login_url = '/auth/login'
    model = Book
    fields = ['title', 'author', 'description', 'category']
    template_name = 'books/create.html'

HERE,

  • from django.contrib.auth.mixins import LoginRequiredMixin imports the login required mixin
  • class BookCreateView(LoginRequiredMixin, CreateView): the LoginRequiredMixin mixin is now part of the class definition
  • login_url = '/auth/login' defines the URL where the user should be redirected to if they are not logged in.

In the next lesson, we will look at how to process forms that will create and update data. We will learn more about LoginRequiredMixin mixin and see it in action.

Summary

Django comes with authentication app built-in. which includes an admin panel. However, Django allows us to define our own URLs and templates for authentication but take advantage of the built-in app to handle all of the logic for us in the background. Django also comes in with a mixin that allows us to protected pages on our application.

Author: Rodrick Kazembe

Rodrick is a developer who works on Desktop, Web and Mobile Applications. He is familiar with Python, Java, JavaScript, C++, C#, Kotlin, PHP, Python and the list goes on. Rodrick enjoys sharing knowledge especially when it comes to technology.

Django Views

Django Form Processing

Leave A Reply