2013-10-27 55 views
3

我试图找出是否可能建立一个查询,其将采取行动像Model.objects.values_list('id', 'related_model__ids')和返回类似[(1L, [2L, 6L]), (2L, [1L,]), (3L, [1L, 3L, 4L, 5L]), ...]这里的一部分是一些细节:Django的:一个相关的模型值列表作为值列表查询

class Player(models.Model): 
    positions = models.ForeignKey(Position) 
    ... 

>>> # players 31, 32, 33 play multiple positions, and I want a result to be 
>>> # [(player.id, [a list of position.id for all positions]), ...] 

>>> Player.objects.filter(id__in=[31, 32, 33]).values_list('id', 'positions__id') 
[(31L, 13L), (31L, 7L), (32L, 13L), (32L, 8L), (33L, 13L), (33L, 7L)] 

这个values_list查询为相同的id值产生多个元组,id=31,id=32id=33两个条目。当我利用特定的球员(id=31)一个values_list查询,我得到我想要的位置ID列表:

>>> p31 = Player.objects.get(id=31) 
>>> position_ids = p31.positions.values_list('id', flat=True) 
>>> type(position_ids) 
<class 'django.db.models.query.ValuesListQuerySet'> 
>>> position_ids 
[13L, 7L] 
>>> 
>>> # I want [(31L, [13L, 7L]), (32L, [13L, 8L), (33L, [13L, 7L)] 
>>> # Without have to do something like a list comprehension: 
>>> # [(p.id, list(p.positions.values_list('id', flat=True)) 
>>> #  for p in Player.objects.filter(id__in=[31, 32, 33])] 

毫无疑问,一个列表解析会产生的结果,我想。我想避免多个个人查询到数据库,每个list(p.positions.values_list('id', flat=True))强制ValuesListQuerySet的分辨率成为一个实际列表。当然,如果我不强制解决方案,对列表理解结果的操作似乎会执行新的p.positions.valuse_list('id', flat=True)查询。

回答

3

是的,我希望有一些分组查询方法。

我最近不得不做一些类似的高度嵌套模型,以避免一些数据库调用的瘫痪。我最终使用了values()来有效地获得我需要的所有umm值。然后,将所有东西拼成一个纯Python的字典。它结束了数英里更高的效率,但当然定制有其自身的维护下降。

它的要点,用作者/预订模型:

# models.py 
class Author(models.Model): 
    name = models.CharField() 

class Book(models.Model): 
    name = models.CharField() 
    authors = models.ManyToManyField(Author) 

然后在视图(或在我的情况下,壳)构建可以传递给你的模板字典:

>>> authors = Author.objects.prefetch_related('book_set').values('id', 'book') 
>>> print authors 
    [{'book': 1, 'id': 1}, {'book': 2, 'id': 1}, {'book': 2, 'id': 2}] 
>>> author_dict = {} 
>>> for a in authors: 
    if a['id'] not in author_dict: 
     author_dict[a['id']] = set() 
    author_dict[a['id']].add(a['book']) 
>>> print author_dict 
    {1: set([1, 2]), 2: set([2])} 

不是你可能想要的答案,但它是我唯一想到的。我很想听听其他人是否用某种本地Django方法解决了这个问题。

希望这会有所帮助!

+0

你的回答反映了我实际工作的内容。我运行的搜索查询太多,很难打到数据库,所以我正在编写一个模型,它可以保存运行某些查询及其结果的手段。下一步是找出如何让自定义模型管理器检查查询结果是保存还是需要运行查询并保存结果。你看过用模型查询绑定你的字典吗? – Cole

+1

我没有。通常,当我不能再使用Django的语法(非SQL语句)优化我的查询时,是时候将Web服务器从数据库服务器分离到不同的机器上(无论如何,如果有资源,这是个好主意)。如果可能的话,它可以是更多的硬件或自定义SQL。另外请注意,在某些情况下,使用'prefetch_related'可能比'select_related'快得多。 – Fiver

+1

此外,忘了提及它,但有一个梦幻般的数据库调试器Django称为[django调试工具栏](https://github.com/django-debug-toolbar/django-debug-toolbar)。你可能已经在使用它了,但我想补充说,对于谁停下来。 – Fiver

相关问题