【问题标题】:Override save in Django causing infinite recursion error在 Django 中覆盖保存导致无限递归错误
【发布时间】:2019-02-24 03:23:33
【问题描述】:

(Django 2.0、Python 3.6、Django Rest Framework 3.8)

我正在尝试覆盖 Django 的 save() 方法以在创建单个实例时发布多个实例。我有一个循环可以更改我保存为随机生成的字符串的unique_id,以及通过另一个名为onDay() 的函数更新的日期时间值。

我的想法是,如果我每次循环时都更改unique_id,Django 会将实例保存为数据库中的新实例。但是,当我运行它时,我不断返回一个无限递归错误。当我用pdb.set_trace() 检查它时,一切都按预期进行,直到我在for 循环中达到save() 值。一旦发生这种情况,我就会回到if self.recurrent_type == "WEEKLY":这一行。

我以类似的方式(不循环)使用super() 来覆盖单独模型的save() 函数,并且它按预期工作。我认为我对 super() 函数有一些误解。

这是我目前所拥有的:

覆盖 save()

def save(self, *args, **kwargs):
        if not self.pk:  # if there is not yet a pk for it
            # import pdb; pdb.set_trace()
            if self.recurrent_type == "WEEKLY":
                LIST_OF_DAYS = self.days_if_recurring["days"]
                HOW_MANY_DAYS_FOR_ONE_WEEK = len(LIST_OF_DAYS)
                REPEATS = HOW_MANY_DAYS_FOR_ONE_WEEK * self.number_of_times_recurring
                RESET_COUNTER = 0
                for i in range(REPEATS):
                    self.id = ''.join(random.choices(string.ascii_letters, k=30))
                    self.calendarydays = onDay(self.calendarydays, LIST_OF_DAYS[RESET_COUNTER])
                    if RESET_COUNTER == HOW_MANY_DAYS_FOR_ONE_WEEK - 1:
                        RESET_COUNTER = 0
                    self.save()
            else:
                self.id = ''.join(random.choices(string.ascii_letters, k=30))
                self.save()
        return super(Bookings, self).save(*args, **kwargs)

onDay()

def onDay(date, day):  # this function finds next day of week, and skips ahead one week if today's time has already passed
    utc = pytz.UTC
    check_right_now = utc.localize(datetime.datetime.now())
    if check_right_now > date:
        forward_day = date + datetime.timedelta(days=(day - date.weekday() + 7) % 7) + datetime.timedelta(days=7)
    else:
        forward_day = date + datetime.timedelta(days=(day - date.weekday() + 7) % 7)
    return forward_day

与往常一样,非常感谢任何帮助。

【问题讨论】:

  • 您在if self.recurrent_type == "WEEKLY" 中写入self.save() .save() 函数,因此您在其定义中调用该函数。由于self.recurrent_type 永远不会改变(也不会改变其他决定循环的参数),这确实会导致无限递归。
  • 我明白了,感谢@WillemVanOnsem 的输入,你知道我能做些什么来解决这个问题吗?我完全不知所措
  • 尝试删除self.save(),你在if self.recurrent_type == "WEEKLY"和它的else中有那个。
  • 您应该调用super(Bookings, self).save(*args, **kwargs) 而不是self.save()。超级保存将调用 django 的实际模型保存,这是您想要的。调用self.save() 只会调用您覆盖的保存,它不会在数据库中执行任何操作。但是,是的,@AamirAdnan 所说的应该可以解决您的问题。
  • 感谢大家的帮助!我最终使用了@bdbd 提供的解决方案(您能否将您的解决方案作为答案发布,以便我接受?)。除了避免无限递归之外,我还犯了以下错误:(1)将变量保存为self.id,而它们应该是self.unique_id(2)我没有增加我的计数器变量RESET_COUNTER(3)我应该在底部返回None,以避免重复保存unique_ids。现在一切正常。

标签: python django django-models django-rest-framework


【解决方案1】:

您应该调用super(Bookings, self).save(*args, **kwargs) 而不是self.save()。超级保存将调用 django 的实际模型保存,这是您想要的。调用self.save() 只会调用您覆盖的保存,它不会在数据库中执行任何操作。但是,是的,@AamirAdnan 所说的应该可以解决您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2018-05-01
    • 1970-01-01
    • 2012-07-20
    • 2018-07-21
    • 1970-01-01
    • 2012-09-04
    相关资源
    最近更新 更多