Show login error messages in Python with Django

Asked

Viewed 564 times

0

I’m building a Python login page with Django, Javascript and HTML. What I’m not knowing how to do is show, on the login screen an Alert with the messages "Unauthorized user" and "Incorrect user or password". My question specifically is: how do I send the error message from the views.py file to login.html, capturing the content of that message and showing it inside an Alert. Below my code:

login.html

{% load static %}
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <div class="login">
        <div class="app-title">
            <h2>Entre no Sistema</h2>
        </div>

        <form class="login-form" method=POST>
            {% csrf_token %}
            <div class="control-group">
                <input type="text" name=username placeholder="usuário">
            </div>

            <div class="control-group">
                <input type="password" name=password placeholder="senha">
            </div>

            <input type=submit class="btn" value="Login">
        </form>
    </div>
</body>
</html>

py views.

from django.http import HttpResponse
from django.shortcuts import render, redirect
import ldap, json, os


def login(request):
    usuarios = ler_usuarios_cadastrados()

    request.session['username'] = ''
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        if username == 'admin' and password == 'admin':
            request.session['username'] = username
            request.session['campus'] = 0
            request.session['curso'] = 0
            return redirect('/geral')
        else:
            if username not in usuarios:
                #aqui deve mostrar a mensagem "Usuário não autorizado"
                return redirect('login')
            else:
                request.session['username'] = username
                request.session['campus'] = usuarios[username]['campus_id']
                request.session['curso'] = usuarios[username]['curso_id']

            username_ldap = 'uid=' + username + ',ou=People,dc=xpto,dc=abacaxi,dc=edu,dc=br'
            try:
                conn = ldap.initialize('ldap://ldap.xpto.abacaxi.edu.br')
                conn.protocol_version = 3
                conn.set_option(ldap.OPT_REFERRALS, 0)
                conn.simple_bind_s(username_ldap, password)
            except ldap.LDAPError:
                #aqui deve mostrar a mensagem "Usuário ou senha incorretos"
                return redirect('login')
            return redirect('/geral')
    else:
        return render(request,'login.html')

def ler_usuarios_cadastrados():
    file_path = os.path.join(os.path.dirname(__file__), 'usuarios_cadastrados.json')
    with open(file_path, "r", encoding="utf8") as usuarios_cadastrados: 
        return json.load(usuarios_cadastrados)

NOTE: All login logic is working correctly. I would just like to include the error messages. Thanks for your help.

2 answers

1


Use Django’s own messaging system, you can see all the options by clicking here.

To send a login failure message, for example, you can try the following:

from django.contrib import messages

def login(request):
    usuarios = ler_usuarios_cadastrados()

    request.session['username'] = ''
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        if username == 'admin' and password == 'admin':
            request.session['username'] = username
            request.session['campus'] = 0
            request.session['curso'] = 0
            return redirect('/geral')
        else:
            if username not in usuarios:
                # Aqui é onde a magia acontece
                messages.info(request, 'Usuário não autorizado')
                return redirect('login')
            else:
                request.session['username'] = username
                request.session['campus'] = usuarios[username]['campus_id']
                request.session['curso'] = usuarios[username]['curso_id']

            username_ldap = 'uid=' + username + ',ou=People,dc=xpto,dc=abacaxi,dc=edu,dc=br'
            try:
                conn = ldap.initialize('ldap://ldap.xpto.abacaxi.edu.br')
                conn.protocol_version = 3
                conn.set_option(ldap.OPT_REFERRALS, 0)
                conn.simple_bind_s(username_ldap, password)
            except ldap.LDAPError:
                #aqui deve mostrar a mensagem "Usuário ou senha incorretos"
                return redirect('login')
            return redirect('/geral')
    else:
        return render(request,'login.html')

To display the message in your template, simply add the following to the template:

{% if messages %}
    {% for m in messages %}
        <div class="alert alert-warning" role="alert">
          {{ m }}
        </div>
    {% endfor %}
{% endif %}

I hope this will be useful.

  • thanks thanks for your reply I solved my problem.

0

Live create a template for errors, and make include in the templates you want to show errors. Now I don’t know why you are reading the users of a txt file, when using db is simpler.

html errors.

{% if item.total_error_count %}
    <div class="alert alert-danger col-12 mx-1" role="alert">
        <div id="form_errors">
            {% if item.non_form_errors %}
                {{ item.non_form_errors }}
            {% endif %}
            {% for error in item.errors %}
                {{ error }}
            {% endfor %}
        </div>
    </div>
{% endif %}

login.html

{% load static %}
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <div class="login">
        <div class="app-title">
            <h2>Entre no Sistema</h2>
        </div>

        <form class="login-form" method=POST>
            {% csrf_token %}
            <div class="control-group">
                <input type="text" name=username placeholder="usuário">
            </div>

            <div class="control-group">
                <input type="password" name=password placeholder="senha">
            </div>
            {% include 'errors.html' %} <!-- Coloca aqui o include do template, mas coloca o path correto-->
            <input type=submit class="btn" value="Login">
        </form>
    </div>
</body>
</html>

py views.

from django import forms

...
           if username not in usuarios:
                # este mecanismo é tipico a sua utilização no forms, não sei se vai funcionar diretamente aqui, mas com o import do forms, o return seguinte será inutil.
                raise forms.ValidationError('Não existe o utilizador.'))
                #aqui deve mostrar a mensagem "Usuário não autorizado"
                return redirect('login')
...

NOTE: The best approach would be to switch to db and add Forms and login was simpler. Code below.

Forms.py

class LoginForm(forms.Form):
    """Login form for users."""
    username = forms.CharField(required = True, label = _('Username'), max_length = 32,)
    password = forms.CharField(required = True, label = _('Palavra Passe'), max_length = 32, widget = forms.PasswordInput())
    remember_user = forms.BooleanField(required = False, label = 'Memorizar')
    
    def clean(self):
        try:
            user = User.objects.get(username__iexact = self.cleaned_data['usernam'])
        except User.DoesNotExist:
            raise forms.ValidationError('Username ou Palavra passe inválida, corriga por favor.')
        
        if not user.check_password(self.cleaned_data['password']):
            raise forms.ValidationError('Username ou Palavra passe inválida, corriga por favor.')
        
        return self.cleaned_data

py views.

def login(request):
    """Display and processs the login form."""
    if request.method == 'POST':
        form = LoginForm(request.POST or None)
        if form.is_valid():
            user = auth.authenticate(username = form.cleaned_data['username'], password = form.cleaned_data['password'])
            if user:
                redirect('/geral')
            else:
                redirect('login')
    else:
        form = LoginForm()
    render(request,'login.html')
  • Thanks for the answer, but since I’m a beginner, the @Victorfernandes response made more sense to me because it was simpler. Taking advantage, I’m reading users a file pq at the moment do not have access to database.

  • Of course, if you decide to use a database. Here’s the solution. Good learning.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.