Monday, October 14, 2019

Using Django authentication views

The login view we created in the previous post was to understand the process of user authentication in Django. Now we'll use the default Django authentication views in most cases. Let's start with the-

Login and logout views

To use Django authentication views edit the urls.py file of our account application as shown below:

from django.urls import path
from django.contrib.auth import views as auth_views
from . import views

urlpatterns = [

    #post views
    #path('login/', views.user_login, name='login'),
    path('login/', auth_views.LoginView.as_view(),name='login'),
    path('logout/', auth_views.LogoutView.as_view(),name='logout'),
   
    ]


We comment out the URL pattern for the user_login view we have created previously to use the LoginView view of Django's authentication framework. We also add a URL pattern for the LogoutView view.

Now create a new directory inside the templates directory of your account application and name it registration. This is the default path where the Django authentication views expect our authentication
templates to be.

The django.contrib.admin module includes some of the authentication templates that are used for the administration site. We have placed the account application at the top of the INSTALLED_APPS setting so that Django uses our templates by default instead of any authentication templates defined in other apps.

Now create a new file inside the templates/registration directory, name it login.html, and add the following code to it:

{% extends "base.html" %}

{% block title %}Log-in{% endblock %}

{% block content %}
  <h1>Log-in</h1>
  {% if form.errors %}
    <p>
      Your username and password didn't match.
      Please try again.
    </p>
  {% else %}
    <p>Please, use the following form to log-in:</p>
  {% endif %}
  <div class="login-form">
    <form action="{% url 'login' %}" method="post">
      {{ form.as_p }}
      {% csrf_token %}
      <input type="hidden" name="next" value="{{ next }}" />
      <p><input type="submit" value="Log-in"></p>
    </form>
   </div>
 
{% endblock %}


You can see that this login template is quite similar to the one we created before. Django uses the AuthenticationForm form located at django.contrib.auth.forms by default. This form tries to authenticate the user and raises a validation error if login was unsuccessful. In this case, we can look
for errors using {% if form.errors %} in the template to check whether the credentials provided are wrong. Note that we have added a hidden HTML <input> element to submit the value of a variable called next. This variable is first set by the login view when you pass a next parameter in the request (for example, http://127.0.0.1:8000/account/login/?next=/account/).

The next parameter has to be a URL. If this parameter is given, the Django login view will redirect the user to the given URL after a successful login.

Next we'll create a logged_out.html template inside the registration template directory for which the code is shown below:

{% extends "base.html" %}

{% block title %}Logged out{% endblock %}

{% block content %}
  <h1>Logged out</h1>
  <p>You have been successfully logged out. You can <a href="{% url "login" %}">log-in again</a>.</p>
{% endblock %}


This is the template that Django will display after the user logs out. After adding the URL patterns and the templates for login and logout views, your website is ready for users to log in using Django
authentication views.

Now, we will create a new view to display a dashboard when users log in to their account. Open the views.py file of your account application and add the following code to it:

@login_required
def dashboard(request):
    return render(request,
                  'account/dashboard.html',
                  {'section': 'dashboard'})


We decorate our view with the login_required decorator of the authentication framework. The login_required decorator checks whether the current user is authenticated. If the user is authenticated, it executes the decorated view; if the user is not authenticated, it redirects the user to the login URL with the originally requested URL as a GET parameter named next. By doing so, the login view redirects users to the URL they were trying to access after they successfully log in. Remember that we added a hidden input in the form of our login template for this purpose. We also define a section variable. We will use this variable to track the site's section that the user is browsing. Multiple views may correspond to the same section. This is a simple way to define the section that each view corresponds to.

Next we create a template for the dashboard view. To do so, create a new file inside the templates/account/ directory and name it dashboard.html. For this file the code is shown below:

{% extends "base.html" %}

{% block title %}Dashboard{% endblock %}

{% block content %}
  <h1>Dashboard</h1>
  <p>Welcome to your dashboard. </p>
{% endblock %}




Then, add the following URL pattern for this view in the urls.py file of the account application:

path('', views.dashboard, name='dashboard')

Edit the settings.py file of your project and add the following code to it:

LOGIN_REDIRECT_URL = 'dashboard'
LOGIN_URL = 'login'
LOGOUT_URL = 'logout'

The settings mentioned in the preceding code are as follows:
  • LOGIN_REDIRECT_URL: Tells Django which URL to redirect after a successful login if no next parameter is present in the request
  • LOGIN_URL: The URL to redirect the user to log in (for example, views using the login_required decorator)
  • LOGOUT_URL: The URL to redirect the user to log out 
We are using the names of the URL patterns we previously defined using the name attribute of the path() function. Hard coded URLs instead of URL names can also be used for these settings.

Now, we will add login and logout links to our base template to put everything together. In order to do this, we have to determine whether the current user is logged in or not in order to display the
appropriate link for each case. The current user is set in the HttpRequest object by the authentication middleware. You can access it with request.user. You will find a User object in the request even if the
user is not authenticated. A non-authenticated user is set in the request as an instance of AnonymousUser. The best way to check whether the current user is authenticated is by accessing its read-only attribute is_authenticated.

We' ll edit our base.html template and modify the <div> element with
a header ID, as shown below:

<span class="logo">Bookmarks</span>
    {% if request.user.is_authenticated %}
      <ul class="menu">
        <li {% if section == "dashboard" %}class="selected"{% endif %}>
          <a href="{% url "dashboard" %}">My dashboard</a>
        </li>
        <li {% if section == "images" %}class="selected"{% endif %}>
          <a href="#">Images</a>
        </li>
        <li {% if section == "people" %}class="selected"{% endif %}>
          <a href="#">People</a>
        </li>
      </ul>
    {% endif %}

    <span class="user">
      {% if request.user.is_authenticated %}
        Hello {{ request.user.first_name }},
        <a href="{% url "logout" %}">Logout</a>
      {% else %}
        <a href="{% url "login" %}">Log-in</a>
      {% endif %}
    </span>
  </div>

We only display the site's menu to authenticated users. We also check the current section to add a selected class attribute to the corresponding <li> item in order to highlight the current section in the menu using CSS. We also display the user's first name and a link to log out if the user is authenticated, or a link to log in otherwise.

Now, open http://127.0.0.1:8000/account/login/ in your browser. You should see the login page. Enter a valid username and password and click on the Log-in button.



You can see that the My dashboard section is highlighted with CSS because it has a selected class. Since the user is authenticated, the first name of the user is displayed on the right side of the header.
Click on the Logout link. You should see the following page:


In the page mentioned in the preceding screenshot, you can see that the user is logged out, and, therefore, the menu of the website is not being displayed anymore. Now, the link on the right side of the header shows Log-in.

Here I am ending this post. In the next post we'll integrate Django authentication views for password change.
Share:

0 comments:

Post a Comment