Зачем нужна пользовательская модель пользователя?
Django по умолчанию предоставляет встроенную модель пользователя, которая подходит для большинства стандартных случаев. Однако, когда проект требует расширенной функциональности, специфичных полей (например, phone_number, company_id для рекламной платформы) или иной логики аутентификации (например, использование email вместо username), создание пользовательской модели становится необходимостью.
Преимущества:
- Кастомизация: Добавление любых необходимых полей и методов.
- Контроль: Полный контроль над процессом аутентификации и авторизации.
- Расширяемость: Легкая интеграция с другими частями приложения.
Обзор архитектуры Django REST Framework и её компонентов
Django REST Framework (DRF) – мощный и гибкий инструмент для создания RESTful API. Ключевые компоненты DRF, которые будут использоваться:
- Serializers: Преобразуют данные модели в JSON и обратно, а также выполняют валидацию данных.
- Views: Обрабатывают HTTP запросы и возвращают ответы.
- Routers: Автоматически создают URL patterns для views.
- Permissions: Определяют, кто имеет доступ к каким endpoints.
Необходимые инструменты и зависимости
Убедитесь, что установлены следующие пакеты:
Django: Веб-фреймворк.Django REST Framework: Фреймворк для создания API.djangorestframework-simplejwt(опционально): Для JWT аутентификации.
Установка:
pip install django djangorestframework djangorestframework-simplejwt
Создание пользовательской модели пользователя
Определение модели пользователя: поля и методы
Создайте файл models.py в вашем Django приложении (например, accounts) и определите пользовательскую модель, унаследовав её от AbstractBaseUser и PermissionsMixin:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class CustomUserManager(BaseUserManager):
def create_user(self, email: str, password: str = None, **extra_fields):
"""Создает и возвращает нового пользователя."""
if not email:
raise ValueError('Email address is required')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email: str, password: str):
"""Создает и возвращает нового суперпользователя."""
user = self.create_user(email, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""Пользовательская модель пользователя."""
email = models.EmailField(unique=True, verbose_name='Email Address')
first_name = models.CharField(max_length=150, blank=True, verbose_name='First Name')
last_name = models.CharField(max_length=150, blank=True, verbose_name='Last Name')
is_active = models.BooleanField(default=True, verbose_name='Active')
is_staff = models.BooleanField(default=False, verbose_name='Staff status')
date_joined = models.DateTimeField(auto_now_add=True, verbose_name='Date joined')
phone_number = models.CharField(max_length=20, blank=True, verbose_name='Phone Number')
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
Настройка менеджера пользователей
Необходимо создать менеджер пользователей (CustomUserManager) для управления созданием пользователей и суперпользователей. Это позволяет определить логику, специфичную для вашей модели.
Регистрация пользовательской модели в settings.py
Укажите вашу пользовательскую модель в settings.py:
AUTH_USER_MODEL = 'accounts.User'
Миграции базы данных
Создайте и примените миграции:
python manage.py makemigrations
python manage.py migrate
Настройка сериализаторов для пользовательской модели пользователя
Создание сериализаторов для регистрации, аутентификации и профиля пользователя
Создайте файл serializers.py в вашем приложении и определите сериализаторы:
from rest_framework import serializers
from .models import User
class UserRegistrationSerializer(serializers.ModelSerializer):
"""Сериализатор для регистрации новых пользователей."""
password = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'})
password2 = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'})
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'password', 'password2')
extra_kwargs = {
'first_name': {'required': True},
'last_name': {'required': True}
}
def validate(self, data):
"""Проверяет совпадение паролей."""
if data['password'] != data['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return data
def create(self, validated_data):
"""Создает нового пользователя."""
user = User.objects.create_user(
email=validated_data['email'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
password=validated_data['password']
)
return user
class UserLoginSerializer(serializers.Serializer):
"""Сериализатор для аутентификации пользователей."""
email = serializers.CharField(required=True)
password = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'})
class UserProfileSerializer(serializers.ModelSerializer):
"""Сериализатор для профиля пользователя."""
class Meta:
model = User
fields = ('id', 'email', 'first_name', 'last_name', 'phone_number')
read_only_fields = ('email', 'id')
Валидация данных в сериализаторах
Используйте метод validate для кастомной валидации данных, например, для проверки совпадения паролей.
Переопределение методов create и update
Переопределите методы create и update для реализации кастомной логики создания и обновления пользователей.
Создание API endpoints для работы с пользовательской моделью
Реализация endpoints для регистрации новых пользователей
Создайте файл views.py и определите views для регистрации, аутентификации и получения профиля пользователя:
from rest_framework import generics, permissions
from rest_framework.response import Response
from rest_framework import status
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
from .serializers import UserRegistrationSerializer, UserLoginSerializer, UserProfileSerializer
class UserRegistrationView(generics.CreateAPIView):
"""View для регистрации новых пользователей."""
serializer_class = UserRegistrationSerializer
permission_classes = (permissions.AllowAny,)
class UserLoginView(generics.GenericAPIView):
"""View для аутентификации пользователей."""
serializer_class = UserLoginSerializer
permission_classes = (permissions.AllowAny,)
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid(raise_exception=True):
email = serializer.validated_data['email']
password = serializer.validated_data['password']
user = authenticate(request, email=email, password=password)
if user is not None:
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserProfileView(generics.RetrieveUpdateAPIView):
"""View для получения и обновления профиля пользователя."""
serializer_class = UserProfileSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_object(self):
return self.request.user
Реализация endpoints для аутентификации пользователей (логин)
Используйте authenticate для проверки учетных данных пользователя.
Реализация endpoints для получения и обновления информации о пользователе (профиль)
Используйте RetrieveUpdateAPIView для получения и обновления профиля пользователя. Метод get_object возвращает текущего пользователя.
Использование разрешений (permissions) для защиты endpoints
Используйте permissions.IsAuthenticated для защиты endpoints, требующих аутентификации.
Зарегистрируйте ваши views в urls.py:
from django.urls import path
from .views import UserRegistrationView, UserLoginView, UserProfileView
urlpatterns = [
path('register/', UserRegistrationView.as_view(), name='register'),
path('login/', UserLoginView.as_view(), name='login'),
path('profile/', UserProfileView.as_view(), name='profile'),
]
Тестирование и отладка
Написание тестов для API endpoints
Создайте файл tests.py в вашем приложении и напишите тесты для проверки функциональности API endpoints. Используйте библиотеку pytest или встроенный unittest.
Использование Postman или cURL для тестирования API
Postman и cURL – удобные инструменты для тестирования API endpoints. Отправляйте запросы к вашим endpoints и проверяйте ответы.
Отладка проблем и распространенные ошибки
- Неправильные настройки в
settings.py: ПроверьтеAUTH_USER_MODEL. - Проблемы с миграциями: Убедитесь, что миграции созданы и применены.
- Ошибки в сериализаторах: Проверьте валидацию данных и методы
createиupdate. - Неправильные разрешения: Убедитесь, что endpoints защищены нужными разрешениями.
Следуя этому руководству, вы сможете создать пользовательскую модель пользователя в Django REST Framework и настроить API endpoints для работы с ней.