Skip to main content

django user authentication how to login, logout and Register



This post will demonstrate the necessary step's that you will need to follow when you want to build  authentication system with you Django framework using the built-in user authentication system. You
can get the code of this project on github

Start with clean work space where Django app is going to live 

mkdir news-wire

cd news-wire

Time to setup virtual eviroment, install django and kickoff the project

python3 -m venv venv

source venv/bin/activate

pip3 install Django

django-admin startproject news_art

House keeping

mv news_art/manage.py ./

mv news_art/news_art/* news_art/

rm -r news_art/news_art/

nano news_art/settings.py

ALLOWED_HOSTS = ['*']---------- We want to acsses our app from anywhere

Django automatically installs the auth app when a new project is created. This can be reveled in the settings.py under INSTALLED_APPS and you can see auth is one of several built-in apps Django has installed.


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth', ----------------------This one
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

python3 manage.py migrate

python3 manage.py runserver 192.168.0.245:8000


To use the auth app we need to add it to our project-level urls.py file. Make sure to add include on the second line. I’ve chosen to include the auth app at accounts/ but you can use any url pattern you want.

nano news_art/urls.py

from django.contrib import admin
from django.urls import path, include # add this

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')), # new
]


Login Page

Django by default will look within a templates folder called registration for auth templates. The login template is called login.html.

mkdir -p templates/registration

Update the settings.py file to tell Django to look for a templates folder at the project level. Update the DIRS setting within TEMPLATES as follows.
nano news_art/settings.py
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
    },
]


 We need to specify where to redirect the user upon a successful login.  We use the LOGIN_REDIRECT_URL=reverse_lazy setting to specify this route. At the bottom of the settings.py file add the following to redirect the user to the homepage.
"We are using reverse_lazy() to build the URLs dynamically. The reverse_lazy() function reverses URLs just like reverse() does, but you can use it when you need to reverse URLs before your project's URL configuration is loaded."

from django.urls import reverse_lazy
LOGIN_REDIRECT_URL=reverse_lazy('home')
LOGIN_URL=reverse_lazy('login')
LOGOUT_REDIRECT_URL = 'home'

Now update the project-level urls.py file so we can display the homepage. On the third line, import TemplateView and then add a urlpattern for it.
nano news_art/urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView # new
urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')),
    path('', TemplateView.as_view(template_name='home.html'), name='home'), # new
]

Create Template:

create new base.html, home.html and login.html files. Note that base.html and home.html these are located within the templates folder but not within templates/registration/ where Django auth looks by default for user auth templates, login.html.

Base template
nano templates/base.html
 
<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>{% block title %}Django Authentication{% endblock %}</title>

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

</head>

<body>

<div class="container">

    {% block content %}{% endblock %}

</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

</body>

</html>
For the home template

nano templates/home.html


{% extends 'base.html' %}

{% block title %}Home{% endblock %}

{% block content %}

{% if user.is_authenticated %}

  Hi {{ user.username }}!

  <p><a href="{% url 'logout' %}">logout</a></p>

{% else %}

  <p>You are not logged in</p>

  <a href="{% url 'login' %}">login</a>

{% endif %}

{% endblock %}

Login template

nano templates/registration/login.html



{% extends 'base.html' %}

{% block title %} | Account Login {% endblock %}

{% block content %}

<section id="login" class="bg-light py-5">

    <div class="container">

      <div class="row">

        <div class="col-md-6 mx-auto">

          <div class="card">

            <div class="card-header bg-primary text-white">

              <h4>

                <i class="fas fa-sign-in-alt"></i> Login</h4>

            </div>

            <div class="card-body">

                <form action="{% url 'login' %}" method="POST">

                  {% csrf_token %}

                <div class="form-group">

                  <label for="username">Username</label>

                  <input type="text" name="username" class="form-control" required>

                </div>

                <div class="form-group">

                  <label for="password2">Password</label>

                  <input type="password" name="password" class="form-control" required>

                </div>

                <input type="submit" value="Login" class="btn btn-secondary btn-block">

              </form>

            </div>

          </div>

        </div>

      </div>

    </div>

  </section>

  {% endblock %}
Done!. If you start the Django server again with python3 manage.py runserver 192.168.0.245:8000 and navigate to the homepage at http://192.168.0.245:8000/ you’ll see the following:


Click the login link should take you to the login page

Create users

But there’s one missing piece: we haven’t created any users yet. It's possible to create a superuser account from the command line.But for the sake of this post I wont go through that route however I’ll demostrate how to add a signup page to register new users to the Django app.  

Time to create a signup page so users can register for a new account.

Users app

Since we’re making our own view and url for registration, we need to create a dedicated app. Let’s call it accounts.

django-admin startapp accounts
Make sure to add the new app to the INSTALLED_APPS setting file:

 nano news_art/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts',------------------------------ # New
]

Then add a project-level url for the accounts app above our included Django auth app.
nano news_art/urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')), # new
    path('accounts/', include('django.contrib.auth.urls')),
    path('', TemplateView.as_view(template_name='home.html'), name='home'),
]

Create a new urls file in our accounts app. Note that we are importing a view called register
nano accounts/urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('register', views.register, name='register'),
]


For the views.py file add the following

nano accounts/views.py
from django.shortcuts import render, redirect
from django.contrib import messages, auth
from django.contrib.auth.models import User


def register(request):
  if request.method == 'POST':
    # Get form values
    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']

    # Check if passwords match
    if password == password2:
      # Check username
      if User.objects.filter(username=username).exists():
        messages.error(request, 'That username is taken')
        return redirect('register')
      else:
        if User.objects.filter(email=email).exists():
          messages.error(request, 'That email is being used')
          return redirect('register')
        else:
          # Looks good
          user = User.objects.create_user(username=username, password=password,email=email, first_name=first_name, last_name=last_name)

          user.save()
          messages.success(request, 'You are now registered and can log in')
          return redirect('login')
    else:
      messages.error(request, 'Passwords do not match')
      return redirect('register')
  else:
    return render(request, 'accounts/register.html')

 Create a template signup.html
mkdir templates/accounts
nano templates/accounts/register.html


{% extends 'base.html' %}

{% block title %} | Register Account {% endblock %}

{% block content %}

<section id="register" class="bg-light py-5">

    <div class="container">

      <div class="row">

        <div class="col-md-6 mx-auto">

          <div class="card">

            <div class="card-header bg-primary text-white">

              <h4>

                <i class="fas fa-user-plus"></i> Register</h4>

            </div>

            <div class="card-body">

          

              <form action="{% url 'register' %}" method="POST">

                  {% csrf_token %}

                  <div class="form-group">

                      <label for="first_name">First Name</label>

                      <input type="text" name="first_name" class="form-control" required>

                    </div>

                    <div class="form-group">

                      <label for="last_name">Last Name</label>

                      <input type="text" name="last_name" class="form-control" required>

                    </div>

                <div class="form-group">

                  <label for="username">Username</label>

                  <input type="text" name="username" class="form-control" required>

                </div>

                <div class="form-group">

                  <label for="email">Email</label>

                  <input type="email" name="email" class="form-control" required>

                </div>

                <div class="form-group">

                  <label for="password2">Password</label>

                  <input type="password" name="password" class="form-control" required>

                </div>

                <div class="form-group">

                  <label for="password">Confirm Password</label>

                  <input type="password" name="password2" class="form-control" required>

                </div>

                <input type="submit" value="Register" class="btn btn-secondary btn-block">

              </form>

            </div>

          </div>

        </div>

      </div>

    </div>

  </section>

  {% endblock %}

Open the home.html template after
<a href="{% url 'login' %}">login</a>
 
 or
  <a href="{% url 'register' %}">register</a>
-------
add the following

To confirm that it works, spin up the server with python3 manage.py runserver 192.168.0.245:8000 and navigate to http://192.168.0.245:8000.

Clink on the register link to create you'r very first user account


You should be redirected to the login page after sucssefuly registed an account proceed with login

After a sucsseful login you should be redirected to home page




Popular posts from this blog

How To Install the Anaconda Python Distribution on Debian 9 And Running a public notebook server

Anaconda Distribution is an open-source package manager, environment manager and distribution of Python and R programming languages. With a collection of 1,000+ open source packages with free community support. Designed for data science and machine learning workflows, you can use it whether you are on Windows, macOS or Linux. The Anaconda distribution ships with the conda command-line package management utility. You can learn more about Anaconda and conda by reading the official Anaconda Documentation . Jupyter is a browser-based interpreter that allows you to interactively work with Python and R. Anaconda provides Jupyter as well. You can think of Jupyter as a digital notebook that gives you an ability to execute commands, take notes and draw charts.It’s primarily used by Data Scientists. But I find that very useful tool if you are learning Python or R. It’s basically the same as working on a shell but much better. The Jupyter notebook web application is based on a

How to create REST API using Django REST Framework

This post begins with already working project and app's, I found that there some few requirement's that my project needed to handle and the best option for those requirement's was to use the Django's  Rest Framework. The way that I will tackle this task is more specific to the needs of the project rather than a one to one how to..., that being said you can still follow along, the approach that I'm going to use is easy to follow since I'll be providing a lot of information a log the way for better understanding of the why and how.....this code is available on Github , enough with the alerts and on with the show. Note:  If you would want to mimic the exactly settings then you will need to enable user authentication on your project you can follow this link for details .  Start with the DRF (Django Rest Framework) installation pip3 install djangorestframework For our app to use DRF, we'll have to add rest_framework into our settings.py.   nan

django react app setting up the backend

On the previous article I demonstrated how we can use the generic views along with ModelSerializer classes to rapidly develop our REST APIs. Knowledge that you will need  in your career as full stack / backend developer, however think of this article as an extension to the previous one, equipped with what we already know about REST API we will step our game up and discuss about ViewSet, ModelViewset we will dig deep into the concepts of Routers which allow us to manage our api routes in a simple and sophisticated manner as well as helping to speed up building APIs even further. There for on part II of this article i'll work you through on how React application can consume this RESTful API. There for at the end of the day we will have a full stack web app, in short we strat our development at the backend then later on we move at the frontend... so are you excited and ready to take the challange? lets do this then..... you can get source code for the bakend on github Preparat