Heim >Backend-Entwicklung >Python-Tutorial >Leitfaden zum Erstellen einer vollständigen Blog-App mit Django unter Verwendung der TDD-Methodik und PostgreSQL (Teilweise sichere Benutzerauthentifizierung).

Leitfaden zum Erstellen einer vollständigen Blog-App mit Django unter Verwendung der TDD-Methodik und PostgreSQL (Teilweise sichere Benutzerauthentifizierung).

Patricia Arquette
Patricia ArquetteOriginal
2024-10-18 18:18:031000Durchsuche

Willkommen zurück, alle zusammen! Im vorherigen Teil haben wir einen sicheren Benutzerregistrierungsprozess für unsere Django-Bloganwendung eingerichtet. Nach erfolgreicher Registrierung wurden wir jedoch auf die Startseite weitergeleitet. Dieses Verhalten wird geändert, sobald wir die Benutzerauthentifizierung implementieren. Durch die Benutzerauthentifizierung wird sichergestellt, dass nur autorisierte Benutzer auf bestimmte Funktionen zugreifen können, und vertrauliche Informationen werden geschützt.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
In dieser Serie erstellen wir eine vollständige Blog-Anwendung, die sich am folgenden Entity-Relationship-Diagramm (ERD) orientiert. Unser Fokus liegt dieses Mal auf der Einrichtung eines sicheren Benutzerauthentifizierungsprozesses. Wenn Sie diesen Inhalt hilfreich finden, mögen Sie ihn bitte, kommentieren Sie ihn und abonnieren Sie ihn, um auf dem Laufenden zu bleiben, wenn der nächste Teil veröffentlicht wird.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
Dies ist eine Vorschau darauf, wie unsere Anmeldeseite aussehen wird, nachdem wir die Anmeldefunktion implementiert haben. Wenn Sie die vorherigen Teile der Serie noch nicht gelesen haben, empfehle ich Ihnen, dies zu tun, da dieses Tutorial eine Fortsetzung der vorherigen Schritte ist.

Okay, fangen wir an!!

Django verfügt über eine integrierte App namens contrib.auth, die uns die Benutzerauthentifizierung vereinfacht. Sie können die Datei blog_env/settings.py überprüfen. Unter INSTALLED_APPS sehen Sie, dass Auth bereits aufgeführt ist.

# django_project/settings.py
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",  # <-- Auth app
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

Die Authentifizierungs-App bietet uns mehrere Authentifizierungsansichten für die Handhabung von Anmeldung, Abmeldung, Passwortänderung, Passwortzurücksetzung usw. Das bedeutet, dass die wesentlichen Authentifizierungsfunktionen, wie Benutzeranmeldung, Registrierung und Berechtigungen, ohne Notwendigkeit einsatzbereit sind alles von Grund auf neu zu bauen.

In diesem Tutorial konzentrieren wir uns ausschließlich auf die Anmelde- und Abmeldeansichten und behandeln die restlichen Ansichten in späteren Teilen der Serie.

1. Erstellen Sie ein Anmeldeformular

Nach unserem TDD-Ansatz beginnen wir mit der Erstellung von Tests für das Anmeldeformular. Da wir noch kein Anmeldeformular erstellt haben, navigieren Sie zur Datei „users/forms.py“ und erstellen Sie eine neue Klasse, die von AuthenticationForm erbt.

# users/forms.py
from django.contrib.auth import AuthenticationForm

class LoginForm(AuthenticationForm):


Sobald das Formular definiert ist, können wir Testfälle in „users/tests/test_forms.py“ hinzufügen, um seine Funktionalität zu überprüfen.

# users/tests/test_forms.py

#   --- other code

