lezione di django con decoratore e sessioni
Domanda
Sto cercando di convertire alcune delle mie viste django da viste basate sulle funzioni a viste basate sulle classi e ho riscontrato un piccolo problema.
Il mio OO è un po 'debole e penso che il problema sia che ho perso le tracce di dove stanno andando le cose.
Ho un decoratore di login personalizzato di cui ho bisogno nelle viste, quindi ho ...
Per prima cosa ho la classe View da questo esempio http://www.djangosnippets.org/snippets/760/
Quindi la mia classe di visualizzazione è simile a questa ...
class TopSecretPage(View):
@custom_login
def __call__(self, request, **kwargs):
#bla bla view stuff...
pass
Il problema è che il mio decoratore non può accedere a request.session per qualche motivo ...
Il mio decoratore assomiglia a questo ...
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
Penso che sia qualcosa di semplice che mi manca, quindi grazie per la vostra pazienza a tutti!
UPDATE: Ok, quindi ecco l'errore che ottengo ...
" ViewDoesNotExist: provato TopSecretPage nel modulo projectname.application.views. Errore: l'oggetto tipo "TopSecretPage" non ha attributo "sessione" "
Ho anche semplificato il decoratore per assomigliare a questo ....
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
Soluzione
Il problema è che il wrapper si aspetta " richiesta " come primo argomento, ma un metodo su una classe prende sempre " self " come primo argomento. Quindi nel tuo decoratore, ciò che pensa sia l'oggetto richiesta è in realtà TopSecretPage stesso.
Le soluzioni di Vinay o di artran dovrebbero funzionare, quindi non le ripeterò. Ho solo pensato che una descrizione più chiara del problema potesse essere utile.
Altri suggerimenti
Il modo corretto di eseguire questa operazione per qualsiasi decoratore applicato a qualsiasi metodo di visualizzazione basato su classi è utilizzare django.utils.decorators.method_decorator ()
. Non sono sicuro quando è stato introdotto method_decorator () ma ecco un esempio / aggiornamento in Django 1.2 note di rilascio . Usalo in questo modo:
from django.utils.decorators import method_decorator
class TopSecretPage(View):
@method_decorator(custom_login)
def __call__(self, request, **kwargs):
#bla bla view stuff...
pass
Questo problema è emerso prima . È inclusa una soluzione che potrebbe funzionare per te.
Aggiornamento: metodo di esempio con decoratore:
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
Invece di usare il decoratore nella vista puoi decorare l'URL.
Ad esempio in urls.py:
from my_decorators import myuser_login_required
from my_views import TopSecretPage
urlpatterns = patterns('',
(r'^whatever-the-url-is/
Potrebbe essere necessario giocarci un po 'ma è giusto.
, myuser_login_required(TopSecretPage), {}),
)
Potrebbe essere necessario giocarci un po 'ma è giusto.
Questo è effettivamente un duplicato di Django - Modo corretto di passare argomenti ai decoratori di CBV? che descrive il modo corretto di affrontarlo. Il modo corretto di farlo per django 1.9 è il seguente:
@method_decorator(myuser_login_required(), name='dispatch')
class TopSecretPage(View):
..