Yura Khkyan
Yura Khkyan

Reputation: 111

Group queryset by related field values

I have following models structure:

class Chapter:
    name = ...


class Atom:
    name = ...
    chapter = FK(Chapter)


class Question:
    title = ...
    atom = FK(Atom)

I want to get all Questions related to Chapter, grouped by Atoms in this chapter.

How to do it with many queries I know:

atoms = Question.objects.filter(atom__chapter__id=1).values_list("atom", flat=True).distinct()
result = {}
for atom in atoms:
    result["atom"] = Question.objects.filter(atom__id=atom)

I suppose that it could be done with one query using annotate, Subquery and other Django's staff. Is this possible?

Upvotes: 1

Views: 262

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

You can fetch this in one query, but you need to do the grappig yourself:

from itertools import groupby
from operator import attrgetter

questions = Question.objects.filter(
    atom__chapter_id=1
).order_by('atom')

result = {
    k: list(vs)
    for k, vs in groupby(questions, attrgetter('atom_id'))
}

Here result is a dictionary that maps the primary keys of atom_ids on a list of Question objects with that atom_id.

Upvotes: 3

Related Questions