Django: Angemeldete Benutzer von der Anmeldeseite umleiten

71

Ich möchte meine Website so einrichten, dass ein Benutzer, der auf die /loginSeite gelangt und bereits angemeldet ist, auf die Startseite umgeleitet wird. Wenn sie nicht angemeldet sind, wird sie normal angezeigt. Wie kann ich das tun, da der Anmeldecode in Django integriert ist?

kqw
quelle

Antworten:

83

Ich gehe davon aus, dass Sie derzeit die integrierte Anmeldeansicht mit verwenden

(r'^accounts/login/$', 'django.contrib.auth.views.login'),

oder etwas ähnliches in deinen URLs.

Sie können Ihre eigene Anmeldeansicht schreiben, die die Standardansicht umschließt. Es wird überprüft, ob der Benutzer bereits angemeldet ist, und umgeleitet, falls dies der Fall ist. Andernfalls wird die Standardansicht verwendet.

etwas wie:

from django.contrib.auth.views import login

def custom_login(request):
    if request.user.is_authenticated():
        return HttpResponseRedirect(...)
    else:
        return login(request)

und natürlich ändern Sie Ihre URLs entsprechend:

(r'^accounts/login/$', custom_login),
Ofri Raviv
quelle
18
Sie sollten custom_loginmit einem zweiten Argument deklarieren **kwargs, damit alle Argumente, die Sie nicht interessieren, an die integrierte loginAnsicht übergeben werden.
viam0Zah
15
Warum ist dieses Standardverhalten nicht? Ich kann mir keine Situation vorstellen, in der ein bereits angemeldeter Benutzer die Anmeldeseite sehen sollte.
Timmy O'Mahony
2
Ein bereits angemeldeter Benutzer kann LOGIN_URLvon user_passes_test(und damit permission_required) Dekorateuren weitergeleitet werden, wenn er nicht über die erforderlichen Berechtigungen verfügt, um auf eine bestimmte Ansicht zuzugreifen.
Anatoly Rr
Wie übergebe ich das Diktat {'template_name':} an die Anmeldeansicht von django, wenn Sie es so verwenden?
MohitC
Sie können es alslogin(request, template_name = 'user/login.html')
Sachin G.
61

Der Django 1.10 Weg

Für Django 1.10, das im August 2016 veröffentlicht wurde, redirect_authenticated_userwurde der login()funktionsbasierten Ansicht in django.contrib.auth[1] ein neuer Parameter mit dem Namen hinzugefügt .

Beispiel

Angenommen, wir haben eine Django-Anwendung mit einer Datei mit dem Namen views.pyund einer anderen Datei mit dem Namen urls.py. Die urls.pyDatei enthält folgenden Python-Code:

#
# Django 1.10 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', auth_views.login, name='login',
        kwargs={'redirect_authenticated_user': True}),
    url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]

Aus dieser Datei ist der relevante Teil innerhalb der urlpatternsVariablendefinition der folgende, der den bereits erwähnten redirect_authenticated_userParameter mit einem TrueWert verwendet:

    url(r'^login/', auth_views.login, name='login',
        kwargs={'redirect_authenticated_user': True}),

Beachten Sie, dass der Standardwert des redirect_authenticated_userParameters ist False.

Der Django 1.11 Weg

Für Django 1.11, das im April 2017 veröffentlicht wurde, hat die LoginViewklassenbasierte Ansicht die login()funktionsbasierte Ansicht [2] abgelöst, sodass Sie zwischen zwei Optionen wählen können:

  • Verwenden Sie die gleiche Django 1.10-Methode, die gerade beschrieben wurde. Dies ist positiv, da Ihr aktueller Code weiterhin einwandfrei funktioniert. Wenn Sie den Python-Interpreter anweisen, Warnungen anzuzeigen, indem Sie beispielsweise in einem Konsolenterminal den Befehl python -Wd manage.py runserverin Ihrem Django-Projektverzeichnis ausführen und dann mit einem Webbrowser zu Ihrer Anmeldeseite wechseln, wird in demselben Konsolenterminal eine Warnmeldung wie die folgende angezeigt:

/usr/local/lib/python3.6/site-packages/django/contrib/auth/views.py:54: RemovedInDjango21Warning: Die Ansicht login () wird durch die klassenbasierte LoginView () ersetzt.

  • Verwenden Sie das Neue Django 1.11 way, um Ihren Code moderner und kompatibler mit zukünftigen Django-Versionen zu machen. Mit dieser Option sieht das zuvor angegebene Beispiel nun wie folgt aus:

Beispiel

