Как использовать один сериализатор для сохранения нескольких моделей

Проблема: я не могу сохранить обе модели в базе данных из одного серийника.

Описание : Я использую библиотеку djoser auth для регистрации и аутентификации. Для этого я использую пользовательский django auth user и сопоставляю его с моделью userprofile. Так как я использую userprofile вместе с пользователем django, я должен использовать пользовательский сериализатор регистра.

# Мои модели class CustomUser(AbstractUser): username = None email = models.EmailField(_("адрес электронной почты"), unique=True)

USERNAME_FIELD = "email"
REQUIRED_FIELDS = []

objects = CustomUserManager()

class UserProfile(models.Model): user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, related_name="userProfile") user_guid = models.UUIDField( default=uuid.uuid4, unique=True, редактируемое=Ложь ) тип_пользователя = models.IntegerField(choices=UserType.choices(), default=UserType.BUYER) баланс_кошелька = models.FloatField() created_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now_add=True)

class Meta:
    ordering = ['created_at' ]  # Corrected the ordering syntax`

`#Мой сериализатор CustomUser = get_user_model()

class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = UserProfile fields = ['user_guid', 'user_type', 'wallet_balance', 'created_at', 'updated_at'] read_only_fields = ['user_guid', 'created_at', 'updated_at']

class CustomUserCreateSerializer(DjoserUserCreateSerializer): userProfile = UserProfileSerializer()

class Meta:
    model = CustomUser
    fields = ['id', 'email', 'password', 'userProfile']
    extra_kwargs = {'password': {'write_only': True}}

def create(self, validated_data):
    user_profile_data = validated_data.pop('userProfile')
    user = CustomUser.objects.create_user(**validated_data)
    

    UserProfile.objects.create(user=user, **user_profile_data)
    return user`

AUTH_USER_MODEL = 'users.CustomUser' DJOSER = { 'SERIALIZERS': { 'user_create': 'users.v1.serializers.CustomUserCreateSerializer', 'user': 'users.v1.serializers.CustomUserCreateSerializer', 'current_user': 'users.v1.serializers.CustomUserCreateSerializer', } }`

Error : raise ValueError( ValueError: Невозможно присвоить "{'user_type': 1, 'wallet_balance': 0.0}": "CustomUser.userProfile" должен быть экземпляром "UserProfile".

  1. Вам не нужно предоставлять CustomUserCreateSerializer.Meta.extra_kwargs пароль, потому что параметр "write_only" уже установлен в djoser.serializers.UserCreateSerializer;
  2. Вы настроили create метод, как в этой документации, но вам нужно настроить validate метод тоже.
from django.contrib.auth.password_validation import validate_password
from django.core import exceptions as django_exceptions
from djoser.serializers import UserCreateSerializer
from rest_framework import serializers
from rest_framework.settings import api_settings

from .models import UserProfile, CustomUser


class UserProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = ['user_guid', 'wallet_balance', 'created_at', 'updated_at']
        read_only_fields = ['user_guid', 'created_at', 'updated_at']


class CustomUserCreateSerializer(UserCreateSerializer):
    user_profile = UserProfileSerializer()

    class Meta:
        model = CustomUser
        fields = ['id', 'email', 'password', 'user_profile']

    def create(self, validated_data):
        profile_data = validated_data.pop('user_profile')
        user = CustomUser.objects.create_user(**validated_data)
        UserProfile.objects.create(user=user, **profile_data)
        return user

    def validate(self, attrs):
        profile_data = attrs.pop("user_profile")
        user = CustomUser(attrs)
        profile = UserProfile(user=user, **profile_data)
        password = attrs.get("password")
        try:
            validate_password(password, user)
        except django_exceptions.ValidationError as e:
            serializer_error = serializers.as_serializer_error(e)
            raise serializers.ValidationError(
                {"password": serializer_error[api_settings.NON_FIELD_ERRORS_KEY]}
            )
        attrs["user_profile"] = profile_data
        return attrs

это отлично работало на моей машине

  • Обратите внимание на то, что я удалил поле user_type, потому что вы не показали его должным образом в своем вопросе (вы можете использовать его по своему усмотрению).
python manage.py shell

Python 3.11.9 (tags/v3.11.9:de54cf5, Apr  2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from my_app.serializers import CustomUserCreateSerializer                                                     
>>> data = {"email": "lengthylyova@gmail.com", "password": "SomeInsanePassword123", "user_profile": {"wallet_balance": 0.0}}
>>> serializer = CustomUserCreateSerializer(data=data)
>>> serializer.is_valid(raise_exception=True) 
True
>>> serializer.save()
<CustomUser: lengthylyova@gmail.com>

Экземпляр UserProfile также создан

sqlite3 db.sqlite3

sqlite> select * from my_app_userprofile;
1|3c6a03729d6a41f4b719b7a702b06507|0.0|2024-07-30 00:01:36.824563|2024-07-30 00:01:36.824563|1
Вернуться на верх