Django DRF - ListCreateAPIView POST失败,深度= 2

时间:2017-03-26 03:06:45

标签: python django django-rest-framework

我有一个ListCreateAPIView用于显示联系人列表,以及创建使用此序列化程序的新联系人:

class ContactPostSerializer(serializers.ModelSerializer):
   class Meta:
     model = Contact
     exclude = ('id',)

对于POST新记录,我必须明确排除id,以便DRF不会抱怨空id。但是,为了使用此序列化程序列出记录,序列化程序不会返回ForeignKey字段中的对象。要获取这些对象,我添加depth = 2。所以现在序列化器看起来像这样:

class ContactPostSerializer(serializers.ModelSerializer):
   class Meta:
     model = Contact
     exclude = ('id',)
     depth = 2

但是,现在,使用depth = 2,我再也无法POST了。它再次抱怨null id值。

编辑:我应该补充一点,我提出的错误depth=2特定于外键对象的模型,而不是我正在创建的新记录。

我在这里缺少什么?

2 个答案:

答案 0 :(得分:0)

我发现问题是当序列化程序有depth=2时该部分不可写。这就是它失败的原因。另一件事是我不想更改我的URL,因此我只有/contacts/列表和创建。要做到这一点,我必须调整我的课程来处理答案。

以下是我提出的建议:

api.py

class ContactViewSet(viewsets.ModelViewSet):
  queryset = Contact.objects.all()
  serializer_class = ContactSerializer

  def create(self, request, *args, **kwargs):
    # If we're creating (POST) then we switch serializers to the one that doesn't include depth = 2
    serializer = ContactCreateSerializer(data = request.data)
    if serializer.is_valid():
      self.object = serializer.save()
      headers = self.get_success_headers(serializer.data)
      # Here we serialize the object with the proper depth = 2
      new_c = ContactSerializer(self.object)
      return Response(new_c.data, status = status.HTTP_201_CREATED, headers = headers)
    return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)

串行

class ContactCreateSerializer(serializers.ModelSerializer):
  class Meta:
    model = Contact
    exclude = ()

class ContactSerializer(serializers.ModelSerializer):
  class Meta:
    model = Contact
    exclude = ()
    depth = 2

相信这个SO答案帮我解决了问题:https://stackoverflow.com/a/26741062/717682

答案 1 :(得分:0)

比方说,调用您的视图的链接是/ example /。
如果要发布数据,则可以这样称呼:“ / example /”,
如果要获取数据(具有深度),可以这样称呼:“ / example /?depth =” yes“

您必须有两个串行器。一种带有深度,一种没有深度。

class ContactPOSTSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact
        exclude = ('id',)

class ContactGETSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact
        exclude = ('id',)
        depth = 2

因此,您的视图将是这样的:

class ExampleView(viewsets.ModelViewSet):
    serializer_class = ContactPOSTSerializer

    def list(self, request, *args, **kwargs):
        depth = self.request.query_params.get('depth', "")

        if (depth != "" and depth != "null"):
            serializer = ContactGETSerializer(context={'request': request})
            return Response(serializer.data)

        serializer = ContactPOSTSerializer(context={'request': request})
        return Response(serializer.data)

这可能不是最佳解决方案,但对我有用:)