I am doing a select_related() queryset to prevent hit database innecesarily. In my model I have:
class Item(models.Model)
user = models.ForeignKey(User, related_name='items')
name = models.CharField(max_length=255)
region = models.ForeignKey(Region, null = True, blank = True) #django-cities
country = models.ForeignKey(Country, null = True, blank = True) #django-cities
def get_ubicacion_name(self):
if self.region:
return self.region
else:
return self.country
class Activity(models.Model)
date = models.DateField()
item = models.ForeignKey(Item, related_name='items')
In my view:
ax = Activity.objects.select_related('item','item__region','item__country').all()[:40]
In my template:
{% for a in ax %}
{{ a.date }} - {{ a.get_ubicacion_name }}
{% endfor %}
debug tool bar displays 43 queries in 53.8开发者_如何学Go7ms because is hitting self.country so select_related('item','item_region','item_country') is not working for this def?
In shell:
>>> ac = ax[0]
>>> dir(ac)
...... '_item_cache', .......
>>> dir(ac.item)
...... '_country_cache','_region_cache',.......
thank you.
This should work. Can you try it in the shell? Get the ax queryset as you do in the view, then examine the first member with dir:
>>> ac = ax[0]
>>> dir(ac)
One of the attributes you should see is _item_cache, which is the way Django caches the ForeignKey lookup. Similarly, if you do dir(ac.item) you should see entries for _region_cache and _country_cache. If not, post the results here and hopefully we can debug further.
I think the issue is that the cities are also related to regions and countries:
class City(models.Model):
# snip
region = models.ForeignKey(Region)
# snip
def __unicode__(self):
return "%s, %s" % (self.name, self.region)
and when you call get_ubicacion_name() if the item has an associated city then the City.__unicode__() method gets called which generates at least one new query (to find the region) for each item.
I'd change your select_related as follows:
ax = Activity.objects.select_related(
'item','item__region__city__country','item__country'
).all()[:40]
I haven't tested this but I think it should work.
加载中,请稍侯......
精彩评论