class LoginFormTest(TestCase):
  def setUp(self):
    self.user = User.objects.create_user(
      full_name= 'Tester User',
      email= 'tester@gmail.com',
      bio= 'new bio for tester',
      password= 'password12345'
    )

  def test_valid_credentials(self):
    """
    With valid credentials, the form should be valid
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'password12345',
      'remember_me': False
    }

    form = LoginForm(data = credentials)
    self.assertTrue(form.is_valid())

  def test_wrong_credentials(self):
    """
    With wrong credentials, the form should raise Invalid email or password error
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'wrongpassword',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertIn('Invalid email or password', str(form.errors['__all__']))

  def test_credentials_with_empty_email(self):
    """
    Should raise an error when the email field is empty
    """
    credentials = {
      'email': '',
      'password': 'password12345',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['email']))

  def test_credentials_with_empty_password(self):
    """
    Should raise error when the password field is empty
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': '',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['password']))

Diese Tests decken Szenarien wie die erfolgreiche Anmeldung mit gültigen Anmeldeinformationen, die fehlgeschlagene Anmeldung mit ungültigen Anmeldeinformationen und den angemessenen Umgang mit Fehlermeldungen ab.

Die AuthenticationForm-Klasse bietet standardmäßig einige grundlegende Validierungen. Mit unserem LoginForm können wir jedoch sein Verhalten anpassen und alle erforderlichen Validierungsregeln hinzufügen, um unsere spezifischen Anforderungen zu erfüllen.

# django_project/settings.py
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",  # <-- Auth app
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

Wir haben ein benutzerdefiniertes Anmeldeformular erstellt, das die folgenden Felder enthält: E-Mail, Passwort und Angemeldet bleiben. Das Kontrollkästchen „member_me“ ermöglicht es Benutzern, ihre Anmeldesitzung über mehrere Browsersitzungen hinweg aufrechtzuerhalten.

Da unser Formular das AuthenticationForm erweitert, haben wir einige Standardverhalten überschrieben:

  • ** __init__-Methode**: Wir haben das Standard-Benutzernamenfeld aus dem Formular entfernt, um es an unsere E-Mail-basierte Authentifizierung anzupassen.
  • clean()-Methode: Diese Methode validiert die E-Mail- und Passwortfelder. Wenn die Anmeldeinformationen gültig sind, authentifizieren wir den Benutzer mithilfe des integrierten Authentifizierungsmechanismus von Django.
  • confirm_login_allowed()-Methode: Diese integrierte Methode bietet die Möglichkeit einer zusätzlichen Überprüfung vor der Anmeldung. Sie können diese Methode bei Bedarf überschreiben, um benutzerdefinierte Prüfungen zu implementieren. Jetzt sollten unsere Tests bestehen:
# users/forms.py
from django.contrib.auth import AuthenticationForm

class LoginForm(AuthenticationForm):


2. Erstellen Sie unsere Login-Ansicht

2.1 Erstellen Sie Tests für die Anmeldeansicht

Da wir noch keine Ansicht für die Anmeldung haben, navigieren wir zur Datei „users/views.py“ und erstellen eine neue Klasse, die von der LoginView der Authentifizierungs-App erbt

# users/tests/test_forms.py

#   --- other code

class LoginFormTest(TestCase):
  def setUp(self):
    self.user = User.objects.create_user(
      full_name= 'Tester User',
      email= 'tester@gmail.com',
      bio= 'new bio for tester',
      password= 'password12345'
    )

  def test_valid_credentials(self):
    """
    With valid credentials, the form should be valid
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'password12345',
      'remember_me': False
    }

    form = LoginForm(data = credentials)
    self.assertTrue(form.is_valid())

  def test_wrong_credentials(self):
    """
    With wrong credentials, the form should raise Invalid email or password error
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'wrongpassword',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertIn('Invalid email or password', str(form.errors['__all__']))

  def test_credentials_with_empty_email(self):
    """
    Should raise an error when the email field is empty
    """
    credentials = {
      'email': '',
      'password': 'password12345',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['email']))

  def test_credentials_with_empty_password(self):
    """
    Should raise error when the password field is empty
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': '',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['password']))

Fügen Sie am Ende der Datei „users/tests/test_views.py“ diese Testfälle hinzu

# users/forms.py

