Heim  >  Artikel  >  Backend-Entwicklung  >  Django-Kontoverwaltungs-App (Registrierung und Aktivierung).

Django-Kontoverwaltungs-App (Registrierung und Aktivierung).

Patricia Arquette
Patricia ArquetteOriginal
2024-11-04 21:57:02971Durchsuche

Was können Sie von diesem Artikel erwarten?

Wir haben im vorherigen Artikel die Grundstruktur des Projekts erstellt, dieser Artikel wird darauf aufbauen. es wird abdecken

  • Struktur der Kontodatenbank, einschließlich Benutzer und Bestätigungscode.
  • Modelle Serialisierer.
  • Kontoansichten für die Kontoregistrierung und -aktivierung. Der nächste Artikel sollte den Rest der Ansichten behandeln, z. B. Anmelden, Token aktualisieren, Passwort ändern, Passwort vergessen und Code erneut senden.

Ich werde versuchen, so viele Details wie möglich abzudecken, ohne Sie zu langweilen, erwarte aber dennoch, dass Sie mit einigen Aspekten von Python und Django vertraut sind.

Die endgültige Version des Quellcodes finden Sie auf https://github.com/saad4software/alive-diary-backend

Serienbestellung

Schauen Sie sich bei Interesse frühere Artikel an!

  1. KI-Projekt von Grund auf, die Idee, lebendiges Tagebuch
  2. Beweisen Sie, dass es mit Google AI Studio machbar ist
  3. Django API-Projekt-Setup
  4. Django-Kontoverwaltungs-App (1), Registrierung und Aktivierung (Sie sind hier?)

Einrichtung der Konten-App

Lassen Sie uns eine Serialisierungsdatei in der App erstellen

from rest_framework import serializers
from app_account.models import *

app_account/serializers.py

und die URL-Datei

from django.urls import path, include
from .views import *

urlpatterns = [

]

app_account/urls.py

Abschließend verbinden wir die App-URLs mit den Projekt-URLs, indem wir die Projekt-URL-Datei bearbeiten als

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/account/', include('app_account.urls')),

]

alive_diary/urls.py

Jetzt können wir jede Konto-URL mit dem Präfix „api/account/“ aufrufen

Die Modelle

Das Hauptmodell für die Konten-App ist natürlich das Benutzermodell

from django.db import models
from django.contrib.auth.models import AbstractUser
from datetime import timedelta, datetime

class User(AbstractUser):
    userTypes = (
        ('A', 'Admin'),
        ('C', 'Client'),
    )

    role = models.CharField(max_length=1, choices=userTypes, default="C")

    hobbies = models.CharField(max_length=255, null=True, blank=True)
    job = models.CharField(max_length=100, null=True, blank=True)
    bio = models.TextField(null=True, blank=True)

    country_code = models.CharField(max_length=10, null=True, blank=True)
    expiration_date = models.DateTimeField(default=datetime.now()+timedelta(days=30))

app_account/models.py

Normalerweise ist es besser, das Benutzermodell so einfach wie möglich zu halten und andere Details in ein Profilmodell mit einer Eins-zu-eins-Beziehung zum Benutzer zu verschieben, aber um die Dinge zu vereinfachen, füge ich die erforderlichen Benutzerinformationen hinzu Diesmal direkt zum Benutzermodell.

Wir erben vom AbstractUser-Modell, AbstractUser enthält mehrere Felder

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(...)
    first_name = models.CharField(...)
    last_name = models.CharField(...)
    email = models.EmailField(...)
    is_staff = models.BooleanField(...)
    is_active = models.BooleanField(...),
    date_joined = models.DateTimeField(...)

Die wichtigsten sind:

  • Der Benutzername wird für die Anmeldung verwendet.
  • is_active wird verwendet, um zu verhindern, dass sich nicht verifizierte Konten anmelden.
  • is_staff unterscheidet Administratoren (mit dem Wert true) von normalen Benutzern.

Wir haben außerdem mehrere Felder für diesen Projektbenutzer hinzugefügt:

  • Um Administrator- und Kundenkonten zu unterscheiden, können wir is_staff für dieses einfache Projekt verwenden, da wir nur zwei Rollen haben, ein größeres Projekt jedoch mehr als zwei Rollen haben kann, sodass dieses Feld für die Berechtigungsverwaltung unerlässlich ist.
  • Hobbys, Job, Biografie Wenn Sie mehr über den Benutzer wissen, kann dies zu einer besseren Reflexion beitragen. Daher fragen wir nach Hobbys, Job und wie der Benutzer sich selbst beschreibt.
  • Ländercode für Statistiken
  • expiration_date für abonnementbasiertes Ablaufdatum.

