Django Rest Framework - 更新外键

时间:2015-10-12 09:08:51

标签: django django-rest-framework

我对使用Django Rest Framework的这个问题感到有点沮丧:

我正在使用 viewset depth set to 1。此序列化程序具有data = { id: 1, issue_name: 'This is a problem', status: { id: 3, name: 'todo' } } 。当我查询这个视图集时,我得到了正确的数据表示,例如:

status_new = {
   id: 4,
   name: 'done'
}

当我需要更新状态时,会出现问题。例如,如果我想为此问题选择其他状态,例如:

data = {
  id: 1,
  issue_name: 'This is a problem',
  status: {
    id: 4,
    name: 'done'
  }

}

我将以下PATCH发送回服务器,这是输出:

{{1}}

但是,状态不会更新。事实上,它甚至不是validated_data字典的一部分。我已经读过嵌套关系是只读的。有人可以用一种简单的方式告诉我我需要做什么吗?

真的有义务。

提前致谢

3 个答案:

答案 0 :(得分:6)

documentation所述,您需要在序列化程序中编写自己的create()update()方法,以支持可写的嵌套数据。

您还需要显式添加状态字段,而不是使用depth参数,否则我认为它不会自动添加到validated_data

编辑:也许我对细节有点缺点:你想要做的是覆盖ModelIssueSerializer中的更新。这基本上会拦截串行器级别的PATCH / PUT请求。然后获取新状态并将其分配给实例,如下所示:

class StatusSerializer(serializers.ModelSerializer):
    class Meta:
        model = Status

class ModelIssueSerializer(serializers.ModelSerializer):
    status = StatusSerializer()
    # ...
    def update(self, instance, validated_data):
        status = validated_data.pop('status')
        instance.status_id = status.id
        # ... plus any other fields you may want to update
        return instance

我在评论中提到您可能需要添加StatusSerializer字段的原因是为了将状态设置为validated_data。如果我没记错的话,如果你只使用depth,那么嵌套对象可能不会在update() / create()方法中被序列化(尽管我可能会弄错)。无论如何,添加StatusSerializer字段只是使用depth=1

的明确形式

答案 1 :(得分:0)

我认为您的模型会模仿序列化程序的数据。此外,我假设您与状态有一对多的关系,但您不需要通过问题序列化程序创建它们,您有一个不同的端点。在这种情况下,您可能会使用SlugRelatedField

SELECT id, cid, sid, posttitle, postdetails, city, `state`, zipcode 
FROM posts 
ORDER BY datepublished DESC

另一个有效的解决方案是留下外键值并通过ui-select或select2组件处理前端的显示名称 - RESTfull方法:您正在处理具有状态引用的Issue对象对象。在Angular前端应用程序中,您将查询特定路径上后端的所有状态,然后您将根据外键值表单Issue显示正确的描述性名称。

让我知道这对你有什么帮助。

答案 2 :(得分:0)

在这种情况下,我通常使用自定义字段。

class StatusField(serializers.Field):

    def to_representation(self, value):
        return StatusSerializer(value).data

    def to_internal_value(self, data):
        try:
            return Status.objects.filter(id=data['id']).first()
        except (AttributeError, KeyError):
            pass

然后在主序列化程序中:

class IssueSerializer(serializers.ModelSerializer):
    status = StatusField()

    class Meta:
        model = MyIssueModel
        fields = (
            'issue_name',
            'status',
        )