Wir nehmen wieder an, dass wir eine Django-Anwendung mit einer Datei namens views.pyund einer anderen Datei namens haben urls.py. Die urls.pyDatei enthält folgenden Python-Code:

#
# Django 1.11 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',
        auth_views.LoginView.as_view(redirect_authenticated_user=True),
        name='login'),
    url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]

Aus dieser Datei ist der relevante Teil innerhalb der urlpatternsVariablendefinition der folgende, der wiederum den bereits erwähnten redirect_authenticated_userParameter mit einem TrueWert verwendet, ihn jedoch als Argument an die as_viewMethode der LoginViewKlasse übergibt :

    url(r'^login/',
        auth_views.LoginView.as_view(redirect_authenticated_user=False),
        name='login'),

Beachten Sie, dass hier auch der Standardwert des redirect_authenticated_userParameters ist False.

Verweise

rodolfojcj
quelle
1
@ Quique gab eine nette Lösung, die mit Django 2.x stackoverflow.com/a/53764272/9177173
ohlr
Ich erhalte diesen Fehler, wenn ich diese Methode befolge. login () fehlt 1 erforderliches Positionsargument: 'user'. Ich habe diesen Fehler beim Upgrade auf Django 2.2 erhalten. Gibt es einen Grund, wie man es klärt?
Venkatesh Gotimukul
25

anonym_erforderlicher Dekorateur

Für klassenbasierte Ansichten

Code:

from django.shortcuts import redirect

def anonymous_required(func):
    def as_view(request, *args, **kwargs):
        redirect_to = kwargs.get('next', settings.LOGIN_REDIRECT_URL )
        if request.user.is_authenticated():
            return redirect(redirect_to)
        response = func(request, *args, **kwargs)
        return response
    return as_view

Verwendung:

url(r'^/?$',
   anonymous_required(auth_views.login),
),
url(r'^register/?$',
    anonymous_required(RegistrationView.as_view()),
    name='auth.views.register'
),
# Could be used to decorate the dispatch function of the view instead of the url

Für Ansichtsfunktionen

Von http://blog.motane.lu/2010/01/06/django-anonymous_required-decorator/

Code:

from django.http import HttpResponseRedirect

def anonymous_required( view_function, redirect_to = None ):
    return AnonymousRequired( view_function, redirect_to )

class AnonymousRequired( object ):
    def __init__( self, view_function, redirect_to ):
        if redirect_to is None:
            from django.conf import settings
            redirect_to = settings.LOGIN_REDIRECT_URL
        self.view_function = view_function
        self.redirect_to = redirect_to

    def __call__( self, request, *args, **kwargs ):
        if request.user is not None and request.user.is_authenticated():
            return HttpResponseRedirect( self.redirect_to )
        return self.view_function( request, *args, **kwargs )

Verwendung:

@anonymous_required
def my_view( request ):
    return render_to_response( 'my-view.html' )
laffuste
quelle
1
Die Verwendung eines Dekorateurs ist die beste Antwort. Diese Art von Logik überfrachtet nur die tatsächlichen Ansichten.
Kevin Stone
Und für CBVs ist es wirklich besser, es als Mixin und Überladung zu schreiben dispatch(). Siehe Django-Klammern für viele Beispiele.
Kevin Stone
Hey, du solltest mehr Stimmen für deine Antwort bekommen. bei weitem die bessere Antwort und viel vielseitiger eines Ansatzes.
Aaron Lelevier
Ich erhalte diesen Fehler, wenn ich diese Methode befolge. login () fehlt 1 erforderliches Positionsargument: 'user'. Gibt es einen Grund, wie man es klärt?
Venkatesh Gotimukul
16

Für Django 2.x in Ihrer urls.py:

from django.contrib.auth import views as auth_views
from django.urls import path

