Как использовать один сериализатор для сохранения нескольких моделей
Проблема: я не могу сохранить обе модели в базе данных из одного серийника.
Описание : Я использую библиотеку 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".
- Вам не нужно предоставлять
CustomUserCreateSerializer.Meta.extra_kwargs
пароль, потому что параметр "write_only" уже установлен вdjoser.serializers.UserCreateSerializer
; - Вы настроили
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