Django rest框架一对一关系
Posted
技术标签:
【中文标题】Django rest框架一对一关系【英文标题】:Django rest framework one to one relation 【发布时间】:2015-10-30 22:50:57 【问题描述】:所以我有以下模型:
class A(models.Model):
name = models.CharField()
age = models.SmallIntergerField()
class B(models.Model):
a = models.OneToOneField(A)
salary = model.IntergerField()
现在我想为这两个创建一个休息端点,因为它们是一对一的。所以我想跟着get
url: 'http://localhost/customs/1/',
name: 'abc',
age: 24,
salary: 10000
同样,我也想创建记录和更新。请让我知道如何在 django rest framework 3 中实现这一点。
【问题讨论】:
【参考方案1】:我知道这是一篇旧帖子,但经过一些研究和阅读Django Rest Framework documentation,我发现了这个 所以快速搜索一下,我发现您可以使用“related_name”参数进行反向关系,如here 所述
ModelSerializer
和 HyperlinkedModelSerializer
类不会自动包含反向关系。要包含反向关系,您必须将其显式添加到字段列表中。
例如:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ['tracks', ...]
您通常需要确保为关系设置了适当的 related_name
参数,您可以将其用作字段名称。
例如:
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks',
on_delete=models.CASCADE)
...
如果您没有为反向关系设置相关名称,则需要在fields
参数中使用自动生成的related name
。
例如:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ['track_set', ...]
另外,请参阅reverse relationships 上的 Django 文档了解更多详细信息。
【讨论】:
【参考方案2】:我刚刚遇到了同样的问题,让响应结构减少与底层模型结构的联系确实很有用。这是我的看法:
阅读很容易
Serializer fields有一个source
参数,可以带点名来遍历属性。
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
写作是……没有官方支持
经过验证的数据将显示嵌套结构,并且标准的创建和更新方法会在尝试将数据字典分配给 OneToOneField 时阻塞。 好消息是您可以通过覆盖 create and update 方法来解决它。这是一个更新示例:
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
related_fields = ['b']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
def update(self, instance, validated_data):
# Handle related objects
for related_obj_name in self.Meta.related_fields:
# Validated data will show the nested structure
data = validated_data.pop(related_obj_name)
related_instance = getattr(instance, related_obj_name)
# Same as default update implementation
for attr_name, value in data.items():
setattr(related_instance, attr_name, value)
related_instance.save()
return super(ABSerializer,self).update(instance, validated_data)
当然,这个例子非常简单,不做任何异常处理,也不能处理嵌套更深的对象……但你明白了。
另一种选择
您也可以create a read-write flavor of SerializerMethodField,它会同时考虑getter 和setter,但最终可能会变得更加冗长。
希望有帮助!
【讨论】:
我更喜欢覆盖更新方法并显式获取经过验证的数据,因此不暗示处理“自动”错误(当然以“更多代码”为代价)。在示例中instance.b.salary = validated_data.get('b', ).get('salary', '$1000000')
以上是关于Django rest框架一对一关系的主要内容,如果未能解决你的问题,请参考以下文章
如何使用模型序列化器在 django-rest 中序列化一对多关系?
Django.rest_framework:如何序列化一对多?