urlpatterns = [
    path('login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]
Quique
quelle
Dies funktioniert perfekt mit Django 2.x. Die gesamte Liste der auth_urls finden Sie auf github: github.com/django/django/blob/master/django/contrib/auth/…
ohlr
Wie mache ich eine Weiterleitung, wenn ich meine URL habe und django loginview wie unten verwende? urlpatterns = [url (r '^ $', LoginView.as_view (template_name = 'Landing.html'), name = 'Landing')]
Venkatesh Gotimukul
Arbeitet in Django 3
Alejandro
11

Fügen Sie diesen Dekorator über Ihrer Anmeldeansicht hinzu, um zu / home umzuleiten, wenn ein Benutzer bereits angemeldet ist

@user_passes_test(lambda user: not user.username, login_url='/home', redirect_field_name=None)

und vergessen Sie nicht, den Dekorateur zu importieren

from django.contrib.auth.decorators import user_passes_test

Stephen
quelle
Ich finde es toll, wie mein Vorschlag ohne Erklärung abgelehnt wurde. Ich bin besonders stolz auf diese Entdeckung, weil sie elegant, pragmatisch und ein Einzeiler ist!
Stephen
Dies ist die eleganteste Lösung imo.
Sandeep Raju Prabhakar
Dies ist großartig, wenn Sie nicht die generischen Ansichten von django.contrib.auth
cardonator
1
user.is_anonymous()ist möglicherweise besser als das Testen des Benutzernamens.
Tim Tisdall
1
Ich denke, die Ablehnung hängt möglicherweise damit zusammen, dass diese Funktion speziell dazu dient, Personen auf die Anmeldeseite umzuleiten. Beispielsweise wird die aktuelle URL in eine nextGET-Variable codiert .
Tim Tisdall
9

Schon seit klassenbasierte Ansichten (CBVs) auf dem Vormarsch sind. Mit diesem Ansatz können Sie zu einer anderen URL umleiten, wenn Sie nur für nicht authentifizierte Benutzer auf die Ansicht zugreifen.

In meinem Beispiel die Anmelde- zwingende Seite die dispatch()Methode.

class Signup(CreateView):
    template_name = 'sign-up.html'

    def dispatch(self, *args, **kwargs):
        if self.request.user.is_authenticated:
            return redirect('path/to/desired/url')
        return super().dispatch(*args, **kwargs)

Prost!

Roel
quelle
3

Ich weiß, dass dies eine ziemlich alte Frage ist, aber ich werde meine Technik hinzufügen, falls jemand anderes sie benötigt:


myproject / myapp / views / misc.py

from django.contrib.auth.views import login as contrib_login, logout as contrib_logout
from django.shortcuts import redirect
from django.conf import settings


def login(request, **kwargs):
    if request.user.is_authenticated():
        return redirect(settings.LOGIN_REDIRECT_URL)
    else:
        return contrib_login(request, **kwargs)

logout = contrib_logout

myproject / myapp / urls.py.

from django.conf.urls import patterns, url

urlpatterns = patterns('myapp.views.misc',
    url(r'^login/$', 'login', {'template_name': 'myapp/login.html'}, name='login'),
    url(r'^logout/$', 'logout', {'template_name': 'myapp/logout.html'}, name='logout'),
)
...
dgel
quelle
0

Angenommen, Sie sind mit dem Einrichten der integrierten Django-Benutzerauthentifizierung (und der Verwendung von Dekoratoren) fertig, fügen Sie dies in Ihrer settings.py hinzu:

LOGIN_REDIRECT_URL = '/welcome/'

HINWEIS: '/ welcome /' hier ist die URL der Homepage. Es liegt an Ihnen, durch was Sie es ersetzen möchten.

Erstaunlicher Angelo
quelle
-1, LOGIN_REDIRECT_URL wird nur verwendet, wenn sich ein Benutzer erfolgreich anmeldet
Tomasz Zieliński
-6

Alles was Sie tun müssen, ist die "root" URL auf die Homepage Ansicht zu setzen. Da die Startseitenansicht für angemeldete Benutzer bereits eingeschränkt ist, werden anonyme Benutzer automatisch auf die Anmeldeseite umgeleitet.

Kepp die URL wie sie ist. Und füge etwas hinzu wie:

(r'^$', 'my_project.my_app.views.homepage'),
Luiz C.
quelle
1
Bitte lesen Sie das OP sorgfältig durch. Die Frage ist, wie angemeldete Benutzer von der Anmeldeseite umgeleitet werden können, wenn sie bereits authentifiziert wurden. Die integrierte loginAnsicht deckt diesen Fall nicht ab.
viam0Zah
Der von mir vorgeschlagene Ansatz funktioniert genauso gut. Er möchte nur, dass angemeldete Benutzer die Anmeldeseite überspringen. Mein Ansatz legt nahe, dass die Hauptseite (Stammseite) die Startseite ist. Da die Anmeldeseite der Startseite eingeschränkt ist, werden anonyme Benutzer zur Anmeldeseite weitergeleitet. Ich habe diesen Ansatz schon einmal verwendet. Notieren Sie meine Lösung nicht, weil Sie sie nicht verstehen.
Luiz C.
2
Das Problem wird immer noch nicht behoben. Ein angemeldeter Benutzer kann weiterhin die Anmeldeseite erreichen (durch Eingabe der URL oder was auch immer).
Gerardo Marset
"Du verstehst es nicht" LoL - du hast die Frage nicht verstanden
JC Rocamonde