清除Django Admin或表单中的预期ExclutionConstraint IntegrityError

2024-06-24 13:31:46 发布

您现在位置:Python中文网/ 问答频道 /正文

这些文档展示了一种接受PostgreSQL提供的数据完整性约束的方法,例如重叠范围ExclusionConstraint。 您可以从文档here中阅读建议的解决方案。 我想有一个预约系统,确保一个“东西”(这里是一个培训师/老师)在一段重叠的时间内不会被预订两次。我将使用文档中的第二个示例,其中重叠标准来自现有字段:

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import (
    DateTimeRangeField,
    RangeBoundary,
    RangeOperators,
)
from django.db import models
from django.db.models import Func, Q


class TsTzRange(Func):
    function = 'TSTZRANGE'
    output_field = DateTimeRangeField()


class Reservation(models.Model):
    trainer = models.ForeignKey('Trainer', on_delete=models.CASCADE)
    start = models.DateTimeField()
    end = models.DateTimeField()
    cancelled = models.BooleanField(default=False)

    class Meta:
        constraints = [
            ExclusionConstraint(
                name='exclude_overlapping_reservations',
                expressions=(
                    (TsTzRange('start', 'end', RangeBoundary()), RangeOperators.OVERLAPS),
                    ('trainer', RangeOperators.EQUAL),
                ),
                condition=Q(cancelled=False),
            ),
        ]

因此,这对我来说很好,当试图保存无效范围时,我将得到预期的IntegrityError:

IntegrityError at /admin/trainer/trainingevent/add/

conflicting key value violates exclusion constraint "exclude_overlapping_reservations"
DETAIL:  Key (tstzrange(start, "end", '[)'::text), trainer_id)=(["2020-12-19 16:20:00+00","2020-12-19 16:55:00+00"), 1) conflicts with existing key (tstzrange(start, "end", '[)'::text), trainer_id)=(["2020-12-19 16:15:00+00","2020-12-19 16:45:00+00"), 1).

这就引出了我的问题: 如何验证字段,或者更确切地说,如何创建一个适当的clean()方法来验证输入,而不复制功能? 从我目前的角度来看,最好是要求PostgreSQL以某种方式进行检查,或者以某种方式将模型保存在try-catch块中

因此,在更一般的情况下,这个问题应该等同于“如何清理Django中的IntegrityError”

遗憾的是,我在文档中或其他任何地方都找不到与此相关的任何信息,因此,请提前向我提供任何提示和thx


Tags: django方法from文档importmodelspostgresqlcontrib
1条回答
网友
1楼 · 发布于 2024-06-24 13:31:46

因此,我想不可能重复使用约束来查询重叠事件,因为在Django试图将对象保存到数据库时,它已经被清理了,至少从我能找到的情况来看是这样的。 无论如何,我当然会让约束保持活动状态,因为这是对我的数据完整性的有力保证,但是为了获得我想要的功能,我已经在模型中添加了一个自定义管理器

如下所示,它符合“带预订的房间”模式(只需将培训师替换为房间),但您需要根据自己的需要对其进行修改

from django.db import models


class TrainingEventManager(models.Manager):
    def check_availability(self, trainer, start, end):
        return not (
            super()
            .get_queryset()
            .filter(trainer=trainer)
            .filter(start__gte=start)
            .filter(end__lte=end)
            .exists()
        )

它查询给定的日期时间范围(start__gteend__lte),检查它是否有条目(exists()),并返回布尔值,因为我想知道可用性而不是“保留”答案

相关问题 更多 >