Django ORM:选择相关集 [英] Django ORM: Selecting related set

查看:111
本文介绍了Django ORM:选择相关集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有两个模型:

  class Poll(models.Model):
category = models.CharField (uCategory,max_length = 64)
[...]

类选择(models.Model):
poll = models.ForeignKey(Poll)
[...]

给定一个Poll对象,我可以通过以下方式查询其选择:

  poll.choice_set.all()

但是,是否有一个实用功能来查询一组投票的所有选项?



实际上,我正在寻找类似于以下内容(不支持,我不寻求如何):

  polls = Poll.objects.filter( category ='foo')。select_related('choice_set')
在轮询中的投票:
print poll.choice_set.all()#这不应该在每次迭代执行SQL查询

我做了一个(丑陋的)功能来帮助我实现:



def $ {pre> def qbind(objects,target_na我的模型,field_name)
对象=列表(对象)
objects_dict = dict([object(object.id,object)对象中的对象])
为外部在model.objects。过滤器(** {field_name +'__in':objects_dict.keys()}):
id = getattr(foreign,field_name +'_id')
如果object_dict中的id:
object = object_dict [id]
if hasattr(object,target_name):
getattr(object,target_name).append(foreign)
else:
setattr(object,target_name,[foreign] )
返回对象

其用法如下:

  polls = Poll.objects.filter(category ='foo')
polls = qbind(polls,'choices',Choice,'poll')
#现在,轮询中的每个对象都有一个选择成员,其中包含选项列表。
#这是仅通过2个SQL查询实现的。

Django有没有提供更容易的东西?或者至少是一个更好的方式做同样的事情的代码片段。



通常如何处理这个问题?

解决方案

更新:自Django 1.4起,此功能内置: prefetch_related



首先回答:不要浪费时间写作直到你已经编写了一个工作的应用程序,对它进行了分析,并且证明了N个查询实际上是数据库和负载情况的性能问题。



但是也许你这样做了所以第二个答案:qbind()执行你需要做的,但如果打包在一个自定义的QuerySet子类中,它将更加惯用,并带有一个返回自定义QuerySet实例的Manager子类。理想情况下,您甚至可以将其通用和可重用于任何反向关系。那么你可以这样做:

  Poll.objects.filter(category ='foo')。fetch_reverse_relations('choices_set') 

有关Manager / QuerySet技术的示例,请参阅这个片段,它解决了类似的问题,但是对于通用外键的情况,而不是反向关系。将qbind()函数的内容与显示的结构组合在一起是一个非常好的解决方案。


Say I have 2 models:

class Poll(models.Model):
    category = models.CharField(u"Category", max_length = 64)
    [...]

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    [...]

Given a Poll object, I can query its choices with:

poll.choice_set.all()

But, is there a utility function to query all choices from a set of Poll?

Actually, I'm looking for something like the following (which is not supported, and I don't seek how it could be):

polls = Poll.objects.filter(category = 'foo').select_related('choice_set')
for poll in polls:
    print poll.choice_set.all() # this shouldn't perform a SQL query at each iteration

I made an (ugly) function to help me achieve that:

def qbind(objects, target_name, model, field_name):
    objects = list(objects)
    objects_dict = dict([(object.id, object) for object in objects])
    for foreign in model.objects.filter(**{field_name + '__in': objects_dict.keys()}):
        id = getattr(foreign, field_name + '_id')
        if id in objects_dict:
            object = objects_dict[id]
            if hasattr(object, target_name):
                getattr(object, target_name).append(foreign)
            else:
                setattr(object, target_name, [foreign])
    return objects

which is used as follow:

polls = Poll.objects.filter(category = 'foo')
polls = qbind(polls, 'choices', Choice, 'poll')
# Now, each object in polls have a 'choices' member with the list of choices.
# This was achieved with 2 SQL queries only.

Is there something easier already provided by Django? Or at least, a snippet doing the same thing in a better way.

How do you handle this problem usually?

解决方案

Update: Since Django 1.4, this feature is built in: see prefetch_related.

First answer: don't waste time writing something like qbind until you've already written a working application, profiled it, and demonstrated that N queries is actually a performance problem for your database and load scenarios.

But maybe you've done that. So second answer: qbind() does what you'll need to do, but it would be more idiomatic if packaged in a custom QuerySet subclass, with an accompanying Manager subclass that returns instances of the custom QuerySet. Ideally you could even make them generic and reusable for any reverse relation. Then you could do something like:

Poll.objects.filter(category='foo').fetch_reverse_relations('choices_set')

For an example of the Manager/QuerySet technique, see this snippet, which solves a similar problem but for the case of Generic Foreign Keys, not reverse relations. It wouldn't be too hard to combine the guts of your qbind() function with the structure shown there to make a really nice solution to your problem.

这篇关于Django ORM:选择相关集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