# Avoid post\_init duplicate queries

**URL:** <https://forum.djangoproject.com/t/avoid-post-init-duplicate-queries/28431>\
**Category:** Using the ORM\
**Created:** [February 26, 2024, 8:15am UTC](https://forum.djangoproject.com/t/avoid-post-init-duplicate-queries/28431 "2024-02-26T08:15:57Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![miyou995](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/miyou995/32/13731_2.png) [@miyou995](https://forum.djangoproject.com/u/miyou995)\
**Post date:** [February 26, 2024, 8:15am UTC](https://forum.djangoproject.com/t/avoid-post-init-duplicate-queries/28431/1 "2024-02-26T08:15:57Z")

</div>

HI. It’s very easy to track and manage changes of a Model instance using the `post_init` signal in Django.

As shown in the code below, I want to achieve the following behavior:

Whenever a product’s category changes, all associated `ProductSpecs` objects should be removed.  
BTW there isn’t a many-to-many relationship between `Product` and `ProductSpecs`.

```auto
@receiver(post_init , sender=Product)
def set_old_category(sender, instance, **kwargs):
    instance.old_category = instance.category

@receiver(post_save, sender=Product)
def reference_product_signal(sender, instance, created, **kwargs):
    if instance.category != instance.old_category:
        ProductSpecs.objects.filter(product=instance, key__category=instance.old_category).delete()

```

The provided code do its job, but it generates duplicate queries each time it see a product on a page.

My question is: **How can I avoid these duplicate queries?**

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [February 26, 2024, 12:46pm UTC](https://forum.djangoproject.com/t/avoid-post-init-duplicate-queries/28431/2 "2024-02-26T12:46:46Z")

</div>

Don’t use signals for this.

For tracking a change to a model, create a [`from_db`](https://docs.djangoproject.com/en/5.0/ref/models/instances/#customizing-model-loading) method in your model to create the copy of the existing values.

On handling the removal of the (unrelated) ProductSpecs, do this in the save method of the model. However, regardless of how you do the delete, you’re going to do an extra query - [that’s by design](https://docs.djangoproject.com/en/5.0/topics/db/queries/#deleting-objects), and it’s nothing to worry about.

---

<div class="post-metadata">

**Author:** ![miyou995](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/miyou995/32/13731_2.png) [@miyou995](https://forum.djangoproject.com/u/miyou995)\
**Post date:** [February 27, 2024, 7:43am UTC](https://forum.djangoproject.com/t/avoid-post-init-duplicate-queries/28431/3 "2024-02-27T07:43:20Z")

</div>

AMAZING!!!  
Thank you very much @KenWhitesell  
its very smooth… the working code

```auto
    @classmethod
    def from_db(cls, db, field_names, values):
        if len(values) != len(cls._meta.concrete_fields):
            values = list(values)
            values.reverse()
            values = [
                values.pop() if f.attname in field_names else DEFERRED
                for f in cls._meta.concrete_fields
            ]
        instance = cls(*values)
        instance._state.adding = False
        instance._state.db = db
        instance._loaded_values = dict(
            zip(field_names, (value for value in values if value is not DEFERRED))
        )
        return instance
    
    def save(self, *args, **kwargs):
        if not self._state.adding and (
            self.category_id != self._loaded_values["category_id"]
        ):
            ProductSpecs.objects.filter(product=self, key __category__ id=self._loaded_values["category_id"]).delete()
        super(Product, self).save(*args, **kwargs)

```