Wir benötigen außerdem ein Bestätigungscode-Modell, um Bestätigungscodes für die Kontoaktivierung, das Vergessen von Passwörtern und das erneute Senden von Codes aufzubewahren und zu verfolgen.

from rest_framework import serializers
from app_account.models import *

app_account/models.py

Es verbindet sich mit dem Benutzermodell und generiert einen Zufallswert einer 6-stelligen Codenummer. es hat auch eine Ablaufzeit von 24 Stunden. Für den Fall, dass der Benutzer mehrere E-Mail-Adressen validieren möchte, haben wir auch E-Mail-Adressen archiviert. Dies ist selten und kann für diese App entfernt werden. Kommen wir als nächstes zu den Serialisierern.

Die Registrierungs-API

Beginnen wir mit dem Serialisierer

from django.urls import path, include
from .views import *

urlpatterns = [

]

app_account/serializers.py

Wir verwenden ModelSerializer vom Django-Rest-Framework. Wir haben das Benutzermodell get_user_model() in der Klasse Meta und eine Liste serialisierter Felder ausgewählt.

Wir haben dem Modellserialisierer zwei zusätzliche Felder hinzugefügt: Passwort1 und Passwort2. Um zu überprüfen, ob sie denselben Wert haben, haben wir die Methode „validate“ überschrieben. Und um die Verwendung einer gültigen E-Mail-Adresse als Benutzernamen zu erzwingen, haben wir einen Feldvalidator für das Feld „Benutzername“ hinzugefügt.
Die Funktion is_valid_email sollte ungefähr so ​​aussehen

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/account/', include('app_account.urls')),

]

common/utils.py

Ich persönlich mag reguläre Ausdrücke nicht, ich verstehe sie nie, aber sie scheinen die beste Möglichkeit zu sein, E-Mails zu validieren. Wenn Sie einen besseren Weg haben, teilen Sie ihn uns bitte mit.

Da unsere neuen Felder „Passwort1“ und „Passwort2“ nicht zum ursprünglichen Benutzermodell gehören, haben wir sie aus dem Datenwörterbuch entfernt und das Passwortfeld hinzugefügt, um Serialisierungsdaten direkt zum Erstellen eines neuen Benutzers zu verwenden.

Das Best-Practice-Dilemma des Serializers

  • Sollten Serialisierer Datenbankabfragen verwenden und Datenbanken bearbeiten?
  • Oder sollten sie nur eine grundlegende Feldtypvalidierung durchführen (Zeichenfolge, Ganzzahl, ...)?

Es gibt eigentlich keine eindeutige Antwort, zum Beispiel scheinen Serialisierer des Django Rest-Framework-Modells Abfragen nach eindeutigen Feldern durchzuführen, wie der Serializer-Fehler, den wir bekamen, als wir versuchten, eine Verwendung mit demselben Namen zu erstellen, er wurde vom Serializer generiert, nicht die Aussicht.
Die Methoden „Create“, „Save“, „Update“ schreiben Werte in die Datenbank.
Der Zugriff auf die Datenbank nur in Ansichten scheint jedoch eher mit Bedenkenstrennung und Flexibilität in Einklang zu stehen.

Was ist Ihrer Meinung nach besser?

Ich habe viel über die Trennung von Dingen gelesen, sogar über die Trennung von Datenbankabfragen und Datenbankaktualisierungsmethoden. Also lasst uns das versuchen. Das Erstellen der AccountActivateView in der Datei „views.py“ sollte so aussehen.

In unserem Fall können wir die Erstellungsmethode für RegisterSerializer überschreiben, um sofort einen neuen Benutzer und Validierungscode zu erstellen und sogar den Bestätigungscode vom Serializer zu senden.

Aber stattdessen behalte ich die modellbezogenen Vorgänge in der Ansichtsdatei

Gehen wir zur Registrierungsansicht

from rest_framework import serializers
from app_account.models import *

app_account/views.py