# -- other code
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm # new line
from django.contrib.auth import get_user_model, authenticate # new line


# --- other code

class LoginForm(AuthenticationForm):
  email = forms.EmailField(
    required=True,
    widget=forms.EmailInput(attrs={'placeholder': 'Email','class': 'form-control',})
  )
  password = forms.CharField(
    required=True,
    widget=forms.PasswordInput(attrs={
                                'placeholder': 'Password',
                                'class': 'form-control',
                                'data-toggle': 'password',
                                'id': 'password',
                                'name': 'password',
                                })
  )
  remember_me = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(LoginForm, self).__init__(*args, **kwargs)
    # Remove username field

    if 'username' in self.fields:
      del self.fields['username']

  def clean(self):
    email = self.cleaned_data.get('email')
    password = self.cleaned_data.get('password')

    # Authenticate using email and password
    if email and password:
      self.user_cache = authenticate(self.request, email=email, password=password)
      if self.user_cache is None:
        raise forms.ValidationError("Invalid email or password")
      else:
        self.confirm_login_allowed(self.user_cache)
    return self.cleaned_data

  class Meta:
    model = User
    fields = ('email', 'password', 'remember_me')

Wir müssen sicherstellen, dass diese Tests zu diesem Zeitpunkt fehlschlagen.

2.2 Erstellen Sie eine Anmeldeansicht

Fügen Sie in der Datei „users/views.py“ am Ende der Datei den folgenden Code hinzu:

(.venv)$ python3 manage.py test users.tests.test_forms
Found 9 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.........
----------------------------------------------------------------------
Ran 9 tests in 3.334s
OK
Destroying test database for alias 'default'...

Im obigen Code erreichen wir Folgendes:

  • Legen Sie das form_class-Attribut fest: Wir geben unser benutzerdefiniertes LoginForm als form_class-Attribut an, da wir nicht mehr das Standard-AuthenticationForm verwenden.
  • Überschreiben Sie die form_valid-Methode: Wir überschreiben die form_valid-Methode, die aufgerufen wird, wenn gültige Formulardaten gepostet wurden. Dadurch können wir benutzerdefiniertes Verhalten implementieren, nachdem sich der Benutzer erfolgreich angemeldet hat.
  • Sitzungsablauf behandeln: Wenn der Benutzer das Kästchen „member_me“ nicht aktiviert, läuft die Sitzung automatisch ab, wenn der Browser geschlossen wird. Wenn jedoch das Kästchen „remember_me“ aktiviert ist, dauert die Sitzung für die in „settings.py“ definierte Dauer. Die Standardsitzungsdauer beträgt zwei Wochen, wir können dies jedoch mithilfe der Variablen SESSION_COOKIE_AGE in Settings.py ändern. Um beispielsweise das Cookie-Alter auf 7 Tage festzulegen, können wir die folgende Zeile zu unseren Einstellungen hinzufügen:
# -- other code 
from .forms import CustomUserCreationForm, LoginForm
from django.contrib.auth import get_user_model, views
# -- other code

class CustomLoginView(views.LoginForm):


Um Ihre benutzerdefinierte Anmeldefunktion zu verbinden und Benutzern den Zugriff auf die Anmeldeseite zu ermöglichen, definieren wir URL-Muster in der Datei „users/urls.py“. Diese Datei ordnet bestimmte URLs (in diesem Fall /log_in/) den entsprechenden Ansichten (CustomLoginView) zu. Darüber hinaus fügen wir einen Pfad für die Abmeldefunktion mithilfe von Djangos integriertem LogoutView hinzu.

# django_project/settings.py
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",  # <-- Auth app
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

Alles scheint in Ordnung zu sein, aber wir sollten angeben, wohin Benutzer nach erfolgreicher Anmeldung und Abmeldung weitergeleitet werden sollen. Dazu verwenden wir die Einstellungen LOGIN_REDIRECT_URL und LOGOUT_REDIRECT_URL. Fügen Sie am Ende Ihrer blog_app/settings.py-Datei die folgenden Zeilen hinzu, um Benutzer zur Startseite umzuleiten:

