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

jas*_*son 9 django django-rest-framework

使用Django休息

下面是我如何使用serializer.py.

class ProfileSerializer(serializers.ModelSerializer):


    class Meta:
        model = Profile
        fields = ('id', 'name', 'active', 'type')
Run Code Online (Sandbox Code Playgroud)

类型是平面视图

然后我改变它,所以'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'')
Run Code Online (Sandbox Code Playgroud)

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

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

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

更新:

好的,我刚看过这个:

注意:嵌套序列化程序仅适用于只读表示形式,因为如果在更新实例时使用它们,则会出现模糊或不明显的行为.对于读写表示,您应始终使用FlatField子类之一来使用平面表示.

这是有道理的.所以我改成了....

type = serializers.PrimaryKeyRelatedField()
Run Code Online (Sandbox Code Playgroud)

这使它回到POST并工作,但这是一个耻辱,我不能用ID和名称代表'类型',这样对最终用户更有意义吗?

Rob*_*gar 13

对可写嵌套序列化程序的完全支持是一项正在进行工作,但与此同时,一种解决方案是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)
Run Code Online (Sandbox Code Playgroud)

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


小智 6

我在django-rest-framework中遇到了同样的问题,我已经创建了一个快速执行此操作的View,你可以在这个要点中找到它: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
Run Code Online (Sandbox Code Playgroud)

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()),
)
Run Code Online (Sandbox Code Playgroud)

serializers.py

from rest_framework import serializers
from models import Task

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = ('id', 'name')
Run Code Online (Sandbox Code Playgroud)

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')
Run Code Online (Sandbox Code Playgroud)

然后你可以做以下事情:

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


Rar*_*ina 5

现在支持(我使用的是 2.3.6 版,但它可能更早引入)。您可以像这样直接在序列化程序中使用它:

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

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

    class Meta:
        model = Album
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你 :)