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

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

问题描述

我的用户保存在两种不同的模型中, UserProfile 用户。从API的角度来看,没有人真的在乎这两者是不同的。



所以这里我有:

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

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

所以在 UserPSerializer 字段用户只是指向该资源的链接。但是,从用户角度来看,根本就没有理由知道 User



有没有一些

解决方案

如果您还重写序列化程序上的创建和更新方法,您可以使用 @ kahlo的方法POST和PUT。 / p>

给出一个这样的配置文件模型:

 模型):
user = models.OneToOneField(User)
avatar_url = models.URLField(default ='',blank = True)#eg

这是一个用户串行器,可以读取和写入附加的配置文件字段:

 类UserSerializer(serializers.HyperlinkedModelSerializer):
#用户配置文件中的一个字段:
avatar_url = serializers.URLField source ='profile.avatar_url',allow_blank = True)

class Meta:
model =用户
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(inst ance,validated_data)

def update_or_create_profile(self,user,profile_data):
#如果用户缺少一个,这总是创建一个配置文件;
#更改逻辑,如果这不适合您的应用程序
Profile.objects.update_or_create(user = user,defaults = profile_data)

所需的API会根据需要提供一个平面的用户资源:

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

您可以在POST和PUT请求中包含配置文件的 avatar_url 字段。 (和用户资源上的DELETE也会删除其配置文件模型,虽然这只是Django的正常删除级联。)



这里的逻辑将始终为用户创建配置文件模型(如果有任何更新)。用户和个人资料,这可能是你想要的。对于其他关系,它可能不是,您需要更改更新或创建逻辑。 (这就是为什么DRF doesn不要通过嵌套关系自动写入。)


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

So here I have:

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

and

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

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.

解决方案

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)

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"
}

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.)

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框架使OnetoOne关系船感觉像是一个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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