Programación Back-End

Unidad 3: API RESTful con Integración de Base de Datos

Django Users

Redactado por Criz
Publicado el 27 de julio de 2024 a las 03:29
Última actualización el 27 de julio de 2024 a las 03:29

Acciones rapidas
Editar
Siguiente
Previo

Django Users

Django nos provee de un modelo y un sistema completo de autenticación de usuarios.

ESTO NOS VIENDE DE LA PUTA MADRE. Es muy útil e intuitivo, de hecho, quedaras lol.

La Idea

La idea es hacer un sitio en donde el usuario pueda ver su perfil.
Además, crearemos una forma de agregar comentarios a productos.

Estaremos usando el proyecto anterior ProyectoDjango.

Si no tienes el proyecto, tienes dos opciones:

  1. Puedes ver todos los capítulos anteriores y recrear el proyecto (recomendado)
  2. Descargar ProyectoDjango (no recomendado)

Recuerda

  1. Crear un entorno virtual de Python.
  2. Activar el entorno virtual de Python.
  3. Instalar Django.

Manejo del inicio de sesión, registro y logout

Para esto, crearemos una nueva aplicación, asi mantenemos un orden. La app la llamare autenticacion...
py manage.py startapp autenticacion

En views.py de la aplicación autenticacion, creare las siguientes vistas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout 
from .forms import SignupForm, LoginForm
from django.contrib.auth.decorators import login_required

# Create your views here.

# 👇 uso de un decorador
@login_required # 👈 se obliga al usuario a tener una sesion activa para ver esta vista
def index(request):
    return render(request, "autenticacion/index.html")

El decorador permite que Django se encargue de las redirecciones en el caso de que un usuario no tenga sesión activa. Si la tiene, simplemente devuelve la vista.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def registrar(request):
    # 👇 si el usuario tiene sesion activa...
    if request.user.is_authenticated:
        return redirect('autenticacion:index') # entonces lo mandamos al inicio de la app
    form = SignupForm(request.POST)
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return redirect('autenticacion:login')
    return render(request, 'autenticacion/signup.html', {'form': form})

El formulario hereda de otro, por lo que ese "padre" hereda la lógica de registro del usuario.

Al final entendamos que un Usuario es solo un registro. Y Django se encargará de lo más tedioso.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def iniciarsesion(request):
    if request.user.is_authenticated:
        return redirect('autenticacion:index')
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            # 👇 la funcion authenticate nos permite validar un usuario
            user = authenticate(request, username=username, password=password)
            # 👇 si la funcion devuelve un 'Usuario', significa que las credenciales son correctas
            if user:
                # 👇 la funcion login inicia la sesion del usuario
                login(request, user)
                return redirect('autenticacion:index') # lo mandamos al perfil
    else:
        form = LoginForm()
    return render(request, 'autenticacion/login.html', {'form': form})
1
2
3
4
@login_required # 👈 obviamente, un usuario sin sesion no puede terminar una
def cerrarsesion(request):
    logout(request) # cerramos la sesion del usuario
    return redirect('autenticacion:login') # lo mandamos al sitio de inicio de sesion

Los formularios de Registro e Inicio de sesión

Debemos crear el archivo forms.py para definir los formularios...
Primero, importamos lo necesario:

1
2
3
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User # Modelo de Django que contiene a los usuarios

Luego, creamos nuestro formulario de registro:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#                👇 nuestro formulario de registro hereda de UserCreationForm, que tiene toda la logica.
class SignupForm(UserCreationForm):
    class Meta:
        model = User
        # 👇 declaramos que campos deseamos mostrar en el formulario.
        fields = ['username', 'email', 'password1', 'password2']
        # username, password1 y password2 SON OBLIGATORIOS.
        # 👇 definimos las clases y tipos de entrada
        widgets = {
            "username": forms.TextInput(
                attrs={
                    "class": "form-control",
                }
            ),
            "email": forms.EmailInput(
                attrs={
                    "class": "form-control"
                }
            ),
            "password1": forms.PasswordInput(
                attrs={
                    "class": "form-control"
                }
            ),
            "password2": forms.PasswordInput(
                attrs={
                    "class": "form-control"
                }
            ),
        }
1
2
3
class LoginForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))
    password = forms.CharField(widget=forms.PasswordInput(attrs={"class": "form-control"}))

Definición de rutas

Creamos nuestro archivo urls.py dentro de la app autenticacion y definimos las rutas que usaremos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.urls import path
import autenticacion.views as app

app_name = "autenticacion"

urlpatterns = [
    path('', app.index, name="index"),
    path('signup/', app.registrar, name="signup"),
    path('login/', app.iniciarsesion, name="login"),
    path('logout/', app.cerrarsesion, name="logout"),
]

Recuerda que es importante definir la variable app_name y definir las variables name a cada ruta.

Creando las templates

