python - 处理唯一一起错误的最佳方法 - Django 2.2?

标签 python django django-models django-rest-framework

我知道这个问题已经被问过很多次了,但我仍然找不到正确的解决方案。假设我有如下模型

class Student(models.Model):
    number = models.IntegerField()
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    class Meta:
       constraints = [
                     models.UniqueConstraint(fields=['department', 'number'])
                     ]

我的序列化程序如下所示。

class StudentModelSerializer(serializers.ModelSerializer):
     class Meta:
          model = Student
          fields = ("number",)

在这个模型中,departmentnumberunique,现在department是从传入的pk中获取的网址。我处理独特错误的方式如下。

class StudentViewSet(ModelViewSet):
     queryset = Student.objects.all()
     serializer_class = StudentModelSerializer

     def perform_create(self, serializer):
          department = Department.objects.get(pk=self.kwargs['pk'])
          serializer.save(department=department)

     def create(self, request, *args, **kwargs):
         try:
             return super().create(request, *args, **kwargs)
         except IntegrityError as err:
             if 'UNIQUE constraint' in err.message:
                raise ValidationError({
                    'number': 'Number field should be unique.'
                })
             else:
                raise IntegrityError(err)

如上所示,我调用了 super().create() 捕获异常,然后检查出现的 UNIQUE 消息,如果出现我再次引发验证错误,所以 rest framework 的异常处理程序 会处理它。如果不是我再次提出错误。

这种方法的问题是我正在检查消息 UNIQUE 的唯一错误,将来可能会改变。当然我可以将部门添加到 serializer contextvalidate before save,但这可能会导致 race condition,那么处理这种情况的最佳实践是什么?

最佳答案

更好的方法是将异常的 pgcode 与 psycopg2 错误代码进行比较:

from psycopg2 import errorcodes

class StudentViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def perform_create(self, serializer):
        department = Department.objects.get(pk=self.kwargs['pk'])
        serializer.save(department=department)

    def create(self, request, *args, **kwargs):
        try:
            return super().create(request, *args, **kwargs)
        except IntegrityError as err:
            if err.__cause__.pgcode == errorcodes.UNIQUE_VIOLATION and \
               "number" in err.args[0]
                raise ValidationError({
                    'number': 'Number field should be unique.'
                })
            raise

关于python - 处理唯一一起错误的最佳方法 - Django 2.2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55528622/

相关文章:

python - Scikit-image:无法导入名称 'label'

mac osx上的python位置

python - 带有 SubFactory 字段的 DjangoModelFactory 不创建新条目而是指向现有条目

MYSQL:想要将日期列设为NULL

python - Django - 注释按日期分组的不同值的 Count()

python - 如何对许多对象使用 bulk_create() 来执行 save() 操作

Django - 带有自定义非相关对象的 admin_order_field

Python装饰器不返回值

python - 从 BGR 到灰度的 OpenCV 颜色转换错误

javascript - django View - 502 错误网关