【问题标题】:Django rest framwork - how to prevent 1062, "Duplicate entry"Django rest框架-如何防止1062,“重复条目”
【发布时间】:2022-01-19 16:36:58
【问题描述】:

在我的 Django 应用程序(仅限 DRF)中,我正在尝试创建一个新对象,其中一个字段设置如下:

 resource_name = models.CharField(verbose_name="Resource Name", blank=False, null=False, max_length=50, unique=True)

如果我现在尝试两次创建具有相同资源名称的对象,我总是会遇到以下异常:

django.db.utils.IntegrityError: (1062, "重复条目 'test_ressource123' 用于键 'resource_name'")

有什么好的解决方案可以适用于所有这些情况吗? 简单地做出对象已经存在的 API 响应会很棒,有点奇怪这还不是 DRF 的内置。我可以覆盖序列化程序的 def create 函数调用吗?欢迎任何好的建议。

【问题讨论】:

  • 您可以在您的序列化程序类中编写验证。
  • 我已经遇到过这个想法,但是如果你有很多模型,这有点烦人,因为你必须访问所有序列化程序的每个潜在的唯一字段,我希望这可以处理一些更通用的装饰器或这样可以获取实例,但这仍然不能解决何时检查哪个模型的问题。

标签: django django-rest-framework


【解决方案1】:

通常,您应该为每个模型开发一个序列化程序,以了解您如何使用每个模型。以后可以忘掉这个“通用”的解决方案,找个bug找很久。

不过,我看到了两种实现该行为的方法。

覆盖ModelViewSet

我们可以重新定义默认ModelViewSetcreate方法,然后从这个类继承你的ModelViewSets。像这样:

from django.db import IntegrityError
from rest_framework import viewsets
from rest_framework.exceptions import APIException
from rest_framework.status import HTTP_400_BAD_REQUEST

class SupressIntegrityErrorModelViewSet(viewsets.ModelViewSet):
    def create(self, request, *args, **kwargs):
        try:
            return super().create(request, *args, **kwargs)
        except IntegrityError as e:
            raise APIException(detail=str(e), code=HTTP_400_BAD_REQUEST)

更多信息here

DRFcustom exception handling

首先你需要创建一个custom_exception_handler 方法; DRF 文档建议在<application-directory>/utils.py

from django.http import HttpResponseBadRequest
from rest_framework.views import exception_handler

def custom_exception_handler(exc, context):
    if type(exc).__name__ == 'IntegrityError':
        return HttpResponseBadRequest(str(e))

    return exception_handler(exc, context)

那么你必须在你的settings.py中设置EXCEPTION_HANDLER

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

【讨论】:

    【解决方案2】:

    最好将UniqueValidator 添加到您的序列化程序中。

    resource_name = serializers.CharField(max_length=50, validators=[UniqueValidator(queryset=YourModel.objects.all())], requierd=False) 
    

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 2016-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2017-11-28
      • 2011-11-11
      相关资源
      最近更新 更多