# users/forms.py
from django.contrib.auth import AuthenticationForm

class LoginForm(AuthenticationForm):


Da wir nun die Anmelde-URL haben, aktualisieren wir unsere SignUpView in der Datei „users/views.py“, um bei erfolgreicher Anmeldung zur Anmeldeseite umzuleiten.

# users/tests/test_forms.py

#   --- other code

class LoginFormTest(TestCase):
  def setUp(self):
    self.user = User.objects.create_user(
      full_name= 'Tester User',
      email= 'tester@gmail.com',
      bio= 'new bio for tester',
      password= 'password12345'
    )

  def test_valid_credentials(self):
    """
    With valid credentials, the form should be valid
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'password12345',
      'remember_me': False
    }

    form = LoginForm(data = credentials)
    self.assertTrue(form.is_valid())

  def test_wrong_credentials(self):
    """
    With wrong credentials, the form should raise Invalid email or password error
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'wrongpassword',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertIn('Invalid email or password', str(form.errors['__all__']))

  def test_credentials_with_empty_email(self):
    """
    Should raise an error when the email field is empty
    """
    credentials = {
      'email': '',
      'password': 'password12345',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['email']))

  def test_credentials_with_empty_password(self):
    """
    Should raise error when the password field is empty
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': '',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['password']))

Wir werden auch unsere SignUpTexts, insbesondere test_signup_correct_data(self), aktualisieren, um das neue Verhalten widerzuspiegeln und sicherzustellen, dass unsere Änderungen ordnungsgemäß getestet werden.

# users/forms.py

# -- other code
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm # new line
from django.contrib.auth import get_user_model, authenticate # new line


# --- other code

class LoginForm(AuthenticationForm):
  email = forms.EmailField(
    required=True,
    widget=forms.EmailInput(attrs={'placeholder': 'Email','class': 'form-control',})
  )
  password = forms.CharField(
    required=True,
    widget=forms.PasswordInput(attrs={
                                'placeholder': 'Password',
                                'class': 'form-control',
                                'data-toggle': 'password',
                                'id': 'password',
                                'name': 'password',
                                })
  )
  remember_me = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(LoginForm, self).__init__(*args, **kwargs)
    # Remove username field

    if 'username' in self.fields:
      del self.fields['username']

  def clean(self):
    email = self.cleaned_data.get('email')
    password = self.cleaned_data.get('password')

    # Authenticate using email and password
    if email and password:
      self.user_cache = authenticate(self.request, email=email, password=password)
      if self.user_cache is None:
        raise forms.ValidationError("Invalid email or password")
      else:
        self.confirm_login_allowed(self.user_cache)
    return self.cleaned_data

  class Meta:
    model = User
    fields = ('email', 'password', 'remember_me')

2.3 Erstellen Sie eine Vorlage für die Anmeldung

Erstellen Sie dann mit Ihrem Texteditor eine Datei „users/templates/registration/login.html“ und fügen Sie den folgenden Code ein:

(.venv)$ python3 manage.py test users.tests.test_forms
Found 9 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.........
----------------------------------------------------------------------
Ran 9 tests in 3.334s
OK
Destroying test database for alias 'default'...

Wir werden die Funktion „Passwort vergessen“ später in dieser Serie hinzufügen, aber jetzt ist es nur noch ein toter Link.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
Lassen Sie uns nun unsere Vorlage „layout.html“ aktualisieren, um die Anmelde-, Anmelde- und Abmeldelinks einzuschließen.

# -- other code 
from .forms import CustomUserCreationForm, LoginForm
from django.contrib.auth import get_user_model, views
# -- other code

class CustomLoginView(views.LoginForm):


In unserer Vorlage prüfen wir, ob der Benutzer authentifiziert ist. Wenn der Benutzer angemeldet ist, zeigen wir den Abmeldelink und den vollständigen Namen des Benutzers an. Andernfalls zeigen wir die Anmelde- und Registrierungslinks an.
Lassen Sie uns nun alle Tests durchführen

# users/tests/test_views.py

# -- other code

class LoginTests(TestCase):
  def setUp(self):
    User.objects.create_user(
      full_name= 'Tester User',
      email= 'tester@gmail.com',
      bio= 'new bio for tester',
      password= 'password12345'
    )
    self.valid_credentials = {
      'email': 'tester@gmail.com',
      'password': 'password12345',
      'remember_me': False
    }

  def test_login_url(self):
    """User can navigate to the login page"""
    response = self.client.get(reverse('users:login'))
    self.assertEqual(response.status_code, 200)

  def test_login_template(self):
    """Login page render the correct template"""
    response = self.client.get(reverse('users:login'))
    self.assertTemplateUsed(response, template_name='registration/login.html')
    self.assertContains(response, '<a class="btn btn-outline-dark text-white" href="/users/sign_up/">Sign Up</a>')

  def test_login_with_valid_credentials(self):
    """User should be log in when enter valid credentials"""
    response = self.client.post(reverse('users:login'), self.valid_credentials, follow=True)
    self.assertEqual(response.status_code, 200)
    self.assertRedirects(response, reverse('home'))
    self.assertTrue(response.context['user'].is_authenticated)
    self.assertContains(response, '<button type="submit" class="btn btn-danger"><i class="bi bi-door-open-fill"></i> Log out</button>')

  def test_login_with_wrong_credentials(self):
    """Get error message when enter wrong credentials"""
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'wrongpassword',
      'remember_me': False
    }

    response = self.client.post(reverse('users:login'), credentials, follow=True)
    self.assertEqual(response.status_code, 200)
    self.assertContains(response, 'Invalid email or password')
    self.assertFalse(response.context['user'].is_authenticated)

3. Testen Sie, ob in unserem Browser alles wie gewünscht funktioniert

Da wir nun die An- und Abmeldefunktion konfiguriert haben, ist es an der Zeit, alles in unserem Webbrowser zu testen. Starten wir den Entwicklungsserver

# django_project/settings.py
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",  # <-- Auth app
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

Navigieren Sie zur Registrierungsseite und geben Sie gültige Anmeldeinformationen ein. Nach erfolgreicher Registrierung sollten Sie zur Anmeldeseite weitergeleitet werden. Geben Sie die Benutzerinformationen in das Anmeldeformular ein und klicken Sie nach der Anmeldung auf die Schaltfläche „Abmelden“. Anschließend sollten Sie abgemeldet und zur Startseite weitergeleitet werden. Stellen Sie abschließend sicher, dass Sie nicht mehr angemeldet sind und dass die Registrierungs- und Anmeldelinks erneut angezeigt werden.
Alles funktioniert einwandfrei, aber mir ist aufgefallen, dass ein Benutzer, wenn er angemeldet ist und die Registrierungsseite unter http://127.0.0.1:8000/users/sign_up/ besucht, immer noch Zugriff auf das Registrierungsformular hat. Sobald ein Benutzer angemeldet ist, sollte er im Idealfall nicht mehr auf die Anmeldeseite zugreifen können.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
Dieses Verhalten kann zu mehreren Sicherheitslücken in unserem Projekt führen. Um dieses Problem zu beheben, müssen wir SignUpView aktualisieren, um alle angemeldeten Benutzer auf die Startseite umzuleiten.
Aber zuerst aktualisieren wir unseren LoginTest, um einen neuen Test hinzuzufügen, der das Szenario abdeckt. Fügen Sie also in der Datei „users/tests/test_views.py“ diesen Code hinzu.

# users/forms.py
from django.contrib.auth import AuthenticationForm

class LoginForm(AuthenticationForm):


Jetzt können wir unsere SignUpView aktualisieren

# users/tests/test_forms.py

#   --- other code

class LoginFormTest(TestCase):
  def setUp(self):
    self.user = User.objects.create_user(
      full_name= 'Tester User',
      email= 'tester@gmail.com',
      bio= 'new bio for tester',
      password= 'password12345'
    )

  def test_valid_credentials(self):
    """
    With valid credentials, the form should be valid
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'password12345',
      'remember_me': False
    }

    form = LoginForm(data = credentials)
    self.assertTrue(form.is_valid())

  def test_wrong_credentials(self):
    """
    With wrong credentials, the form should raise Invalid email or password error
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': 'wrongpassword',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertIn('Invalid email or password', str(form.errors['__all__']))

  def test_credentials_with_empty_email(self):
    """
    Should raise an error when the email field is empty
    """
    credentials = {
      'email': '',
      'password': 'password12345',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['email']))

  def test_credentials_with_empty_password(self):
    """
    Should raise error when the password field is empty
    """
    credentials = {
      'email': 'tester@gmail.com',
      'password': '',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['password']))

Im obigen Code überschreiben wir die Methode „dispatch()“ unseres SignUpView, um jeden Benutzer umzuleiten, der bereits angemeldet ist und versucht, auf die Registrierungsseite zuzugreifen. Diese Weiterleitung verwendet die in unserer Datei „settings.py“ festgelegte LOGIN_REDIRECT_URL, die in diesem Fall auf die Startseite verweist.
Okay! Lassen Sie uns noch einmal alle unsere Tests durchführen, um zu bestätigen, dass unsere Updates wie erwartet funktionieren

# users/forms.py

# -- other code
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm # new line
from django.contrib.auth import get_user_model, authenticate # new line


# --- other code

class LoginForm(AuthenticationForm):
  email = forms.EmailField(
    required=True,
    widget=forms.EmailInput(attrs={'placeholder': 'Email','class': 'form-control',})
  )
  password = forms.CharField(
    required=True,
    widget=forms.PasswordInput(attrs={
                                'placeholder': 'Password',
                                'class': 'form-control',
                                'data-toggle': 'password',
                                'id': 'password',
                                'name': 'password',
                                })
  )
  remember_me = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(LoginForm, self).__init__(*args, **kwargs)
    # Remove username field

    if 'username' in self.fields:
      del self.fields['username']

  def clean(self):
    email = self.cleaned_data.get('email')
    password = self.cleaned_data.get('password')

    # Authenticate using email and password
    if email and password:
      self.user_cache = authenticate(self.request, email=email, password=password)
      if self.user_cache is None:
        raise forms.ValidationError("Invalid email or password")
      else:
        self.confirm_login_allowed(self.user_cache)
    return self.cleaned_data

  class Meta:
    model = User
    fields = ('email', 'password', 'remember_me')

Ich weiß, dass es noch viel zu erreichen gibt, aber nehmen wir uns einen Moment Zeit, um zu würdigen, was wir bisher erreicht haben. Gemeinsam haben wir unsere Projektumgebung eingerichtet, eine PostgreSQL-Datenbank angebunden und ein sicheres Benutzerregistrierungs- und Anmeldesystem für unsere Django-Bloganwendung implementiert. Im nächsten Teil befassen wir uns mit der Erstellung einer Benutzerprofilseite, die es Benutzern ermöglicht, ihre Informationen zu bearbeiten und das Passwort zurückzusetzen! Seien Sie gespannt auf weitere spannende Entwicklungen, während wir unsere Reise zur Django-Blog-App fortsetzen!

Ihr Feedback ist uns immer wichtig. Bitte teilen Sie Ihre Gedanken, Fragen oder Vorschläge in den Kommentaren unten. Vergessen Sie nicht, zu liken, einen Kommentar zu hinterlassen und sich zu abonnieren, um über die neuesten Entwicklungen auf dem Laufenden zu bleiben!

Das obige ist der detaillierte Inhalt vonLeitfaden zum Erstellen einer vollständigen Blog-App mit Django unter Verwendung der TDD-Methodik und PostgreSQL (Teilweise sichere Benutzerauthentifizierung).. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn