我想弄清楚是否有可能设置一个类似Model.objects.values_list('id', 'related_model__ids')
的查询并返回类似[(1L, [2L, 6L]), (2L, [1L,]), (3L, [1L, 3L, 4L, 5L]), ...]
的内容。以下是一些细节:
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=32
和id=33
生成两个条目。当我对特定播放器(values_list
)进行id=31
查询时,我会得到我想要的位置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)
查询。
答案 0 :(得分:3)
是的,我希望也有一些分组查询方法。
我最近不得不使用高度嵌套的模型做类似的事情,以避免一些严重的数据库调用。我最终使用values()
来有效地获得我需要的所有值。然后,将所有内容拼接成纯Python中的字典。它的效率提高了几英里,但当然定制有其自身的维护缺点。
使用作者/书籍模型的要点:
# models.py
class Author(models.Model):
name = models.CharField()
class Book(models.Model):
name = models.CharField()
authors = models.ManyToManyField(Author)
然后在一个视图(或我的案例中的shell)中构建您可以传递给模板的字典:
>>> 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方法解决了这个问题。
希望这有帮助!