So melden Sie einen Benutzer nach der Registrierung in Django automatisch an

73

Folgendes verwende ich derzeit für die Registrierung:

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            messages.info(request, "Thanks for registering. Please login to continue.")
            return HttpResponseRedirect("/dashboard/")
    else:
        form = UserCreationForm()
    return render_to_response("accounts/register.html", {
        'form': form,
    }, context_instance=RequestContext(request))

Ist es möglich, dass sich der Benutzer nach dem Erstellen eines Kontos nicht manuell anmelden muss, sondern sich einfach automatisch anmeldet? Vielen Dank.

edit: Ich hatte die Funktion login () ohne Erfolg ausprobiert. Ich glaube, das Problem ist, dass AUTHENTICATION_BACKENDS nicht gesetzt wurde.

Chris
quelle
Ich denke, Sie können dies verwenden: docs.djangoproject.com/de/dev/topics/auth/…
Oscar Carballal

Antworten:

106

Verwenden der authenticate()und login()-Funktionen:

from django.contrib.auth import authenticate, login

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            messages.info(request, "Thanks for registering. You are now logged in.")
            new_user = authenticate(username=form.cleaned_data['username'],
                                    password=form.cleaned_data['password1'],
                                    )
            login(request, new_user)
            return HttpResponseRedirect("/dashboard/")
Ben James
quelle
1
Vielen Dank. Ich hatte dies ohne Erfolg versucht, aber jetzt stelle ich fest, dass das Problem darin bestand, dass ich das Backend nicht angegeben hatte. Die Zeilen: new_user.backend = 'django.contrib.auth.backends.ModelBackend' Login (Anfrage, new_user) machen den Trick. (Oder sollte das Backend an anderer Stelle angegeben werden und nicht jedes Mal, wenn eine Registrierung erfolgt?)
Chris
2
Setzen Sie AUTHENTICATION_BACKENDSauf django.contrib.auth.backends.ModelBackendin settings.py. Weitere Informationen finden Sie unter docs.djangoproject.com/de/1.2/topics/auth/… .
David Antaramian
3
Ah, du musst authenticate()zuerst anrufen, sonst gibt es kein backendSet. Ich habe meine Antwort aktualisiert, um dies zu zeigen.
Ben James
2
Eine andere Sache, die mich hier oben stolperte, war, dass man beim authenticateIng rohe Saiten verwenden muss . Ich habe versucht, klug zu sein und es vom ursprünglichen new_userObjekt wegzuschleichen, aber ich stelle mir vor, dass dies einige der Referenzen aus den Feldern mit sich brachte. Das heißt, tu es nicht: new_user = authenticate(username = new_user.username, password = new_user.password)hol sie POSTdir lieber wie im Snippet beschrieben oder von der form.
Alex Beynenson
11
Hat perfekt funktioniert. Es ist wahrscheinlich besser, die Felder des validierten Formulars im Gegensatz zu den POST-Daten direkt zu verwenden, falls sie während der Validierung aus irgendeinem Grund geändert werden. new_user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password'])
Patrick
9

Für klassenbasierte Ansichten war hier der Code, der für mich funktioniert hat (ursprünglich Django 1.7, aktualisiert für 2.1).

from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.views.generic import FormView

class SignUp(FormView):
    template_name = 'signup.html'
    form_class = UserCreateForm
    success_url='/account'

    def form_valid(self, form):
        #save the new user first
        form.save()
        #get the username and password
        username = self.request.POST['username']
        password = self.request.POST['password1']
        #authenticate user then login
        user = authenticate(username=username, password=password)
        login(self.request, user)
        return HttpResponseRedirect(self.get_success_url)
colins44
quelle
Warum authenticate(username=username, password=password)wird benötigt? Warum nicht einfach das Benutzerobjekt übergeben?
Avi
1
@avi Wenn Sie einen Benutzer manuell anmelden, müssen Sie den Benutzer erfolgreich mit authenticate () authentifizieren, bevor Sie login () aufrufen. authenticate () legt dem Benutzer ein Attribut fest, das angibt, welches Authentifizierungs-Backend diesen Benutzer erfolgreich authentifiziert hat (Einzelheiten finden Sie in der Backend-Dokumentation). Diese Informationen werden später während des Anmeldevorgangs benötigt. Ein Fehler wird ausgelöst, wenn Sie versuchen, ein Benutzerobjekt anzumelden, das direkt aus der Datenbank abgerufen wurde. Quelle: docs.djangoproject.com/de/1.9/topics/auth/default/…
f1nn
Dies funktionierte nicht sofort in Django 2.1.4. Ich musste eine andere Rückgabe verwenden redirect, siehe meine separate [Frage] ( stackoverflow.com/questions/54179736/… )
sc28
1
@ sc28 Ich habe die Antwort aktualisiert, um mit späteren Versionen von Django zu arbeiten.
Alasdair
0

Sie können die UserCreationForm von Django in Unterklassen unterteilen und die Speichermethode überschreiben, um sie anzumelden, wenn commit = True.

forms.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login

class CustomUserCreationForm(UserCreationForm):
    """
    A ModelForm for creating a User and logging 
    them in after commiting a save of the form.
    """

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    class Meta(UserCreationForm.Meta):
        pass

    def save(self, commit=True):
        user = super().save(commit=commit)
        if commit:
            auth_user = authenticate(
                username=self.cleaned_data['username'], 
                password=self.cleaned_data['password1']
            )
            login(self.request, auth_user)

        return user

Sie müssen nur sicherstellen, dass Sie ein Anforderungsobjekt übergeben, wenn Sie das Formular instanziieren. Sie können dies tun, indem Sie die Methode get_form_kwargs der Ansicht überschreiben.

views.py

def get_form_kwargs(self):
    form_kwargs = super().get_form_kwargs()
    form_kwargs['request'] = self.request
    return form_kwargs

Oder stellen Sie sicher, wenn Sie eine form_class instanziieren CustomUserCreationForm(data=request.POST, request=self.request).

QFXC
quelle