with tutorial pelicula learning how descargar con aplicaciones python django

python - tutorial - La mejor manera de hacer que el inicio de sesión de Django sea el predeterminado



django windows (7)

Aquí hay una solución de middleware para django 1.10+

Los middleware deben escribirse de una nueva forma en django 1.10+ .

Código

import re from django.conf import settings from django.contrib.auth.decorators import login_required class RequireLoginMiddleware(object): def __init__(self, get_response): # One-time configuration and initialization. self.get_response = get_response 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 __call__(self, request): response = self.get_response(request) return response 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

Instalación

  1. Copie el código en su carpeta de proyecto y guárdelo como middleware.py
  2. Agregar a MIDDLEWARE

    MIDDLEWARE = ​​[... ''.middleware.RequireLoginMiddleware'', # Requerir inicio de sesión]

  3. Agregue a su settings.py:

LOGIN_REQUIRED_URLS = ( r''(.*)'', ) LOGIN_REQUIRED_URLS_EXCEPTIONS = ( r''/admin(.*)$'', ) LOGIN_URL = ''/admin''

Fuentes:

  1. Esta respuesta por Daniel Naab

  2. Tutorial de Django Middleware por Max Goodridge

  3. Django Middleware Docs

Estoy trabajando en una gran aplicación Django, la gran mayoría de las cuales requiere un inicio de sesión para acceder. Esto significa que a lo largo de toda nuestra aplicación hemos rociado:

@login_required def view(...):

Está bien, ¡y funciona genial siempre que recordemos agregarlo a todos lados ! Tristemente a veces lo olvidamos, y el fracaso a menudo no es muy evidente. Si el único enlace a una vista está en una página @login_required, entonces no es probable que notes que puedes llegar a esa vista sin iniciar sesión. Pero los chicos malos podrían darse cuenta, lo cual es un problema.

Mi idea era invertir el sistema. En lugar de tener que escribir @login_required en todos lados, preferiría tener algo como:

@public def public_view(...):

Solo por lo público. Traté de implementar esto con algún middleware y no pude lograr que funcionara. Todo lo que probé interactuó mal con otro middleware que estamos usando, creo. A continuación intenté escribir algo para recorrer los patrones de URL y comprobar que todo lo que no sea @public estuviera marcado @login_required; al menos, obtendríamos un error rápido si olvidáramos algo. Pero entonces no pude averiguar cómo se ha aplicado @login_required a una vista ...

Entonces, ¿cuál es la forma correcta de hacer esto? ¡Gracias por la ayuda!


Es difícil cambiar las suposiciones incorporadas en Django sin volver a trabajar la forma en que las URL se transfieren para ver las funciones.

En lugar de rebuscar en las internas de Django, aquí hay una auditoría que puedes usar. Simplemente revisa cada función de vista.

import os import re def view_modules( root ): for path, dirs, files in os.walk( root ): for d in dirs[:]: if d.startswith("."): dirs.remove(d) for f in files: name, ext = os.path.splitext(f) if ext == ".py": if name == "views": yield os.path.join( path, f ) def def_lines( root ): def_pat= re.compile( "/n(/S.*)/n+(^def/s+.*:$)", re.MULTILINE ) for v in view_modules( root ): with open(v,"r") as source: text= source.read() for p in def_pat.findall( text ): yield p def report( root ): for decorator, definition in def_lines( root ): print decorator, definition

Ejecute esto y examine la salida para def s sin los decoradores apropiados.


Existe una alternativa para poner un decorador en cada función de vista. También puede colocar el login_required() en el archivo urls.py 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 e importan directamente, no como cadenas.

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


Inspirado por la respuesta de Ber, escribí un pequeño fragmento que reemplaza la función de patterns , envolviendo todas las devoluciones de llamada de URL con el decorador de login_required . Esto funciona en Django 1.6.

def login_required_patterns(*args, **kw): for pattern in patterns(*args, **kw): # This is a property that should return a callable, even if a string view name is given. callback = pattern.callback # No property setter is provided, so this will have to do. pattern._callback = login_required(callback) yield pattern

Usarlo funciona de la siguiente manera (la llamada a la list es obligatoria debido al yield ).

urlpatterns = list(login_required_patterns('''', url(r''^$'', home_view)))


Middleware puede ser su mejor apuesta. He usado este fragmento de código en el pasado, modificado a partir de un fragmento encontrado en otra parte:

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 no es un ajuste de uno a uno, puede optar por modificar el middleware para adaptarse a sus circunstancias más de cerca.

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


Realmente no puedes ganar esto. Simplemente debe hacer una declaración de los requisitos de autorización. ¿En qué otro lugar colocarías esta declaración, excepto en la función de vista?

Considere reemplazar sus funciones de vista con objetos invocables.

class LoginViewFunction( object ): def __call__( self, request, *args, **kw ): p1 = self.login( request, *args, **kw ) if p1 is not None: return p1 return self.view( request, *args, **kw ) def login( self, request ) if not request.user.is_authenticated(): return HttpResponseRedirect(''/login/?next=%s'' % request.path) def view( self, request, *args, **kw ): raise NotImplementedError

A continuación, crea sus subclases de funciones de vista de LoginViewFunction .

class MyRealView( LoginViewFunction ): def view( self, request, *args, **kw ): .... the real work ... my_real_view = MyRealView()

No guarda ninguna línea de código. Y no ayuda al problema de "nos olvidamos". Todo lo que puede hacer es examinar el código para asegurarse de que las funciones de visualización sean objetos. De la clase correcta.

Pero aun así, nunca sabrá realmente que cada función de vista es correcta sin un conjunto de pruebas de unidad.