Расширение пользователя Django с помощью объекта модели динамического профиля с использованием Rest Framework - PullRequest
0 голосов
/ 21 мая 2019

Я пытаюсь включить регистрацию пользователя через 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 и внешние уроки, перепробовал много комбинаций кода, но без особого успеха. Большое спасибо за ваше время.

...