如何检查此实例是从数据库启动还是新对象

问题描述

我有一个任务的 Django 模型。在我的网站中,任务可以重复,也可以不重复。所以我以这种方式覆盖了 init 方法


    def __init__(self,*args,**kwargs):
        """Init new Task
        :param period - timedelta object. How often should task be repeated
        :param repeated - if true task will be repeated
        :param end_date - datetime until which tasks will be repeated or it will be repeated for 10 years
        """
        if not self.from_database() # I don't Now how to do it
            if kwargs.get("repeated"):
                period = kwargs["period"]
                end_date = kwargs["end_date"] or kwargs["date_time"] + TEN_YEARS
                base_task = self
                date = base_task.date_time + period
                with transaction.atomic():
                    while date <= end_date:
                        base_task.clone_task(date)
                        date += period
            try:
                del kwargs["repeated"]
                del kwargs["period"]
                del kwargs["end_date"]
            except KeyError:
                pass
        super().__init__(*args,**kwargs)

但是我有问题。如何检查此实例是从数据库初始化还是新对象。

解决方法

首先,我不确定我是否会以这种方式设计您的任务创建。任务对象应该限定自身的范围并避免处理其他任务。也许,处理创建重复任务的选项的任务创建者可能更合适。这只是一个不知道您的上下文的意见,但它可以避免您的问题,而无需做任何特殊的事情。

话虽如此,根据 Django 文档,您应该避免覆盖 init() 方法。它提出了另外两种方法。其中之一涉及覆盖管理器。

https://docs.djangoproject.com/en/3.2/ref/models/instances/

它让你从对象内部封装一些逻辑,从 oop 的角度来看,这是有争议的,但可以理解。但是,在django的做事方式中,你应该把这种逻辑封装在一个专门的管理器中。

我使用这种处理方式在我的许多实体中维护诸如 created_at、updated_at、deleted_at 和 is_deleted 之类的字段,并且效果很好。

我不建议从对象创建内部创建对象。如果你想这样做,请确保在这里,你的 clone_task 方法不包含重复参数,否则每个重复的任务都会创建许多重复的任务,你最终会得到许多重复。