Wir verwenden CreatAPIView aus dem Rest-Framework, es akzeptiert POST-Anfragen mit dem Schema von serializer_class, der BrowsableAPIRenderer erstellt eine Webschnittstelle für diese API und der JSONRenderer ist für die Erstellung der JSON-Antwort verantwortlich.

Das Überschreiben der perform_create-Methode ermöglicht uns die Steuerung des Benutzererstellungsmechanismus. Wir erstellen den Benutzer-Instant, stellen sicher, dass das Feld is_active auf False gesetzt ist, erstellen dann den Verifizierungscode-Instant, der mit dem neuen Benutzermodell verbunden ist, und senden ihn schließlich eine E-Mail mit dem Bestätigungscode an den Benutzer.

Für das Versenden der E-Mail ist die korrekte Konfiguration der E-Mail-Felder in der Einstellungsdatei erforderlich. Bitte lassen Sie mich wissen, wenn Sie in diesem speziellen Punkt Probleme haben, um einen separaten Artikel dafür zu erstellen

Zuletzt fügen wir noch die API-URL hinzu

from django.urls import path, include
from .views import *

urlpatterns = [

]

app_account/urls.py

Schön, probieren wir es mal aus

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/account/', include('app_account.urls')),

]

Wenn wir http://localhost:8555/api/account/register öffnen, sollten wir so etwas sehen können (es liegt am BrowsableAPIRenderer)

