【问题标题】:POST json array and get response as json arrayPOST json 数组并以 json 数组的形式获取响应
【发布时间】:2017-04-26 16:48:26
【问题描述】:

我的客户正在向我发送一个带有 json-array 的 POST,并且正在等待包含所请求数据的完整详细信息的响应。我对单个请求和单个响应没有问题,但为了尽量减少开销,我想处理一个数组。

我的模型.py

class RoFile(models.Model):
    user = models.ForeignKey('auth.User', null=True)
    filename = models.CharField(max_length=120, null=True)
    deleted = models.BooleanField(default=False)
    info = models.CharField(max_length=120, null=True)
    md5check = models.CharField(max_length=120, null=True)

尝试我的序列化程序:

class RoFileSerializer(serializers.ModelSerializer):
    deleted = serializers.ReadOnlyField(required=False)
    user = serializers.ReadOnlyField(required=False)
    info = serializers.ReadOnlyField(required=False)

    class Meta:
        model = RoFile
        fields = (
            'filename', 'md5check', 'deleted', 'user', 'info',
        )

   def create(self, validated_data):
        return RoFile(**validated_data)

尝试我的观点:

@api_view(['POST'])
def rofile_detaillist(request, format=None):
    data = JSONParser().parse(request)
    serializer = RoFileSerializer(data=data, many=True)
    if serializer.is_valid():
        json_add = []
        for x in serializer.validated_data:
            try:
                rofile = RoFile.objects.filter(md5check=x['md5check'])
            except ObjectDoesNotExist:
                continue

            *invalid code here*

        return Response(jsonarraywithallinfos)
    else:
        return Resonse(status=status.HTTP_400_BAD_REQUEST)

另一个视图尝试:

class RoFileDetailList(viewsets.ModelViewSet):
    model = RoFile
    serializer_class = RoFileSerializer(many=True)

    def get_queryset(self):
         return Rofile.objects.filter(md5check=self.request.data['md5check'])

一个 POST 示例:

{"filename": "filename1.exe", "md5check": "f8541061779b1efc5c30c4783edfb8f8"},
{"filename": "filename2.exe", "md5check": "16cdac5eb0ec829c2e2c199488681f6e"}

我需要什么作为回复:

{"filename": "filename1.exe", "md5check": "f8541061779b1efc5c30c4783edfb8f8", user: "testuser1", deleted: "True", info: ""},
{"filename": "filename2.exe", "md5check": "16cdac5eb0ec829c2e2c199488681f6e", user: "testuser1", deleted: "False", info: ""}

对不起,无效的代码部分,但我已经尝试了这么多,所以我删除了那部分(不小心)。 谢谢!

编辑:

我不需要使用 POST 创建,我只需要检索额外的数据(模型的其余部分)。我不得不更改序列化程序中的创建函数,因为我不想创建条目,我只想从数据库中检索与 md5check 关联的数据。

感谢@zaphod100.10 我实际的序列化器:

class RoFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = RoFile
        fields = '__all__'
        read_only_fields = ('deleted',)

    def create(self, validated_data):
        return RoFile(**validated_data)

我的看法:

class RoFileListDetailApi(generics.ListCreateAPIView):
    serializer_class = RoFileSerializer

    def get_queryset(self):
        return RoFile.objects.filter(md5check=self.request.data['md5check'])

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=True)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_200_OK, headers=headers)

我的帖子:

{"filename": "filename1.exe", "md5check": "f8541061779b1efc5c30c4783edfb8f8"},
{"filename": "filename2.exe", "md5check": "16cdac5eb0ec829c2e2c199488681f6e"}

我的实际响应现在是一个列表,但只有我的 POST 数据,而不是来自 db 的真实数据:

{"filename": "filename1.exe", "md5check": "f8541061779b1efc5c30c4783edfb8f8", deleted: false, info: null, user: null},
{"filename": "filename2.exe", "md5check": "16cdac5eb0ec829c2e2c199488681f6e", deleted: false, info: null, user: null}

应该是:

{"filename": "filename1.exe", "md5check": "f8541061779b1efc5c30c4783edfb8f8", deleted: true, info: "some info", user: "usertest1"},
{"filename": "filename2.exe", "md5check": "16cdac5eb0ec829c2e2c199488681f6e", deleted: false, info: "some info2", user: "usertest2"}

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    使用这个:

    class RoFileSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = RoFile
            fields = '__all__'
            read_only_fields = ('deleted', 'user', 'info')
    
    class RoFileListCreateApi(generics.ListCreateAPIView):
        serializer_class = RoFileSerializer
    
        def get_queryset(self):
             return Rofile.objects.filter(md5check=self.request.data['md5check'])
    
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data, many=True)
            serializer.is_valid(raise_exception=True)
            # override perform_create or the serializers create method for custom create logic
            self.perform_create(serializer)
            # assign other fields to the objs and save again
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    

    您只需将 many=True 传递给序列化程序即可处理列表。

    覆盖通用视图中的 perform_create 方法或序列化程序的 create 方法以应用自定义创建逻辑。

    编辑:

    根据提供的新信息,我更改了创建方法。

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=True)
        serializer.is_valid(raise_exception=True)
        # don't create anything just insert required data
        for rof_data in serializer.data:
            md5check = rof_data['md5check']
            # code to retrieve data from db based on md5check
            ....
            # code to insert values in rof_data
            rof_data['user'] = user.username
            rof_data['deleted'] = deleted
            rof_data['info'] = info
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    

    【讨论】:

    • 谢谢,我不想创建它们,因为它们已经在数据库中了。我只需要进行查询即可获取附加数据。请查看我的编辑。
    • @bingobear 我昨天更新了答案。成功了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 2020-02-28
    • 1970-01-01
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多