Когда вызывается метод `create` в сериализаторе Django REST Framework?

Ответ

Метод create() в сериализаторе Django REST Framework (DRF) вызывается, когда вы сохраняете новый объект через serializer.save() и сериализатор был инициализирован без существующего экземпляра (instance=None или не передан).

Назначение: Этот метод предназначен для реализации пользовательской логики создания объекта, которая выходит за рамки простого сохранения полей модели. Например:

  • Создание связанных объектов.
  • Выполнение дополнительных действий после создания (отправка уведомлений).
  • Хеширование паролей или другая обработка данных перед сохранением.

Метод create() принимает один аргумент: validated_data (словарь проверенных данных) и должен вернуть созданный экземпляр модели.

Пример: Предположим, нам нужно создать пользователя с хешированным паролем, используя метод create_user модели User.

from rest_framework import serializers
from django.contrib.auth.models import User # Пример модели пользователя

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'email', 'password']
        extra_kwargs = {'password': {'write_only': True}} # Пароль только для записи

    def create(self, validated_data):
        # Извлекаем пароль, чтобы передать его в create_user
        password = validated_data.pop('password', None)
        user = User.objects.create_user(**validated_data)
        if password:
            user.set_password(password) # Хешируем и устанавливаем пароль
            user.save()
        return user

# Использование в представлении (например, для POST-запроса):
# from rest_framework.response import Response
# from rest_framework import status
# serializer = UserSerializer(data=request.data)
# if serializer.is_valid():
#     user = serializer.save() # Здесь будет вызван метод create()
#     return Response(user.username, status=status.HTTP_201_CREATED)

Важно: Если сериализатор инициализирован с существующим объектом (serializer = UserSerializer(instance=user, data=...)), то при вызове serializer.save() вместо create() будет вызван метод update().

Ответ 18+ 🔞

А, ну это про метод create() в DRF, да? Так, слушай, это ж та самая штука, которая выстреливает, когда ты через serializer.save() новый объект в базу пихаешь, и сериализатору не подсунули старый экземпляр, чтобы обновить. То есть, чистый, девственный POST-запрос, понимаешь?

Зачем он вообще, этот create()? Ну, блядь, иногда же мало просто взять данные и запихнуть их в модель как есть, как дурак. Бывает же логика какая-то, ёпта! Например:

  • Надо ещё кучу связанных объектов налепить.
  • Или после создания письмо какое-нибудь отправить, типа «добро пожаловать, лох».
  • Или, там, пароль хешировать, а не хранить как есть, чтобы потом не охуеть от стыда.

Метод этот принимает один аргумент — validated_data. Это такой уже проверенный, чистый словарь с данными, которые можно в рот брать. И он обязан вернуть тебе готовый, сохранённый в базе экземпляр модели. Не хухры-мухры, а конкретный объект.

Смотри, как это выглядит на практике, ёбана: Допустим, нам надо пользователя создать, но пароль хешировать, а не в открытом виде хранить, как какой-то распиздяй.

from rest_framework import serializers
from django.contrib.auth.models import User # Ну, стандартная модель пользователя

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'email', 'password']
        extra_kwargs = {'password': {'write_only': True}} # Пароль, сука, только для записи, чтоб не светить

    def create(self, validated_data):
        # Вытаскиваем пароль из словаря, чтобы его отдельно обработать
        password = validated_data.pop('password', None)
        # Создаём юзера, но пока без пароля
        user = User.objects.create_user(**validated_data)
        if password:
            user.set_password(password) # Вот тут магия хеширования, блядь!
            user.save()
        return user # Возвращаем готового пользователя, как и положено

# А в каком-нибудь View это будет использоваться так:
# serializer = UserSerializer(data=request.data)
# if serializer.is_valid():
#     user = serializer.save() # БАМ! Вот тут-то и вызывается наш кастомный create()
#     return Response(user.username, status=status.HTTP_201_CREATED)

Важный момент, на котором все обжигаются, как дураки: Если ты сериализатору скормил уже существующий объект (типа serializer = UserSerializer(instance=user, data=...)), то при save() вызовется уже не create(), а update(). DRF сам соображает, что ты тут делаешь — рожаешь нового или старика переделываешь. В общем, не тупи.