Search code examples
djangoormmode

How can I check if this instance initing from database or it is new object


I have django model of a Task. In my website Tasks can be repeated and not repeated. So I override init method in this way:


    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)

But i have problem. How can I check if this instance initing from database or it is new object.


Solution

  • First, I am not sure I would have designed your tasks creation this way. The task object should scope itself and avoid having to deal with other tasks. Maybe, a task creator handling the option of creating repeated tasks might be more appropriate. It is just an opinion without knowing your context but it will avoid your issue without having to do any special stuff.

    This being said, as per Django documentation you should avoid the override of the init() method. It proposes 2 other approches. One of them involve overriding the Manager.

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

    It seams you which to encapsulate some logic from inside your object and in a oop perspective, this is debatable but understandable. However, in the django way of doing things, you should encapsulate this kind of logic in a specialized manager.

    I use this way of doing things to maintain fields such as created_at, updated_at, deleted_at and is_deleted in many of my entities and it works fine.

    I would not recommand creating objects from inside an object creation. If you want to do so, be sure here, your clone_task method does not include the repeated argument otherwise each repeated task will create many repeated task and you will end up with many duplicates.

    This being said, in a model, the following code will return True if object is newly created and False if comming from the db:

    self._state.adding
    

    Django documentation about _state