无法一次将多个相关对象发布到使用django rest框架创建的api

时间:2015-11-12 18:39:30

标签: django django-rest-framework

我正在制作一个ToDo应用,但很难获得api以允许用户通过一个api调用创建包含多个项目的新列表。每个列表都属于特定的"房间"。

我得到400 Bad Request。如果我离开' todo_items'关闭POST数据,它可以正常创建ToDoList对象。

另外,如果我删除" user"从CreateToDoItemSerializer的Meta fields属性,它将创建ToDoList对象和ToDoItem对象,但"内容"对于每个ToDoItem将是一个空字符串。在NewToDoListSerializer的create方法中,validated_data返回键#34; todo_items"的空OrderedDict()对象列表。我不知道该怎么做。

我的模特:

class Room(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    slug = models.SlugField(max_length=255, blank=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="rooms")

class ToDoList(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, blank=True)
    room = models.ForeignKey(Room, related_name="todo_lists")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="todo_lists")

class ToDoItem(models.Model):
    todo_list = models.ForeignKey(ToDoList, related_name="todo_items")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="replies")
    content = FroalaField(options={'placeholder': '''Just start writing...
                                                 Highlight any text to bring up the editor.'''})

我的序列化程序

class CreateTodoItemSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(many=False, read_only=False, queryset=User.objects.all())

    class Meta:
        model = ToDoItem
        fields = ['pk', 'user', 'content']

    def create(self, validated_data):
        reply = ToDo.objects.create(**validated_data)


class NewToDoListSerializer(serializers.ModelSerializer):
    room = serializers.PrimaryKeyRelatedField(many=False, read_only=False, queryset=Room.objects.all())
    user = UserSerializer(read_only=True)
    todo_items = CreateTodoItemSerializer(many=True, read_only=False)

    class Meta:
        model = ToDoList
        fields = ['pk', 'slug', 'title', 'user', 'room', 'todo_items']
        lookup_field = "slug"
        depth = 1

    def create(self, validated_data):
        todo_items_data = validated_data.pop('todo_items')
        todo_list = ToDoList.objects.create(**validated_data)
        for todo_item_data in todo_items_data:
            todo_item = ToDo.objects.create(user=todo_list.user, todo_list=todo_list, **todo_item_data)

我的观点(相关位):

class ToDoListViewSet(viewsets.ModelViewSet):
    queryset = ToDoList.objects.all()
    serializer_class = ToDoListSerializer
    authentication_classes = [TokenAuthentication, SessionAuthentication]
    permission_classes = [IsAuthenticated]
    renderer_classes = (renderers.TemplateHTMLRenderer, renderers.JSONRenderer, renderers.BrowsableAPIRenderer)
    template_name = "react_base.html"
    lookup_field = "slug"

def create(self, request, **kwargs):
    self.serializer_class = NewToDoListSerializer
    return super(ToDoListViewSet, self).create(request, **kwargs)

def perform_create(self, serializer):
    instance = serializer.save(user=self.request.user)

我发布的数据:

todoListTitle,todoItemContent,moreTodoItemContent都是字符串。 this.props.room.pk是一个整数。 this.props.csrfmiddlewaretoken是csrfmiddlewaretoken

var newToDoListData = {
        "room": this.props.room.pk,
        "title": todoListTitle,
        "todo_items": [{"content": todoItemContent}, {"content": moreTodoItemContent}],
        "csrfmiddlewaretoken": this.props.csrfmiddlewaretoken
    };

1 个答案:

答案 0 :(得分:1)

您需要在序列化程序中使todo_items为required = false。我不确定我明白你的第二个问题是什么。

class NewToDoListSerializer(serializers.ModelSerializer):
room = serializers.PrimaryKeyRelatedField(many=False, read_only=False, queryset=Room.objects.all())
user = UserSerializer(read_only=True)
todo_items = CreateTodoItemSerializer(many=True, required=False)

class Meta:
    model = ToDoList
    fields = ['pk', 'slug', 'title', 'user', 'room', 'todo_items']
    lookup_field = "slug"
    depth = 1

def create(self, validated_data):
    todo_items_data = validated_data.pop('todo_items')
    todo_list = ToDoList.objects.create(**validated_data)
    for todo_item_data in todo_items_data:
        todo_item = ToDo.objects.create(user=todo_list.user, todo_list=todo_list, **todo_item_data)