现在Django支持DateRangeField,是否有一个' Pythonic'防止记录重叠日期范围的方法?
一个假设用例是预订系统,您不希望人们同时预订相同的资源。
class Booking(models.model):
# The resource to be reserved
resource = models.ForeignKey('Resource')
# When to reserve the resource
date_range = models.DateRangeField()
class Meta:
unique_together = ('resource', 'date_range',)
答案 0 :(得分:5)
我知道答案很旧,但是现在您可以在模型的元数据中创建一个约束,这将使Postgres可以解决此问题
from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
from django.db import models
from django.db.models import Q
class Room(models.Model):
number = models.IntegerField()
class Reservation(models.Model):
room = models.ForeignKey('Room', on_delete=models.CASCADE)
timespan = DateTimeRangeField()
cancelled = models.BooleanField(default=False)
class Meta:
constraints = [
ExclusionConstraint(
name='exclude_overlapping_reservations',
expressions=[
('timespan', RangeOperators.OVERLAPS),
('room', RangeOperators.EQUAL),
],
condition=Q(cancelled=False),
),
]
答案 1 :(得分:2)
您可以在模型full_clean
方法中进行检查,该方法在ModelForm验证期间会自动调用。如果您直接保存对象,则不会自动调用它。.这是Django验证的已知问题,您可能已经知道了!因此,如果要在保存对象的任何时间进行验证,则还必须重写模型save
的方法。
class Booking(models.model):
def full_clean(self, *args, **kwargs):
super(Booking, self).full_clean(*args, **kwargs)
o = Booking.objects.filter(date_range__overlap=self.date_range).exclude(pk=self.pk).first()
if o:
raise forms.ValidationError('Date Range overlaps with "%s"' % o)
# do not need to do this if you are only saving the object via a ModelForm, since the ModelForm calls FullClean.
def save(self):
self.full_clean()
super(Booking, self).save()