如何避免Django模型中的日期重叠?

时间:2015-03-23 07:07:20

标签: python django datetime django-models

我有一个模特:

class Dimension_Item(models.Model):
    uq_dimension_item_id = MyCharField(max_length=1024, primary_key=True)
    dimension_id = MyCharField(max_length=1024)
    dimension_item_id = MyCharField(max_length=100)
    name = MyCharField(max_length=255)
    description = MyCharField(max_length=512, null = True)
    start_date = models.DateField(default=date(1,1,1))
    end_date = models.DateField(default=date(9999,12,31))

用于向模型添加信息的功能:

def addRows(in_args):
    rq = in_args[0]
    pk_l=[]
    rows = rq['rows']
    if type(rows).__name__ == 'dict':
        dim = Dimension_Item(
                        name=rows['name'],
                        start_date=rows['start_date'],
                        end_date=rows['end_date']
        )
        dim.save()
        pk_l.append(dim.dimension_id)
    elif type(rows).__name__ == 'list':
        for i in rows:
            dim = Dimension_Item(
                        name=rows['name'],
                        start_date=rows['start_date'],
                        end_date=rows['end_date']
            )
            dim.save()
            pk_l.append(dim.dimension_id)
    else:
        pass
    return getRows(in_args, pk_l)
    # return "success add row"
clauses.addMethod(addRows)

和修改模型项的功能:

def modifyRows(in_args):
    pk_l=[]
    rq = in_args[0]
    rows = rq['rows']
    if type(rows).__name__ == 'dict':
        dim = Dimension_Item.objects.get(pk=rows['pk'])
        for attr in rows:
            if attr!='pk':
                try:
                    setattr(dim, attr, rows[attr])
                except KeyError:
                    pass
        dim.save()
        pk_l.append(dim.dimension_id)
    elif type(rows).__name__ == 'list':
        for i in rows:
            dim = Dimension_Item.objects.get(pk=i['pk'])
            for attr in i:
                if i!='pk':
                    try:
                        setattr(dim, attr, i[attr])
                    except KeyError:
                        pass
            dim.save()
            pk_l.append(dim.dimension_id)
    else:
        pass
    return getRows(in_args, pk_l)
    # return "success modify"
clauses.addMethod(modifyRows)

我应该检查start_date和end_date字段是否与数据库中的其他记录不重叠。

例如,我输入:2.02.1988-3.07.1989。如果我已经拥有2.07.1989 - 3.08.1990的记录,我必须抛出关于日期重叠的异常。

我能做得更好吗?

2 个答案:

答案 0 :(得分:1)

我会覆盖save()模型的Dimension_Item方法。

在自定义save()方法中,您可以检查重叠日期。如果一切正常,请创建对象。如果没有,只返回任何内容(或引发错误。)

Django文档解释说它非常好:https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods

以下是一些(未经测试的)代码,可帮助您入门:

class Dimension_Item(models.Model):
    start_date = models.DateField(default=date(1,1,1))
    end_date = models.DateField(default=date(9999,12,31))

    def save(self, *args, **kwargs):
        # get number of items that have an overlapping start date
        dimension_items_overlapping_start = Dimension_Item.objects.filter(start_date__gte=self.start_date, start_date__lte=self.end_date).count()

        # get number of items that have an overlapping end date
        dimension_items_overlapping_end = Dimension_Item.objects.filter(end_date__gte=self.start_date, end_date__lte=self.end_date).count()

        overlapping_dimension_items_present = dimension_items_overlapping_start > 0 or dimension_items_overlapping_end > 0

        if overlapping_dimension_items_present:
            return 
        else:
            super(Dimension_Item, self).save(*args, **kwargs) # Call the "real" save() method.

答案 1 :(得分:0)

class Dimension_Item(models.Model):
    start_date = models.DateField(default=date(1,1,1))
    end_date = models.DateField(default=date(9999,12,31))

    def save(self, *args, **kwargs):
        # check for items that have an overlapping start date
        dimension_items_overlapping_start = Dimension_Item.objects.filter(start_date__gte=self.start_date, start_date__lte=self.end_date).exists()

        # check for items that have an overlapping end date
        dimension_items_overlapping_end = Dimension_Item.objects.filter(end_date__gte=self.start_date, end_date__lte=self.end_date).exists()

        # check for items that envelope this item
        dimension_items_enveloping = Dimension_Item.objects.filter(start_date__lte=self.start_date, end_date__gte=self.end_date).exists()

        overlapping_dimension_items_present = dimension_items_overlapping_start or dimension_items_overlapping_end or dimenstion_items_enveloping

        if overlapping_dimension_items_present:
            return 
        else:
            super(Dimension_Item, self).save(*args, **kwargs) # Call the "real" save() method.