174 votes

Comment utiliser permission_required décorateurs sur django basés sur une classe vues

Je vais avoir un peu de mal à comprendre comment le nouveau CBVs travail. Ma question est la suivante, j'ai besoin d'exiger de connexion dans tous les points de vue, et dans certains d'entre eux, des autorisations spécifiques. En fonction des vues basées sur les je le fais avec @permission_required() et le login_required attribut de la vue, mais je ne sais pas comment le faire sur le nouveau point de vue. Est-il un article dans le django docs expliquer cela? Je n'ai pas trouvé quoi que ce soit. Quel est le problème dans mon code?

J'ai essayé d'utiliser le @method_decorator mais il répond "erreur TypeError à l' /espaces/prueba/ _wrapped_view() prend au moins 1 argument (0)"

Voici le code (GPL):

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required, permission_required

class ViewSpaceIndex(DetailView):

    """
    Show the index page of a space. Get various extra contexts to get the
    information for that space.

    The get_object method searches in the user 'spaces' field if the current
    space is allowed, if not, he is redirected to a 'nor allowed' page. 
    """
    context_object_name = 'get_place'
    template_name = 'spaces/space_index.html'

    @method_decorator(login_required)
    def get_object(self):
        space_name = self.kwargs['space_name']

        for i in self.request.user.profile.spaces.all():
            if i.url == space_name:
                return get_object_or_404(Space, url = space_name)

        self.template_name = 'not_allowed.html'
        return get_object_or_404(Space, url = space_name)

    # Get extra context data
    def get_context_data(self, **kwargs):
        context = super(ViewSpaceIndex, self).get_context_data(**kwargs)
        place = get_object_or_404(Space, url=self.kwargs['space_name'])
        context['entities'] = Entity.objects.filter(space=place.id)
        context['documents'] = Document.objects.filter(space=place.id)
        context['proposals'] = Proposal.objects.filter(space=place.id).order_by('-pub_date')
        context['publication'] = Post.objects.filter(post_space=place.id).order_by('-post_pubdate')
        return context

237voto

A Lee Points 3052

Voir https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-class-based-views

Vous pouvez ajouter le décorateur urls.py, par exemple,

login_required(ViewSpaceIndex.as_view(..))

ou décorer l' dispatch méthode de method_decorator par exemple,

from django.utils.decorators import method_decorator

@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
    return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)

La raison pour laquelle vous êtes l'obtention d'un TypeError est expliqué dans la doc:

Note: method_decorator passe *args et **kwargs comme paramètres à la décorées méthode de la classe. Si votre méthode n'accepte pas compatible d'un ensemble de paramètres qu'il va lever une exception TypeError.

120voto

Gert Steyn Points 1455

Voici mon approche, j’ai créer un mixin qui est protégé (ce qui est conservé dans ma bibliothèque mixin) :

Chaque fois que vous souhaitez un affichage à protéger il suffit d’ajouter le mixin approprié :

Assurez-vous juste que votre mixin est premier.

47voto

mjtamlyn Points 824

Voici une alternative à l’aide de décorateurs de classe en fonction :

Cela peut alors servir simplement comme ceci :

14voto

mephisto Points 145

Je me rends compte de ce thread est un peu daté, mais voici mes deux cents, de toute façon.

avec le code suivant:

from django.utils.decorators import method_decorator
from inspect import isfunction

class _cbv_decorate(object):
    def __init__(self, dec):
        self.dec = method_decorator(dec)

    def __call__(self, obj):
        obj.dispatch = self.dec(obj.dispatch)
        return obj

def patch_view_decorator(dec):
    def _conditional(view):
        if isfunction(view):
            return dec(view)

        return _cbv_decorate(dec)(view)

    return _conditional

nous avons maintenant un moyen de patcher un décorateur, de sorte qu'il deviendra multifonctionnel. Cela signifie que lorsqu'il est appliqué à un affichage normal décorateur, comme suit:

login_required = patch_view_decorator(login_required)

ce décorateur continue de fonctionner lorsque utilisées de la façon dont il était initialement prévu:

@login_required
def foo(request):
    return HttpResponse('bar')

mais aussi travailler correctement lorsqu'il est utilisé comme suit:

@login_required
class FooView(DetailView):
    model = Foo

Cela semble bien fonctionner dans plusieurs cas, j'ai récemment rencontré, y compris en ce monde réel, exemple:

@patch_view_decorator
def ajax_view(view):
    def _inner(request, *args, **kwargs):
        if request.is_ajax():
            return view(request, *args, **kwargs)
        else:
            raise Http404

    return _inner

Le ajax_view fonction est écrite pour modifier une (fonction de base) de la vue, de sorte qu'il soulève une erreur 404 à chaque fois que ce point de vue est visité par un appel ajax. Simplement en appliquant le patch de la fonction en tant que décorateur, ce décorateur est tous ensemble pour le travail en classe en fonction d'une vue sur la

4voto

kaleissin Points 577

Si c’est un site où la majorité des pages requiert que l’utilisateur se connecte, vous pouvez utiliser un middleware pour forcer la connexion sur toutes les vues sauf quelques-uns qui sont particulièrement marqués.

middleware.py :

views.py :

Vues de tiers que vous ne voulez pas envelopper peuvent être faites dispensé dans les paramètres :

Settings.py :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X