在Django休息框架中转换`ManyToManyField`

时间:2014-02-19 14:30:58

标签: django api rest django-rest-framework

我正在使用Django-rest-framework来构建API。我有一个模型Chair我正在构建一个视图集。它与模型ManyToManyFieldTag,因此每个主席都有多个标记。

Tag是一个Django模型,但在与API交互时,我不希望看到每个标记的JSON字典;我只想使用标签的名称。

E.g。在API中查看Chair时,我希望看到它有这个:

{
    'tags': ['meow', 'frrr', 'nutella'],
     ... Any other chair attributes
}

同样,当我创建Chair时,我希望能够传入一个标记名称列表,然后为每个标记名称执行get_or_create。 (所以我要么使用带有该名称的现有标签,要么创建一个新标签。)

如何将所有这些逻辑放入我的序列化程序/视图集中?

1 个答案:

答案 0 :(得分:2)

在序列化程序中定义您的标记字段,如下所示:

tags = serializers.SlugRelatedField(slug_field='name', many=True)

现在对于get_or_create行为,我的建议是使用django表单。您必须覆盖post方法(如果使用视图集,则创建方法)并编写一个正常的django方法,以便使用表单创建内容。

查看request.DATA它是一个普通的python字典,用它作为椅子表格的数据。

表单将接受此数据,然后您可以正常验证数据,就像使用django表单一样。

然后使用:

创建一个椅子实例
chair = form.save(commit=False)
chair.save()

现在您拥有了椅子实例,您可以使用以下方法添加任意数量的标签:

chair.tags.add(tag1, tag2, tag3...)

要将标记作为python对象获取,请从request.DATA dict中取出标记名称列表,并将名称传递给get_or_create函数。你可以这样做:

tags = []
tags_name_list = request.DATA['tags']
for tag_name in tags_name_list:
    tag = Tag.objects.get_or_create(name=tag_name)
    tags.append(tag)

现在您有了标签列表。将它们添加到主席:

chair.tags.add(*tags)