Django accounts management app ( registration and activation

Die erforderlichen Felder sind Benutzername, Passwort1 und Passwort2. Wir gehen davon aus, dass die E-Mail-Adresse als Benutzername verwendet wird.
Es sieht in Ordnung aus, es hat ein Benutzermodell mit einem damit verbundenen Bestätigungscodemodell erstellt (habe SqlBrowser zum Öffnen der SQLite-DB-Datei verwendet). Aber die Standardantwort sieht mit dem Status 201 so aus.

from django.db import models
from django.contrib.auth.models import AbstractUser
from datetime import timedelta, datetime

class User(AbstractUser):
    userTypes = (
        ('A', 'Admin'),
        ('C', 'Client'),
    )

    role = models.CharField(max_length=1, choices=userTypes, default="C")

    hobbies = models.CharField(max_length=255, null=True, blank=True)
    job = models.CharField(max_length=100, null=True, blank=True)
    bio = models.TextField(null=True, blank=True)

    country_code = models.CharField(max_length=10, null=True, blank=True)
    expiration_date = models.DateTimeField(default=datetime.now()+timedelta(days=30))

Ich bevorzuge, dass alle Antworten dieses Schema haben

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(...)
    first_name = models.CharField(...)
    last_name = models.CharField(...)
    email = models.EmailField(...)
    is_staff = models.BooleanField(...)
    is_active = models.BooleanField(...),
    date_joined = models.DateTimeField(...)

  • Der Status sollte entweder „Erfolg“ oder „Fehler“ sein
  • Code ist der Antwortstatuscode
  • Daten sind die tatsächlichen Antwortdaten
  • Die Nachricht sollte einen Fehlertext oder eine andere Nachricht enthalten

Aber wie geht das?
Der beste Weg ist die Implementierung einer benutzerdefinierten JSON-Renderer-Funktion. Lass es uns tun

import random

class VerificationCode(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    code = models.CharField(max_length=6, default=random.randint(111111, 999999))
    email = models.EmailField()
    expiration_date = models.DateTimeField(default=datetime.now()+timedelta(days=1))

    def __str__(self):
        return self.user.username

common/utils.py

Wir haben von JSONRenderer geerbt und die Render-Methode überschrieben. Serialisierungsfehler.

  • begann mit dem Lesen des Antwortstatuscodes und dem Einfügen in das Codefeld
  • und wir haben die tatsächlichen Antwortdaten in das Datenfeld in unserem Antwortschema verschoben
  • Um Fehler von erfolgreichen Antworten zu unterscheiden, überprüfen wir den Statuscode. Wenn der Statuscode in der 200er-Familie liegt, handelt es sich um eine erfolgreiche Antwort
  • Wenn nicht, handelt es sich um einen Fehler. Daher ändern wir den Status in „Fehler“ und extrahieren die Fehlermeldung aus dem Feld mit den Antwortdetails (falls verfügbar).
  • Die Validierungsfehler des Serializers haben keine Detailfelder, es handelt sich um ein Wörterbuch, das für jeden Feldnamen (Schlüssel) eine Fehlermeldung (Wert) angibt. Deshalb haben wir eine kleine Funktion dict2string erstellt, um sie in eine einfache Zeichenfolge umzuwandeln. Ich denke, es kann noch weiter verbessert werden. Können Sie dabei helfen?

Das war's mit dem Antwortschema. Probieren wir es jetzt aus!
Fügen Sie in „views.py“ unseren benutzerdefinierten Renderer zur Registeransichtsklasse hinzu

from rest_framework import serializers
from app_account.models import *

app_account/views.py

Wenn Sie den Server ausführen und http://localhost:8555/api/account/register/ öffnen, wird der Unterschied direkt angezeigt

Django accounts management app ( registration and activation

Wir können unser Schema in der Fehlermeldung sehen? Cool, versuchen wir, einen neuen Benutzer zu registrieren. Ich nenne ihn „test5@gmail.com“

Django accounts management app ( registration and activation

Sieht großartig aus. Jetzt testen wir den Validierungsfehler des Serialisierers. Wir werden versuchen, denselben Benutzer erneut zu registrieren

Django accounts management app ( registration and activation

Wunderbar, das ist eine Validierungsfehlerantwort, sie wurde als field:message
serialisiert Was kommt nach der Registrierung? es ist eine Bestätigung
registrieren -> E-Mail bestätigen -> Anmelden -> was auch immer

Die Aktivierungs-API

Wir möchten überprüfen, ob der Benutzer den Aktivierungscode erhalten hat, den wir bei der Registrierung gesendet haben oder nicht. Wenn der Benutzer den richtigen Code sendet, aktivieren wir sein Konto. Wenn nicht, werden wir ihn bitten, erneut nachzuschauen, oder vielleicht Senden Sie den Code erneut (eine andere API für später)
Beginnen wir ähnlich wie beim Erstellungsprozess der Registrierungs-API mit dem Serialisierer

from django.urls import path, include
from .views import *

urlpatterns = [

]

Dies hängt nicht mit einem bestimmten Datenbankmodell zusammen, daher erben wir vom generischen Serializer. Beachten Sie, dass Serializer Formularen ähneln, daher legen wir die Felder und ihre Validierungsregeln fest.
Wir verwenden zwei Zeichenfolgenfelder (CharField), beide sind erforderlich, Benutzername, der die E-Mail-Adresse des Benutzers ist, und Code.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/account/', include('app_account.urls')),

]

app_account/views.py

Da wir eine benutzerdefinierte API-Ansicht verwenden, die wir von APIView erben, bietet sie 5 Funktionen (Abrufen, Posten, Einfügen, Löschen und Patchen). Wir deserialisieren Anforderungsdaten von POST-Anfragen und validieren ihren Typ. Anschließend führen wir eine Abfrage durch, um herauszufinden, ob die bereitgestellten Daten vorhanden sind oder nicht. Wenn sie vorhanden sind, aktivieren wir den Benutzer und entfernen das Codeobjekt aus seiner Tabelle. Wenn nicht, senden wir eine Fehlermeldung, dass es sich um einen „invalid_code“ handelt. Schließlich sollte die URL-Datei aktualisiert werden, um die URL dieser Ansicht einzuschließen

from rest_framework import serializers
from app_account.models import *

app_account/urls.py

Jetzt können wir die URL http://localhost:8555/api/account/activate/ öffnen. Wir verwenden eine benutzerdefinierte API-Ansicht, sodass das erforderliche Feld nicht angezeigt wird

Django accounts management app ( registration and activation

Wir können den Code aus der Datenbank abrufen (zu Testzwecken). Die Anfrage sollte wie folgt aussehen:

from django.urls import path, include
from .views import *

urlpatterns = [

]

Wenn alles erfolgreich verlaufen ist, sollte die Antwort wie folgt aussehen:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/account/', include('app_account.urls')),

]

Das ist es
Bringen wir es zum Abschluss! Ich weiß, dass wir uns noch nicht eingeloggt haben, aber es ist tatsächlich ein sehr langer Artikel geworden, lasst uns im nächsten Artikel fortfahren

Bleiben Sie dran ?

Das obige ist der detaillierte Inhalt vonDjango-Kontoverwaltungs-App (Registrierung und Aktivierung).. 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