【问题标题】:Prevent DateRangeField overlap in Django model?防止 Django 模型中的 DateRangeField 重叠?
【发布时间】:2018-01-31 16:44:28
【问题描述】:

既然 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',)

【问题讨论】:

标签: python django postgresql django-models


【解决方案1】:

您可以在您的模型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()

【讨论】:

    【解决方案2】:

    我知道答案是旧的,但现在你可以在模型的元数据中创建一个约束,这将使 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),
                ),
            ]
    

    Postgress Coonstraints

    【讨论】:

    • 如果有多个房间怎么办 - 所以从 Reservation 到 Room 的关系是 ManyToMany ?
    猜你喜欢
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 2011-04-18
    相关资源
    最近更新 更多