[英]Django - Selecting related set : how many times does it hit the database?
[英]MySQL database being hit too many times with django query
我正在使用django-favorites来提取用户所拥有的对象列表。 该应用程序有一个模型和一个经理
class FavoriteManager(models.Manager):
""" A Manager for Favorites
"""
def favorites_for_user(self, user):
""" Returns Favorites for a specific user
"""
return self.get_query_set().filter(user=user)
class Favorite(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
created_on = models.DateTimeField(auto_now_add=True)
objects = FavoriteManager()
class Meta:
verbose_name = _('favorite')
verbose_name_plural = _('favorites')
unique_together = (('user', 'content_type', 'object_id'),)
def __unicode__(self):
return "%s added %s as a favorite" % (self.user, self.content_object)
在我看来,我正在为用户拉扯最爱
from favorites.models import Favorite
def myfavorites(request):
item = Favorite.objects.favorites_for_user(user=request.user)
return render_to_response('myfavorites.html', {
'favorites':item
},
context_instance=RequestContext(request))
在我的模板中,我尝试获取收藏夹及其模型类型的列表:
{% for fave in favorites %}
{{ fave.content_type }}<br>
{{ fave.content_object }}<br><br>
{% endfor %}
但是使用django调试工具栏,我发现每次循环我都会访问数据库两次。 代码正在查询数据库中的content_type和content_object,以查找favorites对象中的每个fave。
如何优化代码以便数据被拉一次而无需对数据库进行多次点击以检索信息?
您可以在以下几种解决方
身份映射/缓存 ,使用内容类型和对象id来制作缓存模型的密钥,这里有一个例子,您可以将代码放在__getstate__
和__setstate__
并制作模板标签,这是您可以找到的最快的解决方案
使用JonhyCache , JohnyCache是一个用于查询 集的缓存框架,它与django缓存抽象一起使用。 我还没有亲自尝试过,因为这三个解决方案在我的项目中已经足够了。
缓存模板片段 ,减少hacky,它看起来像处理这种产生大量查询的问题的官方方式 ,并且当用户更改他的收藏夹时,您可以使缓存版本无效 。
请注意, select_related()不适用于泛型关系 。 这是因为相关对象可以在任何表中,因此无法在纯sql中进行正确的连接。 通用关系是Django的一个特性,而不是来自MySQL。
尝试使用select_related queryset方法。
像这样的东西应该做的伎俩:
item = Favorite.objects.favorites_for_user(user=request.user).select_related('content_type', 'content_object')
编辑:jpic正确地指出select_related不适用于'content_object',因为它是一个通用的外键。 不幸的是,没有很好的内置方法来处理这个问题,直到Django 1.4才会出现这种情况。 在此期间,请查看此SO问题以获取一些指示。 jpic在他的回答中也发布了一些很好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.