Django对象不保存递归保存方法的所有迭代

时间:2017-03-30 20:33:18

标签: python django recursion

我在Django项目中有一个递归保存方法来创建多个日历事件实例;问题只是实际上似乎得到了保存的最后一个事件。我要么忽略了一些明显的东西,要么就是我不熟悉的Django巫术。

ETA:例如,如果我在一个月的第一个星期五有三个月的活动,那么只有第三个月会实际保存到数据库。

保存方法如下,相关功能如下:

def move_to_next_month(sent_date):
    temp_date = sent_date.replace(tzinfo=None)
    if temp_date.month != 12:
        temp_date = temp_date.replace(month=temp_date.month + 1, day=1)
        return temp_date
    else:
       temp_date = temp_date.replace(year=temp_date.year + 1, month=1, day=1)
        return temp_date

def date_checker(temp_date, day_of_week, week_of_month):
    if week_of_month == "first":
        return temp_date.weekday() == day_of_week and 0 < temp_date.day < 8
    if week_of_month == "second":
        return temp_date.weekday() == day_of_week and 7 < temp_date.day < 15
    if week_of_month == "third":
        return temp_date.weekday() == day_of_week and 14 < temp_date.day < 22
    if week_of_month == "fourth":
        return temp_date.weekday() == day_of_week and 21 < temp_date.day < 28

def save(self, *args, **kwargs):
    if not self.orig_title:
        self.orig_title = self.title
    if self.end_date is None:
        self.end_date = self.start_date
    tempSlug = slugify("%s %s %s" % (self.orig_title, self.start_date.strftime("%b %d %Y"), self.branch))
    self.slug = tempSlug
    if not self.pk:
        self.is_repeating = repeating_event_check(self)
        super(MonthlyRepeatingEvent, self).save(*args,**kwargs)
        if self.number_of_repetitions > 1:
            temp_start_date = move_to_next_month(self.start_date)
            temp_end_date = move_to_next_month(self.end_date)
            next_repetition = self
            next_repetition.pk = None
            next_repetition.end_date = temp_end_date
            next_repetition.start_date = temp_start_date
            next_repetition.number_of_repetitions = self.number_of_repetitions - 1
            while not date_checker(next_repetition.start_date,next_repetition.day_of_week,next_repetition.week_of_month):
                next_repetition.start_date = next_repetition.start_date.replace(tzinfo=None) + datetime.timedelta(days=1)
            while not date_checker(next_repetition.end_date,next_repetition.day_of_week,next_repetition.week_of_month):
                next_repetition.end_date = next_repetition.end_date.replace(tzinfo=None) + datetime.timedelta(days=1)
            next_slug = slugify("%s %s %s" % (next_repetition.orig_title, next_repetition.start_date.strftime("%b %d %Y"), next_repetition.branch))
            next = MonthlyRepeatingEvent.objects.filter(slug=next_slug).first()
            if next is not None:
                 next_repetition.pk = next.pk
                 next_repetition.slug = next_slug
                 next.delete()
                 next_repetition.save()
            else:
                 next_repetition.slug = next_slug
                 next_repetition.save()
    else:
        super(MonthlyRepeatingEvent, self).save(*args,**kwargs)
        if self.number_of_repetitions > 1:
            temp_start_date = move_to_next_month(self.start_date)
            temp_end_date = move_to_next_month(self.end_date)
            next_repetition = self
            next_repetition.pk = None
            next_repetition.end_date = temp_end_date
            next_repetition.start_date = temp_start_date
            next_repetition.number_of_repetitions = self.number_of_repetitions - 1
            while not date_checker(next_repetition.start_date,next_repetition.day_of_week,next_repetition.week_of_month):
                next_repetition.start_date = next_repetition.start_date.replace(tzinfo=None) + datetime.timedelta(days=1)
            while not date_checker(next_repetition.end_date,next_repetition.day_of_week,next_repetition.week_of_month):
                next_repetition.end_date = next_repetition.end_date.replace(tzinfo=None) + datetime.timedelta(days=1)
            next_slug = slugify("%s %s %s" % (next_repetition.orig_title, next_repetition.start_date.strftime("%b %d %Y"), next_repetition.branch))
            next = MonthlyRepeatingEvent.objects.filter(slug=next_slug).first()
            if next is not None:
                 next_repetition.pk = next.pk
                 next_repetition.slug = next_slug
                 next.delete()
                 next_repetition.save()
            else:
                 next_repetition.slug = next_slug
                 next_repetition.save()

