获取相关字段时减少查询开销

时间:2014-04-22 13:39:16

标签: django django-orm

我有一个带标签的简单博客应用。

class AbstractDate(models.Model):
     created = models.DateTimeField(auto_now_add=True)

     class Meta:
        abstract = True

class AbstractTitleData(AbstractDate):
    title = models.CharField(max_length=200)

    class Meta:
        abstract = True


class Post(AbstractTitleData):
     body = models.TextField()
     views = models.IntegerField(default=0)
     likes = models.IntegerField(default=0)
     picture = models.ImageField(upload_to='profile_images', blank=True)


    class Meta:
        ordering = ["-created"]

    def __unicode__(self):
        return self.title

class Tag(models.Model):
   slug = models.SlugField(max_length=15)
   post = models.ForeignKey(Post, related_name="tags") 

   def __unicode__(self):
       return self.slug

例如,在我的数据库中有两个帖子。在帖子A和帖子B中有标签' a'''' c'和' d'' e',' f'分别。为了减少对数据库的查询,我尝试使用extra()方法。

condition = 'blog_post.id = blog_tag.post_id'
p = Post.objects.all().extra(select={'t':'blog_tag.slug'},tables=["blog_tag"],where=[condition]) 

结果:

[<Post: A>, <Post: A>, <Post: A>, <Post: B>, <Post: B>, <Post: B>]
for post in p: print post.t
'a'
'b'
'c'
'd'
'e'
'f'

如何获得每个帖子的副本,其中所有标签都列在一个attr中,如下所示:

p =[<Post: A>, <Post: B>]
for post in p: print post.t
['a','b','c']
['d','e','f']

3 个答案:

答案 0 :(得分:1)

根本不会使用extra。而是使用prefetch_related在两个查询中获取帖子及其所有关联的标签:

p = Post.objects.all().prefetch_related('tag')

答案 1 :(得分:1)

我不确定您是否要在Tag模型中使用ForeignKey。在Django中,ForeignKey是多对一的,而你可能更喜欢many-to-many关系(意思是:一个帖子可以有多个标签,一个标签可以引用多个帖子)。

为了解决性能问题,我正在使用select_related

  

返回一个“跟随”外键关系的QuerySet,   在执行查询时选择其他相关对象数据。   这是一个性能助推器,导致单一更复杂   查询但意味着以后使用外键关系不需要   数据库查询。

答案 2 :(得分:0)

你试过django-taggit吗?它可能会让你的生活更轻松。只需将其插入即可。该文档包含一些您可能想要做的示例查询。