Michel Laviron Michel Laviron -4 years ago 237
Python Question

Django refresh_from_db for ForeignKey

Is there a way to use refresh_from_db and automatically propagate it on ForeignKey ?


class TestItemModel(models.Model):
value = models.IntegerField(default=0)
relies_on_item = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True )


>>> end_product = TestItemModel(value=1)
>>> end_product.save()
>>> container_product = TestItemModel(value=10,relies_on_item=end_product)
>>> container_product.save()
>>> end_product.pk
>>> end_product_for_update=TestItemModel.objects.get(pk=12)
>>> end_product_for_update.value = 4
>>> end_product_for_update.save()
>>> container_product.relies_on_item.value
>>> container_product.refresh_from_db()
>>> container_product.relies_on_item.value

The value returned at this point is still the initial one. Is there an option to make refresh_from_db automatically cascade on elements referenced by ForeignKey?

It is possible to do it by explicitly using refresh_from_db on the referenced item - shown below. But I would like to only have to do refresh_from_db on container_product itself.

shell (continued):

>>> container_product.relies_on_item.refresh_from_db()
>>> container_product.relies_on_item.value

Answer Source

AFAIK In django, Till now refresh_from_db will not update data for relational fields.It only check whether relation is removed or not. But you can do like (as you did).

for i in container_product._meta.concrete_fields:
    if i.is_relation:
        getattr(container_product, i.name).refresh_from_db()

OR override refresh_from_db

class Mymodel(models.Model):
    def refresh_from_db(self, using=None, fields=None):
        super(Mymodel, self).refresh_from_db(using=None, fields=None)
        for i in self._meta.concrete_fields:
            if i.is_relation and getattr(self, i.name):
                getattr(self, i.name).refresh_from_db() 
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download