在保存期间标记 django 模型实例以供以后处理

Flagging a django model instance during save for later processing

我 运行 遇到了使用标志标记模型实例以供将来处理的问题。我有一个 class:

class MyModel(models.Model):
    processed = models.BooleanField(default=False)
    changed = models.DateTimeField(auto_now=True)
    # More fields.

    def save(self):
        self.processed = False
        super().save(*args, **kwargs)

然后我有一个管理命令:

class Command(BaseCommand):

    def handle(self, *args: Any, **kwargs: Any) -> None:
        models = MyModel.objects.filter(processed=False).order_by("changed")[:200]
        for model in models:
            # Do some processing
            model.processed = True
            model.save()

现在,显然当模型被保存时,它只是将实例重新标记为未处理。

我是 django 的新手,所以我对模型生命周期和可用方法的了解非常有限。我一直在阅读文档,到目前为止还没有找到任何解决方案。

有什么办法可以解决这个问题吗?

解决这个问题的最好方法可能是添加一个参数来忽略标记:

class MyModel(models.Model):
    processed = models.BooleanField(default=False)
    changed = models.DateTimeField(auto_now=True)
    # More fields.

    def save(self, *args<strong>, unset_processed=True</strong>, **kwargs):
        if <strong>unset_processed</strong>:
            self.processed = False
        super().save(*args, **kwargs)

然后在您的基本命令中,我们可以使用:

class Command(BaseCommand):

    def handle(self, *args: Any, **kwargs: Any) -> None:
        models = MyModel.objects.filter(processed=False).order_by("changed")[:200]
        for model in models:
            # Do some processing
            model.processed = True
            model.save(<strong>unset_processed=False</strong>)

但是请注意,批量创建、更新等将绕过 调用模型.save(…)。因此,例如,如果您使用:

MyModel.objects.filter(pk__in=[1,4,2,5])<strong>.update(</strong>some_field=some_value<strong>)</strong>

例如不会调用.save(…)方法。 documentation on .update(…) [Django-doc] 例如指出:

Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals

(…)

If you want to update a bunch of records for a model that has a custom save() method, loop over them and call save(), like this:

for e in Entry.objects.filter(pub_date__year=2010):
    e.comments_on = False
    e.save()