73 votes

Comment écrire un décorateur personnalisé dans django ?

Le problème -

@is_premium_user
def sample_view:
          .......
          ......

Je veux que certaines vues soient accessibles uniquement aux utilisateurs premium du site.
Et comment puis-je utiliser ce décorateur dans diverses applications de mon projet ?

84voto

PhoebeB Points 2862

J'ai joué avec les différents liens ci-dessus et n'ai pas réussi à les faire fonctionner, puis je suis tombé sur ce lien très simple que j'ai adapté. http://code.activestate.com/recipes/498217-custom-django-login_required-decorator/

from functools import wraps
from django.http import HttpResponseRedirect

def authors_only(function):
  @wraps(function)
  def wrap(request, *args, **kwargs):

        profile = request.user.get_profile()
        if profile.usertype == 'Author':
             return function(request, *args, **kwargs)
        else:
            return HttpResponseRedirect('/')

  return wrap

Utilisation de @wraps es mejor plutôt que de les remplacer manuellement en faisant wrap.__doc__ = fn.__doc__ . Il permet, entre autres, de s'assurer que la fonction wrapper porte le même nom que la fonction wrapped.

Voir https://docs.python.org/2/library/functools.html

0 votes

Cela devrait être la réponse acceptée, pouce en l'air ! J'ai essayé de m'appuyer sur le décorateur user_passes_test mais je me suis perdu, ceci m'a sauvé la mise.

0 votes

@radtek j'ai wrap() takes at least 1 argument (0 given) . Un indice pour le résoudre ?

1 votes

Il faudrait voir votre code, mais il est fort probable que vous n'ayez pas passé la requête à la fonction que vous décorez.

61voto

arie Points 8860

Vous n'avez pas besoin d'écrire votre propre décorateur pour cela car user_passes_test est déjà inclus dans Django.

Et il y a un extrait ( group_required_decorator ) qui étend ce décorateur et qui devrait être assez approprié pour votre cas d'utilisation.

Si vous voulez vraiment écrire votre propre décorateur, alors il y a beaucoup de bonne documentation sur le net.

Et bien, pour (ré)utiliser le décorateur, il suffit de le placer dans un module sur votre chemin et vous pouvez l'importer depuis n'importe quel autre module.

1 votes

Def souk_required() : """L'utilisateur doit être membre d'au moins un des groupes indiqués."" def has_souk(u) : if u.is_authenticated() : if bool(SoukUsers.objects.get(person = u)) : return True return False(u) return user_passes_test(has_souk)

0 votes

Cela donne cette erreur - souk_required ne prend aucun argument (1 donné)

1 votes

Hm j'ai accidentellement upvoted votre commentaire ;-) Eh bien, vous avez supprimé l'argument attendu de votre définition de fonction et donc reçu l'erreur donnée. Alors, pourquoi ne pas créer un groupe "premiumusers" et ajouter vos utilisateurs à ce groupe ? Ensuite, vous pouvez utiliser le snippet tel quel et juste passer dans le nom de votre groupe.

6voto

thnee Points 1356

Merci à arie, la réponse m'a beaucoup aidé, mais elle ne fonctionne pas pour moi.

Quand j'ai trouvé cet extrait, j'ai réussi à le faire fonctionner correctement : http://djangosnippets.org/snippets/983/

Cette solution a fonctionné pour moi :

La fonction d'aide

Cette fonction a l'avantage d'être réutilisable dans d'autres endroits, en tant que remplacement de la fonction user.is_authenticated . Elle pourrait par exemple être exposée comme une balise de modèle.

def my_custom_authenticated(user):
    if user:
        if user.is_authenticated():
            return user.groups.filter(name=settings.MY_CUSTOM_GROUP_NAME).exists()
    return False

Le décorateur

Je viens de mettre ça en haut de mon views.py puisque c'est si court.

def membership_required(fn=None):
    decorator = user_passes_test(my_custom_authenticated)
    if fn:
        return decorator(fn)
    return decorator

L'utiliser

@membership_required
def some_view(request):
    ...

2voto

Spacedman Points 33792

Voir les exemples dans django lui-même :

http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py

Votre exemple particulier n'est probablement qu'une version de 'user_passes_test' où le test est l'appartenance au groupe 'premium'.

Pour l'utiliser n'importe où, créez un paquetage python et importez-le depuis celui-ci. Tant qu'il est dans votre sys.path, il sera trouvé.

1voto

DTing Points 12969

http://www.makina-corpus.org/blog/permission-required-decorator-django

J'ai basé le mien sur cet article de blog.

Placez-les dans un fichier dans le chemin de python ou dans une application "util" et importez-les dans views :

par exemple

project_dir
|_ app1
|_ app2
|_ utils
   |_ __init__.py
   |_ permreq.py

from util.permreq import permission_required

@permmission_required('someapp.has_some_perm', template='denied.html')
def some_view(request):
    blah blah

0 votes

Vous pouvez les inscrire dans vos modèles, docs.djangoproject.com/fr/dev/topics/auth/#custom-permissions et les gérer via l'admin ou le shell django

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