vista de clase django con decorador y sesiones
Pregunta
Estoy tratando de convertir algunas de mis vistas de django de vistas basadas en funciones a vistas basadas en clases y me he encontrado con un pequeño problema.
Mi OO es algo débil y creo que el problema es que he perdido la noción de hacia dónde van las cosas.
Tengo un decorador de inicio de sesión personalizado que necesito en las vistas, así que tengo ...
Primero tengo la clase View de este ejemplo http://www.djangosnippets.org/snippets/760/
Entonces mi clase de vista se ve así ...
class TopSecretPage(View):
@custom_login
def __call__(self, request, **kwargs):
#bla bla view stuff...
pass
El problema es que mi decorador no puede acceder a request.session por alguna razón ...
Mi decorador se ve así ...
def myuser_login_required(f):
def wrap(request, *args, **kwargs):
# this check the session if userid key exist,
# if not it will redirect to login page
if 'field' not in request.session.keys():
return wrap
¡Creo que es algo simple que me falta, así que gracias por su paciencia a todos!
ACTUALIZACIÓN: Ok, aquí está el error que recibo ...
" ViewDoesNotExist: Probé TopSecretPage en el módulo nombre del proyecto.application.views. El error fue: escriba el objeto 'TopSecretPage' no tiene atributo 'sesión' "
También simplifiqué el decorador para que se viera así ...
def myuser_login_required(request, *args, **kwargs):
# this check the session if userid key exist,
# if not it will redirect to login page
if 'username' not in request.session.keys():
return HttpResponseRedirect(reverse("login-page"))
return True
Solución
El problema es que su contenedor espera " solicitud " como primer argumento, pero un método en una clase siempre toma "self" como el primer argumento Entonces, en su decorador, lo que cree que es el objeto de solicitud es en realidad TopSecretPage.
Las soluciones de Vinay o artran deberían funcionar, así que no las repetiré. Solo pensé que una descripción más clara del problema podría ser útil.
Otros consejos
La forma correcta de hacer esto para cualquier decorador aplicado a cualquier método de vista basado en clases es usar django.utils.decorators.method_decorator ()
. No estoy seguro de cuándo se introdujo method_decorator (), pero aquí hay un ejemplo / actualización en Django 1.2 notas de la versión . Úselo así:
from django.utils.decorators import method_decorator
class TopSecretPage(View):
@method_decorator(custom_login)
def __call__(self, request, **kwargs):
#bla bla view stuff...
pass
Este problema ha surgido antes . Se incluye una solución que podría funcionar para usted.
Actualización: Método de ejemplo con decorador:
class ContentView(View):
# the thing in on_method() is the actual Django decorator
#here are two examples
@on_method(cache_page(60*5))
@on_method(cache_control(max_age=60*5))
def get(self, request, slug): # this is the decorated method
pass #in here, you access request normally
En lugar de usar el decorador en la vista, puede decorar la url.
Por ejemplo en urls.py:
from my_decorators import myuser_login_required
from my_views import TopSecretPage
urlpatterns = patterns('',
(r'^whatever-the-url-is/
Puede que necesites jugar un poco con eso, pero es correcto.
, myuser_login_required(TopSecretPage), {}),
)
Puede que necesites jugar un poco con eso, pero es correcto.
Esto es efectivamente un duplicado de Django - Forma correcta de pasar argumentos a los decoradores de CBV? que describe la forma correcta de abordar esto. La forma correcta de hacer esto para django 1.9 es la siguiente:
@method_decorator(myuser_login_required(), name='dispatch')
class TopSecretPage(View):
..