使用 Django REST 框架进行批量 POST 时检查记录是不是存在

Posted

技术标签:

【中文标题】使用 Django REST 框架进行批量 POST 时检查记录是不是存在【英文标题】:Check if record exists when bulk POST'ing with Django REST Framework使用 Django REST 框架进行批量 POST 时检查记录是否存在 【发布时间】:2021-11-16 03:39:53 【问题描述】:

我有一个字典列表,我使用json.dumps() 将其解析为 JSON。我现在想使用 Django REST 框架将此数据发布到我的数据库。

# Example Data to POST
[
   
      "key_1":"data_1",
      "key_2":"data_2",

   ,
   
      "key_1":"data_1",
      "key_2":"data_2",
   ,
   
      "key_1":"data_3",
      "key_2":"data_4",
   
]

如果我们假设所有条目都是唯一的(上面的示例数据集并非如此),我们可以成功地批量发布此数据:

# models.py
class data(models.Model):
    key_1 = models.CharField(max_length=64, blank=True, null=True)
    key_2 = models.CharField(max_length=64, blank=True, null=True)

    class Meta:
        unique_together = (( "key_1", "key_2"))

# serializers.py
class dataSerializer(serializers.ModelSerializer):
    class Meta:
        model = data
        fields = '__all__'

# views.py
class dataViewSet(viewsets.ModelViewSet):
    queryset=data.objects.all()
    serializer_class=dataSerializer
    filter_backends=[DjangoFilterBackend]
    filterset_fields=['key_1', 'key_2']

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

# Initiating the POST request
api_url="localhost:8000/app/api/"
requests.post(
        f"api_urldata/", 
        data=my_json_serialised_data, 
        headers=headers
    )

但是,如果数据库中已经存在一些记录,这将失败(“字段必须是唯一的”)。

根据示例数据,列表中的条目偶尔会出现在数据库中,因此我希望避免 POST 重复(基于模型中的字段组合;我已将 unique_together 指定为明确说明哪些字段)。

在处理批量 POST 时,检查记录是否存在以及(如果存在)跳过它的最佳 DRF 方法是什么?我应该使用viewsets.ModelViewSet 并覆盖该类中的create() 方法吗?还是有更好的方法?我注意到there are several ways to create records in DRF,所以当我们处理上面示例中的一批数据时,我正在寻求最好的方法。

【问题讨论】:

ModelViewSet 并覆盖 create() 方法是一种过滤掉所需数据的方法,但我也想知道最好的方法。 【参考方案1】:

要解决这个问题,您可以使用custom list serializer 来获取经过验证的数据作为列表,然后支持使用bulk_create 批量创建data 对象。

此外,您可以使用 bulk_create 的 ignore_conflicts 忽略约束错误(如您的情况下的唯一约束):

在支持它的数据库上(除 Oracle 之外的所有数据库),将 ignore_conflicts 参数设置为 True 会告诉数据库忽略插入任何违反约束的行(例如重复唯一值)的失败。启用此参数将禁用在每个模型实例上设置主键(如果数据库通常支持它)。

所以总而言之,您可以执行以下操作:

class dataListSerializer(serializers.ListSerializer)
    def create(self, validated_data):
        return data.objects.bulk_create([
            data(**validated) for validated in validated_data
        ], ignore_conflicts=True)


class dataSerializer(serializers.ModelSerializer):
    class Meta:
        model = data
        fields = '__all__'
        list_serializer_class = dataListSerializer

many=True 在序列化程序中被标记时,dataListSerializer 的创建将被使用,而不是dataSerializer,后者将支持上述批量创建。

【讨论】:

以上是关于使用 Django REST 框架进行批量 POST 时检查记录是不是存在的主要内容,如果未能解决你的问题,请参考以下文章