4

私は、次のように動作し、次のようなもの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に対して複数のタプル、、およびの 2 つのエントリを生成します。特定のプレーヤー ( ) に対してクエリを実行すると、必要なポジション ID のリストが取得されます。idid=31id=32id=33values_listid=31

>>> 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])]

間違いなく、リスト内包表記は私が望む結果をもたらすでしょう。データベースへの複数の個別のクエリを避け、それぞれが aを実際のリストにlist(p.positions.values_list('id', flat=True))解決することを強制したかったのです。ValuesListQuerySetもちろん、解決を強制しなければ、リスト内包表記の結果に対する操作は、新しいp.positions.valuse_list('id', flat=True)クエリを実行するように見えます。

4

1 に答える 1

3

ええ、グループ化クエリメソッドもあればいいのにと思います。

私は最近、データベース呼び出しの障害を避けるために、高度にネストされたモデルで同様のことをしなければなりませんでした。values()結局、必要なすべての値を効率的に取得するために使用しました。次に、すべてを純粋な Python の辞書としてつなぎ合わせました。最終的にははるかに効率的になりましたが、もちろん、カスタマイズには独自のメンテナンスの欠点があります.

Author/Book モデルを使用した要点:

# 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 メソッドで問題を解決したかどうか聞いてみたいです。

お役に立てれば!

于 2013-10-27T23:09:05.217 に答える