ETA:更新后的代码低于

class MonthlyRepeatingEvent(Event):
    day_of_week = models.PositiveSmallIntegerField(default=0, choices=DAY_OPTIONS,blank=True,null=True)
    week_of_month = models.CharField(max_length=6, choices=WEEK_OPTIONS,blank=True,null=True)
    number_of_repetitions = models.PositiveSmallIntegerField(default=0)

def create_new_instance(instance):
    temp_start_date = move_to_next_month(instance.start_date)
    temp_end_date = move_to_next_month(instance.end_date)
    next_repetition = instance
    next_repetition.pk = None
    next_repetition.end_date = temp_end_date
    next_repetition.start_date = temp_start_date
    next_repetition.number_of_repetitions = instance.number_of_repetitions - 1
    while not date_checker(next_repetition.start_date,next_repetition.day_of_week,next_repetition.week_of_month):
        next_repetition.start_date = next_repetition.start_date.replace(tzinfo=None) + datetime.timedelta(days=1)
    while not date_checker(next_repetition.end_date,next_repetition.day_of_week,next_repetition.week_of_month):
        next_repetition.end_date = next_repetition.end_date.replace(tzinfo=None) + datetime.timedelta(days=1)
    next_slug = slugify("%s %s %s" % (next_repetition.orig_title, next_repetition.start_date.strftime("%b %d %Y"), next_repetition.branch))
    next = MonthlyRepeatingEvent.objects.filter(slug=next_slug).first()
    if next is not None:
        print("Delete function called.")
        next.delete()
    print("Save function called")   
    next_repetition.save()

@receiver(post_save, sender=MonthlyRepeatingEvent)
    def repeater(sender, instance, **kwargs):
    if instance.number_of_repetitions > 1:
        create_new_instance(instance)

1 个答案:

答案 0 :(得分:0)

首先 - 感谢评论者的提示 - 这有助于大大清理我的代码,从而帮助进行故障排除。

当我以简化形式复制重复函数时,它工作得很好,表明问题不在函数背后的逻辑中;简化对象与原始查询中的简单对象之间的主要区别是直接从models.Model继承的简化对象,原始查询对象使用基础Event对象的继承。

事实上,答案与继承和Django模型有关:

Making Queries|Django documentation|Django

当您从使用继承的类创建对象实例的副本时,您必须同时声明instance.pk = Noneinstance.id = None

因此,创建重复的功能将是:

def create_mre_new_instance(instance):
    temp_start_date = move_to_next_month(instance.start_date)
    temp_end_date = move_to_next_month(instance.end_date)
    next_repetition = instance
    next_repetition.start_date = temp_start_date
    next_repetition.end_date = temp_end_date
    next_repetition.number_of_repetitions = instance.number_of_repetitions - 1
    while not date_checker(next_repetition.start_date,next_repetition.day_of_week,next_repetition.week_of_month):
        next_repetition.start_date = next_repetition.start_date.replace(tzinfo=None) + datetime.timedelta(days=1)
    while not date_checker(next_repetition.end_date,next_repetition.day_of_week,next_repetition.week_of_month):
        next_repetition.end_date = next_repetition.end_date.replace(tzinfo=None) + datetime.timedelta(days=1)
    next_slug = slugify("%s %s %s" % (next_repetition.orig_title, next_repetition.start_date.strftime("%b %d %Y"), next_repetition.branch))
    next = MonthlyRepeatingEvent.objects.filter(slug=next_slug).first()
    if next is not None:
        next.delete()
    next_repetition.pk = None
    next_repetition.id = None
    next_repetition.save()