8 marca 2023
logowanie kont użytkowników poprzez adres e-mail
8 marca 2023
Jednym z popularnych rozwiązań tych problemów jest zastosowanie adresu e-mail jako unikalnego identyfikatora dla logowania. Adresy e-mail są nie tylko unikalne dla każdej osoby, ale także łatwiejsze do zapamiętania. Ponadto, większość użytkowników jest już przyzwyczajona do używania adresów e-mail jako identyfikatorów w różnych usługach internetowych. Wprowadzenie logowania opartego na adresie e-mail może przyczynić się do zwiększenia wygody i satysfakcji użytkowników z korzystania z aplikacji.
W tym artykule przedstawimy, jak zaimplementować logowanie za pomocą adresu e-mail w aplikacji Django, korzystając z funkcji "AbstractUser" oraz funkcji widoków (function based views). Przejdziemy przez proces tworzenia modelu użytkownika, formularzy, widoków, a także szablonów HTML z wykorzystaniem Bootstrap.
Tworzenie modelu użytkownika z AbstractUser
Aby zaimplementować logowanie za pomocą adresu e-mail, musimy najpierw utworzyć niestandardowy model użytkownika, który będzie rozszerzać wbudowany model AbstractUser
. AbstractUser zawiera wszystkie podstawowe pola i metody niezbędne do zarządzania kontami użytkowników. Będziemy modyfikować ten model, aby używać adresu e-mail jako głównego identyfikatora.
Oto jak zbudować niestandardowy model użytkownika:
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
username = None
email = models.EmailField(unique=True, blank=False, error_messages={'unique': "A user with that email already exists!"})
account_type = models.CharField(choices=ACCOUNT_TYPE, max_length=10)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
W powyższym kodzie:
1. Importujemy AbstractUser
z django.contrib.auth.models oraz models z django.db.
2. Tworzymy nową klasę CustomUser
, która dziedziczy po AbstractUser
.
3. Nadpisujemy pole email w klasie CustomUser
, dodając atrybut unique=True
. Oznacza to, że każdy adres e-mail musi być unikalny dla każdego użytkownika.
4. Ustawiamy USERNAME_FIELD
na 'email', co oznacza, że adres e-mail będzie używany jako identyfikator podczas logowania.
5. Nadpisujemy metodę '__str__'
, aby zwracała adres e-mail użytkownika
Teraz musimy zaktualizować ustawienia aplikacji, aby używać naszego niestandardowego modelu użytkownika:
# settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'
W powyższym kodzie zastępujemy 'accounts' nazwą aplikacji, w której znajduje się model CustomUser
. AUTH_USER_MODEL informuje Django, że chcemy korzystać z naszego niestandardowego modelu użytkownika zamiast domyślnego.
Do poprawnego działania modelu CustomUser
niezbędny bedzie CustomUserManager
, który został już uwzględniony przy modelu użytkownika. Oto kod odpowiedzialny za tą funkcjonalność:
# accounts/managers.py
from django.contrib.auth.base_user import BaseUserManager
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(email, password, **extra_fields)
Tworzenie formularzy dla rejestracji i logowania
Następnie musimy utworzyć formularze, które pozwolą użytkownikom rejestrować się i logować się za pomocą swojego adresu e-mail. W tym celu utworzymy dwa formularze: UserRegisterForm
i EmailLoginForm
. Tworzymy nowy plik o nazwie forms.py w folderze naszej aplikacji i dodajemy następujący kod:
# accounts/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import get_user_model
User = get_user_model()
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class EmailLoginForm(AuthenticationForm):
username = None
email = forms.EmailField()
class Meta:
model = User
fields = ['email', 'password']
W powyższym kodzie:
1. Importujemy forms z django, UserCreationForm
i AuthenticationForm
z django.contrib.auth.forms oraz get_user_model
z django.contrib.auth.
2. Pobieramy niestandardowy model użytkownika za pomocą funkcji get_user_model
i przypisujemy go do zmiennej User
.
3. Tworzymy klasę UserRegisterForm
, która dziedziczy po UserCreationForm
. Dodajemy pole email jako wymagane pole do formularza.
4. W klasie Meta formularza UserRegisterForm
ustawiamy model na nasz niestandardowy model użytkownika oraz definiujemy listę pól, które mają być uwzględnione w formularzu.
5. Tworzymy klasę EmailLoginForm
, która dziedziczy po AuthenticationForm
. Ustawiamy username na None, ponieważ będziemy używać adresu e-mail zamiast nazwy użytkownika. Dodajemy pole email jako wymagane pole do formularza.
6. W klasie Metaformularza EmailLoginForm
ustawiamy model na nasz niestandardowy model użytkownika oraz definiujemy listę pól, które mają być uwzględnione w formularzu.
7. Teraz mamy gotowe formularze, które pozwolą użytkownikom rejestrować się i logować się za pomocą swojego adresu e-mail.
Implementacja widoków (views) dla rejestracji i logowania
Teraz, gdy mamy gotowe formularze, możemy utworzyć widoki, które obsługują proces rejestracji i logowania. W tym celu dodajemy następujący kod do pliku views.py
w folderze naszej aplikacji:
# accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate
from .forms import UserRegisterForm, EmailLoginForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
user = form.save()
messages.success(request, 'Konto zostało utworzone! Możesz się teraz zalogować.')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'register.html', {'form': form})
def user_login(request):
if request.method == 'POST':
form = EmailLoginForm(request, request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
form = EmailLoginForm(request)
return render(request, 'login.html', {'form': form})
def home(request):
return render(request, 'home.html')
W powyższym kodzie:
1.Importujemy funkcje render
, redirect
z modułu django.shortcuts, funkcje login
i authenticate
z django.contrib.auth, formularze UserRegisterForm
i EmailLoginForm
z pliku forms.py
2. Tworzymy funkcję widoku register
, która obsługuje żądania POST i GET. Jeśli żądanie jest POST, tworzymy instancję formularza UserRegisterForm
z danymi przesłanymi przez użytkownika. Jeśli formularz jest prawidłowy, zapisujemy nowego użytkownika i wyświetlamy wiadomość o powodzeniu, a następnie przekierowujemy użytkownika do strony logowania. Jeśli żądanie jest GET, wyświetlamy pusty formularz rejestracji.
3. Tworzymy funkcję widoku user_login
, która obsługuje żądania POST i GET. Jeśli żądanie jest POST, tworzymy instancję formularza EmailLoginForm
z danymi przesłanymi przez użytkownika. Jeśli formularz jest prawidłowy, próbujemy uwierzytelnić użytkownika za pomocą funkcji authenticate i przekazujemy adres e-mail oraz hasło. Jeśli uwierzytelnienie się powiedzie, logujemy użytkownika, wyświetlamy powitalną wiadomość i przekierowujemy go na stronę główną. Jeśli żądanie jest GET, wyświetlamy pusty formularz logowania.
4. Tworzymy funkcję widoku home
do której przekierowani zostaną użytkownicy po poprawnym zalogowaniu się do aplikacji. W realnym rozwiązaniu można ją zdecydowanie bardziej rozbudować, jednak w tym przykładzie posłuży ona jedynie do potwierdzenia czy logowanie odbyło się pomyślnie.
Mając gotowe widoki, możemy przejść do tworzenia szablonów HTML.
Tworzenie szablonów HTML z wykorzystaniem Bootstrap
W tym podpunkcie zajmiemy się tworzeniem szablonów HTML dla naszych widoków rejestracji i logowania, używając Bootstrap, aby szybko i łatwo stworzyć atrakcyjne i responsywne formularze. Najpierw utworzymy katalog templates w folderze naszej aplikacji, a następnie w nim dwa pliki: register.html
i login.html
.
Zacznijmy od szablonu register.html
:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rejestracja</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Registration</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">register</button>
</form>
</div>
</body>
</html>
W powyższym szablonie:
1.Ładujemy tag static
na początku pliku, aby móc korzystać ze statycznych plików (nie jest to jednak używane w tym konkretnym szablonie).
2. Dodajemy podstawową strukturę HTML5 z meta tagami, tagiem tytułu i linkiem do arkusza stylów Bootstrap.
3. Tworzymy kontener, w którym umieszczamy formularz rejestracji. Formularz korzysta z metody POST, a tag csrf_token
zapewnia zabezpieczenie przed atakami CSRF.
4. Wyświetlamy formularz za pomocą {{ form.as_p }}
, co wygeneruje formularz z polami zawartymi wewnątrz tagów <p>
.
5. Dodajemy przycisk "Zarejestruj się" z klasą Bootstrap "btn btn-primary".
Teraz przejdźmy do szablonu login.html
:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Log in</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2>Log in</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Log in</button>
</form>
</div>
</body>
</html>
Szablon login.html
jest bardzo podobny do register.html
. Różnice to zmiana tytułu na "Logowanie" oraz przycisku na "Zaloguj się".
Na końcu szablon home.html
, po udanym zalogowaniu użytkownicy zostaną do niego przekierowani.
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rejestracja</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Successful login!</h1>
<h2>you are now logged in based on your email address</h2>
</div>
</body>
</html>
Mając gotowe szablony, możemy teraz dodać odpowiednie adresy URL, aby zintegrować nasze widoki z resztą aplikacji. W tym celu edytujemy plik urls.py
w folderze naszej aplikacji, dodając następujące ścieżki:
from django.urls import path
from . import views
urlpatterns = [
path('register/', views.register, name='register'),
path('login/', views.user_login, name='login'),
path('home/', views.home, name='home'),
]
W powyższym kodzie:
1. Importujemy path z modułu django.urls oraz views
z naszej aplikacji.
2. Dodajemy ścieżki dla widoków register
, user_login
oraz home
, przypisując im odpowiednie nazwy.
W ten sposób zintegrowaliśmy nasze widoki rejestracji i logowania z aplikacją Django. Teraz użytkownicy mogą rejestrować się i logować się za pomocą swojego adresu e-mail.
Przykład rejestracji i logowania użytkownika
W tej części posta pokażemy, jak wygląda proces rejestracji i logowania użytkownika w naszej aplikacji Django. Przypomnijmy, że zaimplementowaliśmy funkcje rejestracji i logowania, które używają adresu e-mail zamiast nazwy użytkownika.
Aby przetestować naszą implementację, wykonaj poniższe kroki:
Przygotować oraz wykonać migrację bazy danych.
python manage.py makemigrations
python manage.py migrate
1. Uruchom serwer deweloperski Django, wpisując w konsoli:
python manage.py runserver
2. Otwórz przeglądarkę i przejdź do adresu URL rejestracji, na przykład: http://127.0.0.1:8000/register/
. Zobaczysz formularz rejestracji, który utworzyliśmy wcześniej.
3. Wypełnij formularz, podając adres e-mail, hasło i powtórzone hasło. Upewnij się, że podane hasło spełnia wymagania dotyczące bezpieczeństwa, takie jak długość i unikalne znaki.
4. Kliknij przycisk "Zarejestruj się". Jeśli formularz został wypełniony poprawnie, zostaniesz przekierowany na stronę logowania z informacją o pomyślnym utworzeniu konta.
5. Przejdź do adresu URL logowania, na przykład: http://127.0.0.1:8000/login/
. Zobaczysz formularz logowania, który również utworzyliśmy wcześniej.
6. Wprowadź adres e-mail i hasło, których użyłeś podczas rejestracji, a następnie kliknij przycisk "Zaloguj się".
7. Jeśli dane logowania są poprawne, zostaniesz przekierowany na stronę główną aplikacji (lub inną stronę, którą zdefiniowaliśmy po zalogowaniu).