2010-04-22 3 views
40

Je suis en train d'écrire un « personnel que » décorateur pour Django, mais je ne peux pas sembler le faire fonctionner:Django: décorateur personnel

def staff_only(error='Only staff may view this page.'): 
    def _dec(view_func): 
     def _view(request, *args, **kwargs): 
      u = request.user 
      if u.is_authenticated() and u.is_staff: 
       return view_func(request, *args, **kwargs) 
      messages.error(request, error) 
      return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('home'))) 
     _view.__name__ = view_func.__name__ 
     _view.__dict__ = view_func.__dict__ 
     _view.__doc__ = view_func.__doc__ 
     return _view 
    return _dec 

Essayer de follow lead from here. Je reçois:

'WSGIRequest' object has no attribute '__name__'

Mais si je prends ces 3 lignes, je juste obtenir un inutile "Internal Server Error". Qu'est-ce que je fais mal ici?

Répondre

10

Ce style de la fonction décorateur est utilisé avec un décorateur paramétré - par exemple lorsque vous faites:

@staffonly(my_arguments) 
def function(request): 
    blah 

Si vous n'êtes pas réellement appeler la fonction externe, à savoir que vous utilisez comme ceci:

@staffonly 
def function(request): 

Vous obtiendrez des résultats bizarres, car l'objet fonction sera transmis à la mauvaise des fonctions imbriquées dans le décorateur.

+0

Oh ... alors comment je contourne ça? – mpen

+1

Je commence à comprendre, donc si j'ai plusieurs fonctions à mon avis, je dois ajouter @staffonly devant chacun d'entre eux? –

128

Ce décorateur existe déjà

from django.contrib.admin.views.decorators import staff_member_required 

@staff_member_required 

Tronc: http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/decorators.py

+0

Oh ... cool. Je veux toujours savoir comment je le code bien;) – mpen

+1

Aussi, le problème avec cela est qu'il n'affiche pas un message d'erreur indiquant quel est le problème. Mes clients sont susceptibles d'essayer de visiter une page du personnel sans compte d'utilisateur. – mpen

+0

Luke (ou Mark), utilisez la source! Dans 'django/contrib/admin/views/decorators.py' (ligne 26 dans la version 1.1.1), vous trouverez cette fonction, et sur la ligne 71, vous verrez' if user.is_active et user.is_staff: ' ce qui donne le pouce en l'air. La seule raison pour laquelle ce décorateur particulier est un peu plus compliqué que la normale est parce qu'il peut déclencher une séquence de connexion comme un effet secondaire. Si vous en avez besoin pour en faire plus (par exemple, des messages d'erreur différents), vous pouvez toujours faire une copie et ensuite appeler votre propre décorateur, le cas échéant. –

2

Pour Based View classe s, vous pouvez décorer la méthode de répartition de la classe d'affichage, comme ceci:

from django.contrib.admin.views.decorators import staff_member_required 
from django.utils.decorators import method_decorator 


@method_decorator(staff_member_required, name='dispatch') 
class ExampleTemplateView(TemplateView): 
    ...