Wie kann ich mich für Django Generic Views anmelden?

87

Ich möchte den Zugriff auf URLs beschränken, die von Django Generic Views verarbeitet werden.

Für meine Ansichten weiß ich, dass der login_requiredDekorateur den Job macht. Auch generische Ansichten erstellen / löschen / aktualisieren übernehmen das login_requiredArgument, aber ich konnte keine Möglichkeit finden, dies für andere generische Ansichten zu tun.

hamdiakoguz
quelle

Antworten:

105

Für Django <1.5 können Sie einen Dekorator hinzufügen, indem Sie die Funktion in Ihre URLs einschließen, sodass Sie die allgemeinen Ansichten umschließen können:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

Die funktionsbasierten generischen Ansichten sind in Django 1.4 veraltet und wurden in Django 1.5 entfernt. Es gilt jedoch das gleiche Prinzip. Schließen Sie einfach die Ansichtsfunktion der klassenbasierten Ansicht mit dem login_requiredDekorator ein:

login_required(TemplateView.as_view(template_name='foo_index.html'))
Will Hardy
quelle
Hier erfahren Sie, wie Sie login_url angeben . Login_required (TemplateView.as_view (template_name = 'foo_index.html'))
Saisiva A
100

Django 1.9 oder mit Django-Klammern

Django 1.9 hat ein LoginRequiredMixin eingeführt , das folgendermaßen verwendet wird:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Wenn Sie eine ältere Version von Django verwenden, können Sie fast das gleiche Mixin von Django-Klammern verwenden - die Django-Version basierte auf der Django-Klammer-Version. django-braces 1.4.x unterstützt weiterhin Django 1.4, sodass Sie es mit ziemlich alten Versionen verwenden können.

Ältere Methoden

Ich habe diese Frage gefunden, als ich gegoogelt habe, wie klassenbasierte Ansichten dekoriert werden sollen, um die Antwort darauf hinzuzufügen:

Dies wird im Dokumentationsabschnitt zum Dekorieren klassenbasierter Ansichten behandelt . Es gibt den urls.pyWrapper, oder Sie können den Dekorator auf die dispatch()Methode anwenden . Beispiele aus der Dokumentation:

Dekorieren in URL conf

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = patterns('',
    (r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    (r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)

Die Klasse dekorieren

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

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

Weitere Informationen finden Sie in der oben verlinkten Dokumentation.

Hamish Downer
quelle
GENIAL! aber ich habe eine einfache Klasse mit nur def dispatchMethode als Unterklasse von gemacht View. Jetzt kann ich einfach so etwas machen:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR
Wenn ich die login_url nicht setze, sondern diese auf settings.py setze, wird sie standardmäßig darauf umgeleitet?
Cookie
38

Die generischen Ansichten wurden von Funktionen zu Objekten mit Version 1.3 von Django geändert. Daher ist eine geringfügige Änderung erforderlich, damit die Antworten von Will McCutchen und Will Hardy mit Version 1.3 funktionieren:

from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

urlpatterns = patterns('',
    (r'^foo/$', login_required(TemplateView.as_view(template_name='foo_index.html'))),
)

In der Dokumentation wird auch beschrieben, wie dies ebenfalls funktioniert.

Brian Fisher
quelle
2
Bitte, Leser, berücksichtigen Sie diese Antwort, da die Zeit vergeht und sich die Software weiterentwickelt. Die erste Lösung funktionierte bei mir nicht.
n3storm
12

Wenn Sie keinen eigenen Thin Wrapper um die betreffenden generischen Ansichten schreiben möchten (wie von Aamir vorgeschlagen), können Sie in Ihrer urls.pyDatei auch Folgendes tun :

from django.conf.urls.defaults import *

# Directly import whatever generic views you're using and the login_required
# decorator
from django.views.generic.simple import direct_to_template
from django.contrib.auth.decorators import login_required

# In your urlpatterns, wrap the generic view with the decorator
urlpatterns = patterns('',
    (r'', login_required(direct_to_template), {'template': 'index.html'}),
    # etc
)
Will McCutchen
quelle
8

Für Django 1.11 können Sie LoginRequiredMixin für klassenbasierte Ansichten verwenden

in der Einstellungsdatei sollten Sie hinzufügen

LOGIN_URL="/login/"

in Ihren views.py

from django.contrib.auth.mixins import LoginRequiredMixin

class RestaurantLocationCreateView(LoginRequiredMixin,CreateView):
    ....
Natiq Vahabov
quelle
8

Eine andere Möglichkeit, dies zu erreichen, ist unten aufgeführt. Ich finde es sehr ähnlich wie bei funktionsbasierten Ansichten und erfordert keine Änderung urls.pyoder Überschreibung dispatch:

@method_decorator(login_required, name='dispatch')
class YourGenericViewSubclass(TemplateView):
    #
    # View methods
    #
Şafak Gezer
quelle
3

Ich wollte eine wiederverwendbare Methode, um die Authentifizierung für viele Ansichten zu erfordern, die von generischen Ansichten abgeleitet sind. Ich habe eine Ersatzversandfunktion erstellt, die ich wie andere Deklarationen zu meiner Ansichtsklasse hinzufügen kann.

class Index(generic.ListView):
    model = models.HomePage
    dispatch = auth.dispatch

In auth.dispatch erledigen wir die Arbeit:

def dispatch(self, request, *args, **kw):
    """Mix-in for generic views"""
    if userSession(request):
        return  super(self.__class__, self).dispatch(request, *args, **kw)

    # auth failed, return login screen
    response = user(request)
    response.set_cookie('afterauth', value=request.path_info)
    return response
julianisch
quelle
2

In Django => 3.0 wird es ziemlich einfach:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

@method_decorator(login_required(login_url='/login/'), name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

als Referenz: https://docs.djangoproject.com/de/3.0/topics/class-based-views/intro/#decorating-the-class

bernardhilbink87
quelle
1

Verwenden Sie Folgendes:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here
Aamir Hussain
quelle
5
Basierend auf dem Datum der Frage gehe ich davon aus, dass das OP nach einer Lösung für die klassenbasierten generischen Ansichten von Django fragt ... nicht für funktionsbasierte Ansichten.
Dolph
0

Das Folgende könnte dieses Problem lösen.

// in views.py:
class LoginAuthenAJAX(View):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            jsonr = json.dumps({'authenticated': True})
        else:
            jsonr = json.dumps({'authenticated': False})
        return HttpResponse(jsonr, content_type='application/json')

// in urls.py
    path('login_auth', views.LoginAuthenAJAX.as_view(), name="user_verify"),

//in xxx.html
<script src = “{% static xxx/script.js %}” 
var login_auth_link = “{%  url user_verify %}”
</script>

// in script.js
        $.get(login_auth_link, {
            'csrfmiddlewaretoken' : csrf_token,
            },
            function(ret){
                if (ret.authenticated == false) {
                    window.location.pathname="/accounts/login/"
                }
                $("#message").html(ret.result);
            }
        )
Shuyuan Yu
quelle