我在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)
答案 0 :(得分:0)
首先 - 感谢评论者的提示 - 这有助于大大清理我的代码,从而帮助进行故障排除。
当我以简化形式复制重复函数时,它工作得很好,表明问题不在函数背后的逻辑中;简化对象与原始查询中的简单对象之间的主要区别是直接从models.Model
继承的简化对象,原始查询对象使用基础Event
对象的继承。
事实上,答案与继承和Django模型有关:
Making Queries|Django documentation|Django
当您从使用继承的类创建对象实例的副本时,您必须同时声明instance.pk = None
和instance.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()