- Author:
- zerok
- Posted:
- August 15, 2008
- Language:
- Python
- Version:
- .96
- Tags:
- foreignkey generic manager query tuning
- Score:
- 7 (after 7 ratings)
This is a simple manager that offers one additional method called relate
, which fetches generic foreign keys (as referenced by content_type
and object_id
fields) without requiring one additional query for each contained element.
Basically, when working with generic foreign keys (and esp. in the usecase of having something like a tumblelog where you use an additional model just to have a single sorting point of multiple other models), don't do something like result = StreamItem.objects.select_related()
but just fetch the content type with result = StreamItem.objects.select_related('content_type')
, otherwise you will end up with first one query for the list of StreamItems but then also with one additional query for each item contained in this resultset.
When you now combine the latter call with result = StreamItem.gfkmanager.relate(result)
, you will just get the one query for the item list + one query for each content type contained in this list (if the models have already been cached).
For further details, please read this post on my blog.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from django.db import models
class GFKManager(models.Manager):
def relate(self, qs):
model_map = {}
item_map = {}
for item in qs:
model_map.setdefault(item.content_type, {}) \
[item.object_id] = item.id
item_map[item.id] = item
for ct, items_ in model_map.items():
for o in ct.model_class().objects.select_related() \
.filter(id__in=items_.keys()).all():
item_map[items_[o.id]].content_object = o
return qs
|
More like this
- Automatically setup raw_id_fields ForeignKey & OneToOneField by agusmakmun 8 months ago
- Crispy Form by sourabhsinha396 8 months, 4 weeks ago
- ReadOnlySelect by mkoistinen 9 months, 1 week ago
- Verify events sent to your webhook endpoints by santos22 10 months, 1 week ago
- Django Language Middleware by agusmakmun 10 months, 2 weeks ago
Comments
Please login first before commenting.