Django REST:嵌套对象添加创建(POST)而不仅仅是更新(PUT)

时间:2013-02-20 11:14:14

标签: django django-rest-framework

使用Django rest

以下是我使用serializer.py的方法。

class ProfileSerializer(serializers.ModelSerializer):


    class Meta:
        model = Profile
        fields = ('id', 'name', 'active', 'type')

类型是平面视图

然后我更改了它,因此'type'嵌套在每个配置文件中,就像这样...

class TypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Type
        fields = ('id', 'name', 'active')

class ProfileSerializer(serializers.ModelSerializer):

    type = TypeSerializer()

    class Meta:
        model = Profile
        fields = ('id', 'name', 'active', 'type'')

现在这种方法很完美,但我现在只能在配置文件详细信息中更新“类型”,现在它是只读的。

如何在创建新配置文件时添加类型并仍保留此嵌套视图?

我希望我已经清楚地解释了这一点。

更新

好的,我刚看过这个:

  

注意:嵌套序列化程序仅适用于只读   表示,因为有些情况下他们会有歧义或   更新实例时使用的非显而易见的行为。用于读写   表示你应该总是使用平面表示,使用   其中一个RelatedField子类。

这样才有意义。所以我改成了....

type = serializers.PrimaryKeyRelatedField()

将它放回到POST并工作,但这很遗憾,我不能用ID和名称来代表'type',这样对最终用户更有意义吗?

3 个答案:

答案 0 :(得分:13)

可写嵌套序列化程序的完全支持是work in progress,但与此同时,一种解决方案是在每种情况下覆盖视图中的create方法:

class FooListCreateView(ListCreateAPIView):
    model = Foo
    serializer_class = FooSerializer

    def create(self, request, *args, **kwargs):
        data=request.DATA

        f = Foo.objects.create()

        # ... create nested objects from request data ...  

        # ...
        return Response(serializer.data, 
                        status=status.HTTP_201_CREATED,
                        headers=headers)

可能不理想,但它适用于我,直到正确的方式出现。

答案 1 :(得分:6)

我在django-rest-framework中遇到了同样的问题,我已经创建了一个真实快速的视图,你可以在这个要点中找到它:https://gist.github.com/edulix/5311365

CRUDManyToManyView 的基本用法如下:

<强> views.py

from models import Project
from serializers import TaskSerializer
from lib.crudmanytomanyview import CRUDManyToManyView

class ProjectTasks(CRUDManyToManyView):
    model = Project
    field_name = 'tasks'
    serializer_class = TaskSerializer

<强> urls.py

from django.conf.urls import patterns, url
import views

urlpatterns = patterns(
'',
    url(r'^projects/(?P<pk>[0-9]+)/tasks/((?P<field_pk>[0-9]+)/)?$',
        views.ProjectTasks.as_view()),
)

<强> serializers.py

from rest_framework import serializers
from models import Task

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = ('id', 'name')

<强> models.py

from django.db import models

class Task(models.Model):
    name = models.CharField(max_length=140, blank=False, null=False)

class Project(models.Model):
    name = models.CharField(max_length=140, blank=False, null=False)
    tasks = models.ManyToManyField(Task, related_name='projects')

然后你可以做以下事情:

  • GET projects / 12 / tasks / 将列出项目任务
  • POST项目/ 12 / tasks / 1 / ,它将任务1添加到项目12任务列表中(任务1必须已存在)
  • 删除项目/ 12 / tasks / 1 / ,这将从项目12任务列表中删除任务1

答案 2 :(得分:4)

现在支持此功能(我使用的是2.3.6版本,但可能会在之前介绍)。您可以直接在序列化程序中使用它:

class SongSerializer(serializers.ModelSerializer):
    class Meta:
        model = Song

class AlbumSerializer(serializers.ModelSerializer):
    songs = SongSerializer(many=True)

    class Meta:
        model = Album

希望有所帮助:)