Ahora, necesitamos el front-end para poder visualizar nuestro sistema de autenticación.
Para ello, creamos la carpeta autenticacion dentro de templates, tal que:

Index

La página index actuará como el perfil del usuario, allí se podrá ver información sobre el usuario:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{% extends 'base.html' %}

{% block title %}Auth{% endblock %}

{% block content %}
<div class="container">
    <!-- la variable 'user' siempre esta disponible, por defecto es un usuario anonimo -->
    <!-- si no hay sesion activa, sus campos no tendran valores -->
    <h1>Bienvenido, {{ user.username }}!</h1>
    <h5>Te registraste el {{ user.date_joined }}</h5>
    <h5>Actualmente, {% if user.is_staff %}eres parte del staff!{% else %}no eres parte del staff.{% endif %}{% if user.is_superuser %} Y eres un Superusuario 👷‍♂️{% else %} Comun y corriente.{% endif %}</h5>
    <h5>Tu correo registrado es {{ user.email }}</h5>
    <!-- como puedes observar, es simplemente un modelo mas, y con ello podemos acceder a sus columnas -->
    <hr>
    <!-- desde no se que version de Django, para el Logout es necesario con POST (y no GET) -->
    <form action="{% url 'autenticacion:logout' %}" method="post">
        {% csrf_token %}
        <button class="btn btn-danger" type="submit">Cerrar sesión</button>
    </form>
</div>
{% endblock %}

Login

La template login permite que el usuario inicie una sesión a través del formulario de inicio de sesión.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{% extends 'base.html' %}

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

{% block content %}
<div class="container">
    <h1>Login</h1>
    <form method="POST">
        {% csrf_token %}
        {{ form }}
        <br>
        <button class="btn btn-success" type="submit">Iniciar sesión</button>
        ¿No tienes una cuenta? <a href="{% url 'autenticacion:signup' %}">Registrate aquí</a>.
    </form>
</div>
{% endblock %}

Signup

Igualmente, no tiene mucha ciencia...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{% extends 'base.html' %}

{% block title %}Sign up - Auth{% endblock %}

{% block content %}
<div class="container">
    <h1>Signup</h1>
    <form method="POST">
        {% csrf_token %}
        {{ form }}
        <br>
        <button class="btn btn-success" type="submit">Registrarse</button>
        ¿Ya tienes una cuenta? <a href="{% url 'autenticacion:login' %}">Inicia sesión aquí</a>.
    </form>
</div>
{% endblock %}

Integración con la template base.html

Es normal que en el navbar (o barra de navegación) se encuentren los típicos botones para iniciar sesión, registrarse y ver el perfil de un usuario. En este caso, no será la excepción.
Para ello, nos dirigiremos a la template base.html y la mejoraremos.

Esto se hace en la etiqueta header:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
                ...
                </ul>
            </div>
            <div class="text-end">
                <!--  user tiene sus metodos, que podemos usar. El siguiente metodo permite saber si el usuario esta autentificado. si no, entonces mostramos los botones comunes -->
                {% if user.is_authenticated %}
                <!-- si el usuario tiene una sesion activa, esta variable es True -->
                <a href="{% url 'autenticacion:index' %}" class="btn btn-primary">Perfil</a>
                {% else %}
                <!-- si no hay sesion, es usuario anonimo -->
                <a href="{% url 'autenticacion:login' %}" class="btn btn-success">Login</a>
                <a href="{% url 'autenticacion:signup' %}" class="btn btn-warning">Sign-up</a>
                {% endif %}
            </div>
        </div>
    </nav>
</header>
...

Configuración de variables de sesión

Django nos permite indicar las rutas para el control del comportamiento del sistema de usuarios. Estas variables se deben definir en settings.py de nuestro proyecto:

1
2
3
4
5
# Login

LOGIN_URL = "autenticacion:login" # Si el usuario topa con una vista que pide inicio de sesion, esta variable le indica donde debe Iniciar sesion
LOGIN_REDIRECT_URL = "autenticacion:index" # Si el usuario inicia sesion (sin redireccion del caso de arriba) lo dirige a la vista index de la app autenticacion
LOGOUT_REDIRECT_URL = "tienda:index" # Si el usuario cierra sesion, lo manda a la vista index de la app tienda

Estas variables indican que debe hacer Django en los casos mencionados.

Finalmente, definimos la ruta principal

Ahora es el turno del archivo urls.py dentro de la carpeta del proyecto (ProyectoDjango/urls.py):

1
2
3
4
5
urlpatterns = [
    ...
    #       👇 definimos la nueva ruta para la aplicacion
    path('cuenta/', include("autenticacion.urls", namespace="autenticacion")),
]

Y eso es todo.
Ahora ya tienes usuarios que pueden registrase, iniciar sesión, cerrar sesión, etc. La lógica se la dejamos a Django.
✨ES UNA PUTA MARAVILLA ❤.


Siguiente
Previo