Login

Per-Instance On-Model M2M Caching

Author:
bryanhelmig
Posted:
July 22, 2010
Language:
Python
Version:
1.2
Score:
2 (after 2 ratings)

If you are like me and you find yourself often using M2M fields for tons of other on-model methods, in templates, and views alike, try using this quick and dirty caching. I show the use of a "through" model for the m2m, but that is purely optional. For example, let's say we need to do several different things with our list of beads, the old way is...

# views.py
necklace = Necklace.objects.get(id=1)
bead = Bead.objects.get(id=1)

if bead in necklace.beads.all():
    # this bead is here!


# template necklace.html
{% for bead in necklace.beads.all %}
    <li>{{ bead }}</li>
{% endfor %}

...which would hit the database twice. Instead, we do this:

# views.py
necklace = Necklace.objects.get(id=1)
bead = Bead.objects.get(id=1)

if bead in necklace.get_beads():
    # this bead is here!


# template necklace.html
{% for bead in necklace.get_beads %}
    <li>{{ bead }}</li>
{% endfor %}

Which only does one hit on the database. While we could have easily set the m2m query to a variable and passed it to the template to do the same thing, the great thing is how you can build extra methods on the model that use the m2m field but share the cache with anyone down the line using the same m2m field.

I'm by no means an expert, so if there is something here I've done foolishly, let me know.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Necklace(models.Model):
    
    ### FIELDS ###
    
    ...

    beads = models.ManyToManyField(Bead, through="BeadSet", blank=True)
    
    ...
    
    ### CACHING METHODS ###
    
    def get_beadsets(self): # cache beadsets query to _beadsets
        try:
            _check = self._beadsets
        except:
            self._beadsets = BeadSet.objects.filter(necklace=self).select_related()
        return self._beadsets
    
    def get_beads(self): # cache beads query to _beads
        try:
            _check = self._beads
        except:
            self._beads = self.beads.all().select_related()
        return self._beads
    
    ...

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Klaidi (on July 22, 2010):

Nice one!

#

Please login first before commenting.