Как создать пользовательскую модель пользователя в Django Rest Framework: пошаговое руководство

Зачем нужна пользовательская модель пользователя?

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 для работы с ней.


Добавить комментарий