Я пытаюсь включить регистрацию пользователя через rest-framework. Мне требуются разные группы пользователей с разной информацией, связанной с их профилями. Я изо всех сил пытаюсь, чтобы мой UserSerializer вызывал различные ProfileSerializer (в зависимости от группы) без проблем. Я хочу, чтобы один API создавал как пользователя, так и профиль.
Я попытался включить и отключить профиль в качестве поля в моем пользовательском сериализаторе. Наличие профиля ссылается на DictField, который затем изменяется на соответствующий сериализатор при инициализации.
Я попытался создать минимальный воспроизводимый код ниже:
models.py
class User(AbstractUser):
@property
def group(self):
groups = self.groups.all()
return groups[0].name if groups else None
class StoreProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
related_name='store_profile'
)
location = models.CharField(max_length=30, blank=True)
class CustomerProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
related_name='customer_profile'
)
address = models.CharField(max_length=30)
serializers.py
class StoreProfileSerializer(serializers.ModelSerializer):
class Meta:
model = StoreProfile
fields = ('location',)
class CustomerProfileSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerProfile
fields = ('address',)
class UserSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
group = serializers.CharField()
profile = serializers.DictField()
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs)
if self.instance and self.instance.group == 'store':
self.profile = StoreProfileSerializer()
elif self.instance and self.instance.group == 'customer':
self.profile = CustomerProfileSerializer()
def create(self, validated_data):
group_data = validated_data.pop('group')
group, _ = Group.objects.get_or_create(name=group_data)
profile_data = validated_data.pop('profile')
data = {
key: value for key, value in validated_data.items()
if key not in ('password1', 'password2')
}
data['password'] = validated_data['password1']
user = self.Meta.model.objects.create(**data)
if group_data == 'store':
StoreProfile.objects.create(user=user, **profile_data)
if group_data == 'customer':
CustomerProfile.objects.create(user=user, **profile_data)
user.groups.add(group)
user.save()
return user
class Meta:
model = get_user_model()
fields = (
'id', 'username', 'password1', 'password2',
'first_name', 'last_name', 'group', 'profile',
)
read_only_fields = ('id',)
views.py
class SignUpView(generics.CreateAPIView):
queryset = get_user_model().objects.all()
serializer_class = UserSerializer
Включая профиль, который я получаю:
AttributeError: Получил AttributeError при попытке получить значение для поля profile
на сериализаторе UserSerializer
.
Поле сериализатора может иметь неправильное имя и не соответствовать ни одному атрибуту или ключу в экземпляре User
.
Исходный текст исключения был: объект «Пользователь» не имеет атрибута «профиль».
Включая профиль, который я получаю:
profile_data = validated_data.pop ('profile')
KeyError: 'profile'
Я просто хочу создать пользовательский и зависимый от группы профиль, связанный с помощью related_name (не через атрибут профиля), используя одну путевую точку API.
Я прочитал несколько других ответов на вопросы stackoverflow и внешние уроки, перепробовал много комбинаций кода, но без особого успеха. Большое спасибо за ваше время.