文档展示了一种包含PostgreSQL提供的数据完整性约束的方法,f.e。重叠区域的ExclusionConstraint。您可以从docs 这里中读取建议的解决方案。我想有一个预订系统,以确保一个“东西”(这里是一个教练/教师)不能在重叠的时间内两次预订。下面是文档中的第二个例子,其中的重叠标准是从现有字段派生的:
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”。
遗憾的是,我在文档中找不到任何关于这件事的东西,也找不到其他任何地方,所以任何提示都会提前得到赏识。
发布于 2020-12-22 11:02:44
因此,我想不可能重用约束来查询重叠事件,因为Django试图将一个对象保存到数据库中,至少从我可以找到的内容来看,它已经被清除了。无论如何,我当然会保留约束,因为这是对数据完整性的有力保证,但是为了获得我想要的功能,我在模型中添加了一个自定义管理器。
如下所示,它适合于“带预订的房间”模式(只需将培训师替换为Room),但是您需要根据需要修改它。
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__gte和end__lte),检查它是否有条目(exists()),并返回与之相反的布尔值,因为我想知道可用性,而不是"is_reserved“答案。
https://stackoverflow.com/questions/65390532
复制相似问题