2017-07-26 2 views
2

Django Anfänger hier.Unterscheiden nicht authentifizierte Benutzer in benutzerdefinierten Dekorator

Ich habe den eingebauten login_required Decorator verwendet. Ich möchte es für bestimmte Benutzer überschreiben, deren Verweis-URLs einem bestimmten Muster entsprechen (z. B. alle Benutzer, die von /buy_and_sell/ stammen).

Mein Zweck ist es, nur diesen Benutzern eine spezielle Anmeldeseite und allen anderen eine allgemeine Anmeldeseite anzuzeigen.

Ich habe an verschiedenen Beispielen von Schreiben von benutzerdefinierten Dekorateure suchen (z here, here, here und here). Aber ich finde die Definitionen für einen Anfänger schwer zu verstehen. Kann mir jemand das Verständnis eines Laien (und vorzugsweise ein illustratives Beispiel) vermitteln, wie ich mein Problem lösen kann?

Antwort

2

Dort ist user_passes_test Dekorateur in Django enthalten. Sie müssen nicht Ihren eigenen Dekorateur machen.

from django.contrib.auth.decorators import user_passes_test 

def check_special_user(user): 
    return user.filter(is_special=True) 

# if not the special user it will redirect to another login url , otherwise process the view 
@user_passes_test(check_special_user,login_url='/login/') 
def my_view(request): 
    pass 
    ... 

Need Anfrage in Dekorateur

dass eine Klon-Version von user_passes_test in Ihrem Projekt oder App machen zu tun und ändern wie folgt zu machen,

def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 
    """ 
    Decorator for views that checks that the user passes the given test, 
    redirecting to the log-in page if necessary. The test should be a callable 
    that takes the user object and returns True if the user passes. 
    """ 

    def decorator(view_func): 
     @wraps(view_func, assigned=available_attrs(view_func)) 
     def _wrapped_view(request, *args, **kwargs): 
      if test_func(request.user): # change this line to request instead of request.user 
       return view_func(request, *args, **kwargs) 
      path = request.build_absolute_uri() 
      resolved_login_url = resolve_url(login_url or settings.LOGIN_URL) 
      # If the login url is the same scheme and net location then just 
      # use the path as the "next" url. 
      login_scheme, login_netloc = urlparse(resolved_login_url)[:2] 
      current_scheme, current_netloc = urlparse(path)[:2] 
      if ((not login_scheme or login_scheme == current_scheme) and 
        (not login_netloc or login_netloc == current_netloc)): 
       path = request.get_full_path() 
      from django.contrib.auth.views import redirect_to_login 
      return redirect_to_login(
       path, resolved_login_url, redirect_field_name) 
     return _wrapped_view 
    return decorator 

Änderung test_func (request .user) zu test_func (request) und Sie erhalten ganze Anfrage in Ihrer Decorator-Funktion.

bearbeiten: In url.py,

url (
    r'^your-url$', 
    user_passes_test(check_special_user, login_url='/login/')(
     my_view 
    ), 
    name='my_view' 
) 
+0

Frage: Wie würde ich die Verweisung url in 'check_special_user' bekommen? Ich habe keine "Anfrage" dort. – Sophia111

+0

Keine Anfrage kann in user_passes_test method decorator nicht verwendet werden. Was versuchst du genau? – Aniket

+0

Wie ich in meiner Frage erwähnt habe, versuche ich eine spezielle Anmeldeseite ** unauth users ** zu zeigen, die von bestimmten URLs in meiner App stammen (z. B. '/ buy_and_sell /'). Alle anderen Unauthenutzer würden eine generische Anmeldeseite angezeigt bekommen. Ich muss den Inhalt von 'request.META.get ('HTTP_REFERER') 'dafür betrachten. – Sophia111

1

hier die beste Antwort Python Dekorateure zu verstehen: How to make a chain of function decorators?

können Sie verwenden login_url Argument von login_required:

@login_required(login_url='some_url) 

Ein anderer Weg ist t o Erstellen eines benutzerdefinierten Dekorateur, ein Beispiel aus dem documentation of Django:

from django.contrib.auth.decorators import user_passes_test 

def email_check(user): 
    return user.email.endswith('@example.com') 

@user_passes_test(email_check) 
def my_view(request): 
    ... 
+0

Haben Sie einen Grund gesehen, meine Antwort zu ändern? – Aniket

+1

Jedenfalls gebe ich Ihnen +1 für Ihre Antwort. – Aniket

Verwandte Themen