使用Rest Framework使用动态配置文件模型对象扩展Django用户

时间:2019-05-21 07:07:17

标签: python django django-models django-rest-framework django-users

我正在尝试通过其余框架启用用户注册。我要求不同的用户组具有与他们的个人资料相关的不同信息。我正在努力使我的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:尝试在序列化程序profile上获取字段UserSerializer的值时,出现AttributeError。 序列化程序字段的名称可能不正确,并且与User实例上的任何属性或键都不匹配。 原始异常文本为:“用户”对象没有属性“配置文件”。

包括个人资料,我得到:     profile_data = validated_data.pop('profile') KeyError:“个人资料”

我只是希望使用单个API航路点,通过related_name(而不是通过profile属性)创建用户和与组有关的profile。

我已经阅读了多个其他stackoverflow答案和外部教程,尝试了多种代码组合,但未获得成功。非常感谢您的宝贵时间。

0 个答案:

没有答案