3

I have the following models.py:

class BagOfApples(models.Model):
    quantity = models.PositiveSmallIntegerField(default = 0)

Let's create a “bag of apples” object and put an “apple” in it:

>>> from myapp import models
>>> 
>>> models.BagOfApples().save()
>>> 
>>> bag1 = models.BagOfApples.objects.get(pk = 1)
>>> bag2 = models.BagOfApples.objects.get(pk = 1)
>>> 
>>> bag1.quantity += 1
>>> bag1.save()
>>> 
>>> bag1.quantity
1
>>> bag2.quantity
0

Is there a way to automatically reload the data in the bag2 variable?

In my real-world application, things are a bit more complicated than that, and the same objects can be modified in different parts of the code after being retrieved by different database queries. This is not even intentional (for instance, this problem occurs to me because Django caches results for OneToOne or ForeignKey relationships).

It would be really helpful to have some kind of manager (maybe a middleware can do this?) that keeps track of the identical objects.

In this example, the manager would automatically detect that bag2 is actually bag1, and would not execute a second query but simply return bag1.

If there is no good way to do this, any other helpful tips on better application design would be appreciated.

alexpirine
  • 3,023
  • 1
  • 26
  • 41

1 Answers1

0

The key is to understand when your query is actually executed. The model object will not repeat the query each time you want to access one of its model fields.

To avoid keeping around objects with stale data, I would make sure to query when I actually need to data. In your example, I'd hold on to the information that you know is not going to change (the pk value), and do a get when you need the object with fresh values.

from myapp import models
models.BagOfApples().save()

bag1 = models.BagOfApples.objects.get(pk = 1)

bag1.quantity += 1
bag1.save()

print bag1.quantity  # will print 1

bag2 = models.BagOfApples.objects.get(pk = 1)
print bag2.quantity  # will print 1 too
Mathieu
  • 7,001
  • 2
  • 19
  • 16
  • 1
    Thanks Matt for the reply. My problem was that Django was caching a ForeignKey relationship, and I solved the issue by forcing Django to make a query each time the relationship was accessed. So instead of using `my_model = object.foreign_model` I now use `my_model = ForeignModel.objects.get(pk = object.foreign_model_id)`. This is exactly what your recommend (“… I would make sure to query when I actually need to data”). But still, it doesn't really answer my question. It would be nice to be able to benefit from the caching whenever possible while avoiding stale data. – alexpirine Aug 20 '13 at 18:20