You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向Django模型批量POST/PATCH JSON:API格式对象?

实现JSON:API规范的批量POST和PATCH功能(Django REST Framework JSON:API)

你已经基于Django REST Framework JSON:API搭好了基础的资源查询功能,要实现批量创建(POST)和批量更新(PATCH),需要调整序列化器和视图集,同时适配JSON:API的批量数据格式,下面是具体的修改步骤:


1. 调整Serializer,完善关系字段映射

你的现有Serializer用了__all__,但为了正确解析JSON:API格式的relationships数据,需要显式定义ResourceRelatedField,确保关系字段能正确关联到对应模型:

from rest_framework_json_api import serializers
from proposal.models import Organization, ProposalConfigurableFields, OptionalFieldsByOrganization
from rest_framework_json_api.relations import ResourceRelatedField

class OptionalFieldsByOrganizationSerializer(serializers.ModelSerializer):
    # 显式声明关系字段,匹配JSON:API的relationships结构
    organization = ResourceRelatedField(queryset=Organization.objects.all())
    configurable_fields = ResourceRelatedField(queryset=ProposalConfigurableFields.objects.all())

    class Meta:
        model = OptionalFieldsByOrganization
        fields = ['id', 'status', 'organization', 'configurable_fields']
        # 可选:如果需要返回关联资源的完整数据,可开启include配置
        # include = ['organization', 'configurable_fields']

2. 修改ViewSet,实现批量处理逻辑

Django REST Framework JSON:API本身支持批量操作,但需要在ViewSet中重写create和update方法,判断请求是否为批量格式并处理:

from sis_common.views import BaseViewSet
from proposal.models import OptionalFieldsByOrganization
from proposal.serializers.optional_fields_by_organization import OptionalFieldsByOrganizationSerializer
from rest_framework.response import Response
from rest_framework import status

class OptionalFieldsByOrganizationViewSet(BaseViewSet):
    queryset = OptionalFieldsByOrganization.objects.all().order_by('pk')
    serializer_class = OptionalFieldsByOrganizationSerializer

    def create(self, request, *args, **kwargs):
        # 判断是否为批量请求(data是数组格式)
        is_bulk = isinstance(request.data.get('data'), list)
        if is_bulk:
            serializers = []
            for item in request.data['data']:
                # 单条数据序列化验证
                serializer = self.get_serializer(data={'data': item})
                serializer.is_valid(raise_exception=True)
                self.perform_create(serializer)
                serializers.append(serializer)
            
            # 整理批量创建的响应数据
            response_data = [serializer.data for serializer in serializers]
            return Response({'data': response_data}, status=status.HTTP_201_CREATED)
        # 单条创建沿用父类逻辑
        return super().create(request, *args, **kwargs)

    def update(self, request, *args, **kwargs):
        # 判断是否为批量更新请求
        is_bulk = isinstance(request.data.get('data'), list)
        if is_bulk:
            updated_data = []
            for item in request.data['data']:
                # 根据id获取要更新的实例
                instance = self.get_queryset().get(pk=item['id'])
                # 部分更新(PATCH),partial=True允许只传修改的字段
                serializer = self.get_serializer(instance, data={'data': item}, partial=True)
                serializer.is_valid(raise_exception=True)
                self.perform_update(serializer)
                updated_data.append(serializer.data)
            
            return Response({'data': updated_data}, status=status.HTTP_200_OK)
        # 单条更新沿用父类逻辑
        return super().update(request, *args, **kwargs)

3. 关键补充配置

  • 唯一性约束:为避免同一个organization和configurable_fields重复创建,建议在模型的Meta中添加联合唯一约束:
    class Meta:
        permissions = (
            ('view_optionalfieldsbyorganization', 'Can view Optional Fields By Organization'),
            ('add_optionalfieldsbyorganization', 'Can add Optional Fields By Organization'),
            ('change_optionalfieldsbyorganization', 'Can change Optional Fields By Organization'),)
        unique_together = ('organization', 'configurable_fields')
    
  • 权限校验:确保你的BaseViewSet已经配置了对应的添加、修改权限,否则批量操作会被拦截。

测试示例

批量POST创建请求

用curl测试你提供的示例payload:

curl -X POST \
http://localhost:8000/v1/optionalfieldsbyorganizations \
-H 'Authorization: Basic YWRtaW46YWRtaW4xMjM=' \
-H 'Content-Type: application/vnd.api+json' \
-d '{
    "data": [
        {
            "type": "OptionalFieldsByOrganization",
            "attributes": { "status": 2 },
            "relationships": {
                "organization": { "data": { "type": "Organization", "id": "2" } },
                "configurable_fields": { "data": { "type": "ProposalConfigurableFields", "id": "2" } }
            }
        },{
            "type": "OptionalFieldsByOrganization",
            "attributes": { "status": 1 },
            "relationships": {
                "organization": { "data": { "type": "Organization", "id": "2" } },
                "configurable_fields": { "data": { "type": "ProposalConfigurableFields", "id": "3" } }
            }
        }
    ]
}'

批量PATCH更新请求

假设要更新id为1和2的记录:

curl -X PATCH \
http://localhost:8000/v1/optionalfieldsbyorganizations \
-H 'Authorization: Basic YWRtaW46YWRtaW4xMjM=' \
-H 'Content-Type: application/vnd.api+json' \
-d '{
    "data": [
        {
            "type": "OptionalFieldsByOrganization",
            "id": "1",
            "attributes": { "status": 0 }
        },{
            "type": "OptionalFieldsByOrganization",
            "id": "2",
            "attributes": { "status": 2 }
        }
    ]
}'

内容的提问来源于stack exchange,提问作者Aashish P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:19:56