首页 文章

Django Rest Framework如何从多个模型创建Serializer

提问于
浏览
3

我需要扩展用户模型以添加地址,分数,更多user_types等内容 . 有两种方法可以实现这一点,扩展用户模型或创建一个与目标用户连接的新模型 OneToOneField . 我决定使用新模型,因为它似乎更容易,并建议在this堆栈溢出问题 . 但是现在我无法在没有嵌套配置文件字段的情况下创建Serializer,因为默认的rest_framwork文档生成器无法生成嵌套序列化程序的文档 .

我的 UserSerializer 看起来像这样:

class UserSerializer(serializers.ModelSerializer):
    # This creates a nested profile field
    profile = ProfileSerializer(required=True)

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create_user(**validate_data)
        profile, created = Profile.objects.upodate_or_creeate(user=user, defaults=profile_data)
        return user

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password', 'buckelists', 'profile')
        read_only_fields = ('id',)
        extra_kwargs = {'password':{'write_only': True}}

此Serializer采用以下JSON格式:

{
    'name': ...,
    'email': ...,
    'password': ...,
    'profile': {
        'address': ...,
        'score': ...,
        'user_type': ...,
        'achievements': ...,
        'country': ...,
        'trusted': ...,
    }

这看起来很奇怪,使用 rest_framework.documentation.include_docs_urls 生成的文档如下所示:

{
    'username': ...,
    'email': ...,
    'password': ...,
    'field': ...,
}

因此,不清楚应在简档字段中包含哪些内容 . 我想创建接受以下格式的Serializer:

{
    'name': ...,
    'email': ...,
    'password': ...,
    'address': ...,
    'score': ...,
    'user_type': ...,
    'achievements': ...,
    'country': ...,
    'trusted': ...,
}

是否可以从头开始创建自定义Serializer?或者至少可以生成嵌套序列化程序的文档 .

PS:我使用python3.6和Django 2.1

编辑:这是我的models.py的相关部分:

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)

trusted = models.BooleanField(default=False)
address = models.CharField(max_length=100, default="")

COUNTRIES = (
    ('CZ', 'Czech Republic'),
    ('EN', 'England'),
)
country = models.CharField(max_length=2, choices=COUNTRIES, default="CZ")

score = models.BigIntegerField(default=0)

achievements = models.ManyToManyField(Achievement, blank=True)

USER_TYPES = (
    ('N', 'Normal'),
    ('C', 'Contributor'),
    ('A', 'Admin'),
)
user_type = models.CharField(max_length=1, choices=USER_TYPES, default='N')


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
    Token.objects.create(user=instance)


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created=False, **kwargs):
if created:
    profile, created = Profile.objects.get_or_create(user=instance)
profile.save()

编辑:

Mohammad Ali 's answers solves this for GET, but I' d也喜欢使用POST,UPDATE和PATCH方法 . 我发现我必须使用 source 参数,但这是相对于序列化程序我不知道如何引用配置文件没有配置文件字段 .

2 回答

  • -1

    放轻松,您可以在create函数中创建Profile obj .

    class UserSerializer(serializers.ModelSerializer):
    
        trusted = serializers.BooleanField()
        address = serializers.CharField()
    
        class Meta:
            model = User
            fields = ('username', 'email', 'password', 'trusted', 'address',)
    
        def create(self, validated_data):
            user = User.objects.create(username=validated_data['username'], email=validated_data['email'])
            user.set_password(validated_data['password'])
            user.save()
    
            profile = Profile(user=user, trusted=validated_data['trusted'], address=validated_data['address']
            profile.save()
            return validated_data
    

    它只是您的场景的简要实现 . 你可以填写这个故事 .

  • 1

    Plase读取Serializers的文档:Django REST FRAMEWORK - user related_name

    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="user_profile") # models
    
    class ProfileSerializer(serializers.ModelSerializer):
        user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False)
    
         class Meta:
            model = Profile
            fields = '__all__'
    
    
    class UserSerializer(serializers.ModelSerializer):
        user_profile = ProfileSerializer(required=True)
    
        class Meta:
            model = User
            fields = '__all__'
    

相关问题