Saltar al contenido

La mejor manera de hacer que el login_required de Django sea el predeterminado

Solución:

El middleware puede ser su mejor opción. He usado este fragmento de código en el pasado, modificado de un fragmento que se encuentra en otro lugar:

import re

from django.conf import settings
from django.contrib.auth.decorators import login_required


class RequireLoginMiddleware(object):
    """
    Middleware component that wraps the login_required decorator around
    matching URL patterns. To use, add the class to MIDDLEWARE_CLASSES and
    define LOGIN_REQUIRED_URLS and LOGIN_REQUIRED_URLS_EXCEPTIONS in your
    settings.py. For example:
    ------
    LOGIN_REQUIRED_URLS = (
        r'/topsecret/(.*)$',
    )
    LOGIN_REQUIRED_URLS_EXCEPTIONS = (
        r'/topsecret/login(.*)$',
        r'/topsecret/logout(.*)$',
    )
    ------
    LOGIN_REQUIRED_URLS is where you define URL patterns; each pattern must
    be a valid regex.

    LOGIN_REQUIRED_URLS_EXCEPTIONS is, conversely, where you explicitly
    define any exceptions (like login and logout URLs).
    """
    def __init__(self):
        self.required = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS)
        self.exceptions = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS_EXCEPTIONS)

    def process_view(self, request, view_func, view_args, view_kwargs):
        # No need to process URLs if user already logged in
        if request.user.is_authenticated():
            return None

        # An exception match should immediately return None
        for url in self.exceptions:
            if url.match(request.path):
                return None

        # Requests matching a restricted URL pattern are returned
        # wrapped with the login_required decorator
        for url in self.required:
            if url.match(request.path):
                return login_required(view_func)(request, *view_args, **view_kwargs)

        # Explicitly return None for all non-matching requests
        return None

Luego, en settings.py, enumere las URL base que desea proteger:

LOGIN_REQUIRED_URLS = (
    r'/private_stuff/(.*)$',
    r'/login_required/(.*)$',
)

Siempre que su sitio siga las convenciones de URL para las páginas que requieren autenticación, este modelo funcionará. Si esto no es un ajuste uno a uno, puede optar por modificar el middleware para que se adapte más a sus circunstancias.

Lo que me gusta de este enfoque, además de eliminar la necesidad de ensuciar el código base con @login_required decoradores – es que si cambia el esquema de autenticación, tiene un lugar adonde ir para realizar cambios globales.

Existe una alternativa a poner un decorador en cada función de vista. También puede poner el login_required() decorador en el urls.py expediente. Si bien esto sigue siendo una tarea manual, al menos lo tiene todo en un solo lugar, lo que facilita la auditoría.

p.ej,

    from my_views import home_view

    urlpatterns = patterns('',
        # "Home":
        (r'^$', login_required(home_view), dict(template_name="my_site/home.html", items_per_page=20)),
    )

Tenga en cuenta que las funciones de vista se nombran y se importan directamente, no como cadenas.

También tenga en cuenta que esto funciona con cualquier objeto de vista invocable, incluidas las clases.

En Django 2.1, podemos decorar todos los métodos en una clase con:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

@method_decorator(login_required, name="dispatch")
class ProtectedView(TemplateView):
    template_name="secret.html"

ACTUALIZAR:
También he encontrado que lo siguiente funciona:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView

class ProtectedView(LoginRequiredMixin, TemplateView):
    template_name="secret.html"

y establecer LOGIN_URL = '/accounts/login/' en tus settings.py

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *