Django Rest Framework 使 OnetoOne 关系感觉就像是一个模型 [英] Django Rest Framework make OnetoOne relation ship feel like it is one model

查看:18
本文介绍了Django Rest Framework 使 OnetoOne 关系感觉就像是一个模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将我的 User 保存在两个不同的模型中,UserProfileUser.现在从 API 的角度来看,没有人真正关心这两者是否不同.

I have my User saved in two different models, UserProfile and User. Now from API perspective, nobody really cares that these two are different.

所以我有:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'first_name', 'last_name', 'email')

class UserPSerializer(serializers.HyperlinkedModelSerializer):
    full_name = Field(source='full_name')
    class Meta:
        model = UserProfile
        fields = ('url', 'mobile', 'user','favourite_locations')

因此,在 UserPSerializer 中,字段 user 只是指向该资源的链接.但是从用户的角度来看,他根本没有理由了解 User.

So in UserPSerializer the field user is just a link to that resource. But form a User perspective there is really no reason for him to know about User at all.

是否有一些技巧可以让我将它们混合在一起并将它们作为一个模型呈现给用户,或者我是否必须以某种方式手动执行此操作.

Is there some tricks with which I can just mash them together and present them to the user as one model or do I have to do this manually somehow.

推荐答案

您可以使用 @kahlo 的方法 POST 和 PUT如果您还覆盖序列化程序上的 create 和 update 方法.

You can POST and PUT with @kahlo's approach if you also override the create and update methods on your serializer.

给定这样的配置文件模型:

Given a profile model like this:

class Profile(models.Model):
    user = models.OneToOneField(User)
    avatar_url = models.URLField(default='', blank=True)  # e.g.

这是一个同时读取和写入附加配置文件字段的用户序列化程序:

Here's a user serializer that both reads and writes the additional profile field(s):

class UserSerializer(serializers.HyperlinkedModelSerializer):
    # A field from the user's profile:
    avatar_url = serializers.URLField(source='profile.avatar_url', allow_blank=True)

    class Meta:
        model = User
        fields = ('url', 'username', 'avatar_url')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile', None)
        user = super(UserSerializer, self).create(validated_data)
        self.update_or_create_profile(user, profile_data)
        return user

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile', None)
        self.update_or_create_profile(instance, profile_data)
        return super(UserSerializer, self).update(instance, validated_data)

    def update_or_create_profile(self, user, profile_data):
        # This always creates a Profile if the User is missing one;
        # change the logic here if that's not right for your app
        Profile.objects.update_or_create(user=user, defaults=profile_data)

生成的 API 根据需要呈现平面用户资源:

The resulting API presents a flat user resource, as desired:

GET /users/5/
{
    "url": "http://localhost:9090/users/5/", 
    "username": "test", 
    "avatar_url": "http://example.com/avatar.jpg"
}

并且您可以在 POST 和 PUT 请求中包含配置文件的 avatar_url 字段.(用户资源上的 DELETE 也将删除其 Profile 模型,尽管这只是 Django 的正常删除级联.)

and you can include the profile's avatar_url field in both POST and PUT requests. (And DELETE on the user resource will also delete its Profile model, though that's just Django's normal delete cascade.)

这里的逻辑将总是为用户创建一个配置文件模型,如果它丢失(在任何更新时).对于用户和配置文件,这可能就是您想要的.对于其他关系,它可能不是,您需要更改更新或创建逻辑.(这就是为什么 DRF 没有't 自动为您写入嵌套关系.)

The logic here will always create a Profile model for the User if it's missing (on any update). With users and profiles, that's probably what you want. For other relationships it may not be, and you'll need to change the update-or-create logic. (Which is why DRF doesn't automatically write through a nested relationship for you.)

这篇关于Django Rest Framework 使 OnetoOne 关系感觉就像是一个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