it-swarm.com.de

Wie schreibe ich einen benutzerdefinierten Dekorateur in Django?

Das Problem -

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

.

49
user677990

Sie müssen dafür keinen eigenen Dekorateur schreiben als user_passes_test ist bereits in Django enthalten.

Und es gibt einen Ausschnitt ( group_required_decorator ) das erweitert diesen Dekorateur und das sollte für Ihren Anwendungsfall ziemlich passend sein.

Wenn Sie wirklich Ihren eigenen Dekorateur schreiben möchten, dann gibt es eine Menge gute Dokumentation im Netz.

Und nun, um den Dekorator (wieder) zu verwenden, setzen Sie einfach Ihren Dekorator in ein Modul auf Ihrem Pfad und Sie können ihn von jedem anderen Modul importieren.

49
arie

Ich habe oben mit den verschiedenen Links herumgespielt und konnte sie nicht zum Laufen bringen. Dann bin ich auf diese wirklich einfache gestoßen, die ich angepasst habe. 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

Mit @wraps ist besser als manuelles Überschreiben wie wrap.__doc__ = fn.__doc__. Unter anderem wird sichergestellt, dass Ihre Wrapper-Funktion denselben Namen wie die Wrapper-Funktion erhält.

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

49
PhoebeB

Dank Arie hat die Antwort viel geholfen, aber bei mir funktioniert es nicht.

Als ich dieses Snippet fand, funktionierte es einwandfrei: http://djangosnippets.org/snippets/983/

Diese Lösung hat bei mir funktioniert:

Die Hilfsfunktion

Diese Funktion hat den Vorteil, dass sie an anderen Orten wiederverwendet werden kann, um user.is_authenticated. Es könnte zum Beispiel als Template-Tag verfügbar gemacht werden.

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

Der Dekorateur

Ich habe das oben in mein views.py, da es so kurz ist.

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

Verwendung

@membership_required
def some_view(request):
    ...
5
thnee

Beispiele finden Sie in Django selbst:

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

Ihr spezielles Beispiel ist wahrscheinlich nur eine Version von 'user_passes_test', bei der der Test zur 'Premium'-Gruppe gehört.

Erstellen Sie ein python - Paket und importieren Sie es von dort. Solange es sich auf Ihrem sys.path befindet, wird es gefunden.

2
Spacedman

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

ich habe meins von diesem Blog-Post abgeleitet.

Stecken Sie das in eine Datei im python Pfad oder in eine "util" App und importieren Sie sie in Views:

, z. B.

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
1
DTing

Hier ist eine etwas andere Implementierung, die zusätzliche Parameter zulässt, um anzugeben, zu welcher Seite umgeleitet werden soll, wenn die Validierung fehlschlägt, und welche Nachricht dem Endbenutzer angezeigt werden soll:

from functools import wraps
from Django.core.urlresolvers import reverse
from Django.http import HttpResponseRedirect
from core.helpers.flash import send_flash_error

def lender_only(redirect_to='plateforme.views.vue_login', error_flash_message=None):
  def inner_render(fn):
    @wraps(fn)  # Ensure the wrapped function keeps the same name as the view
    def wrapped(request, *args, **kwargs):
      if request.context.user.is_authenticated and request.context.user.is_lender:
        return fn(request, *args, **kwargs)
      else:
        if error_flash_message:
          send_flash_error(request, error_flash_message) # Replace by your own implementation

        return HttpResponseRedirect(reverse(redirect_to))
    return wrapped
  return inner_render

# Usage:
@lender_only('vitrine.views.projets', {'message': "Oops, can't go there."})
def render_page_index(request):

Dieser Leitfaden hat mir dabei geholfen: https://elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-Django-goodness/ neben den vorherigen Antworten

0
Vadorequest