使用 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 时检查记录是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django Rest 框架进行 JWT 令牌身份验证

使用 django rest 框架进行单点登录服务的任何可能方式?

使用 Django REST 框架进行 JWT 身份验证

是否可以在 django rest 框架序列化程序中使用重用 django 表单进行验证?

通过对用户进行身份验证,使用 Django REST 框架下载文件

使用 Django Rest Framework 的 ListSerializer 批量创建