Django - Как фильтровать и возвращать данные по группам

У меня есть модель, в которой я хочу вернуть группу по атрибуту самого объекта. Предположим, что модель следующая:

class User():
    username = models.CharField(max_length=50, unique=True)
    group = models.CharField(max_length=20)

Позже в представлении я получу по группам всех пользователей:

group1 = User.objects.filter(group='1')
group2 = User.objects.filter(group='2')
group3 = User.objects.filter(group='3')

Но это вернет для каждой группы следующую структуру:

[{"username":"user1", "group":"1"}]
[{"username":"user2", "group":"2"}]
[{"username":"user3", "group":"3"}]

Как я могу получить следующую структуру (где группа является корнем) непосредственно из фильтра или как я могу объединить группы для достижения этого:

[
"1": [{"username":"user1","group":"1"}], 
"2": [{"username":"user2","group":"2"}], 
"3": [{"username":"user3","group":"3"}]
]

Я предполагаю, что у вас нет модели Group, только поле в модели User. Я не профессионал в Django, поэтому я не знаю никаких трюков Django, которые могли бы помочь вам достичь вашей цели - хотя я уверен, что Django ORM имеет некоторые функции, которые выполнят для вас запрос GROUP BY. Но почему бы вам не написать полностью питоновское решение, просто преобразовав коллекцию, которая у вас уже есть, в ту, которая вам нужна?

обновление после комментария

попробуйте что-нибудь вроде этого сценария:

from functools import reduce

users = [
    {'username': 'foo', 'group':'1'},
    {'username': 'bar', 'group':'2'},
    {'username': 'baz', 'group':'1'},
    {'username': 'asd', 'group':'2'},
    {'username': 'zxc', 'group':'3'},
    {'username': 'rty', 'group':'1'},
    {'username': 'fgh', 'group':'2'},
    {'username': 'vbn', 'group':'3'},
    {'username': 'vbn', 'group':'3'},
]

def reducer(acc,el):
    group = el['group']
    if not acc.get(group):
        acc[group]=[el.get('username')]
    else:
        acc[group].append(el['username'])
    return acc

print(reduce(reducer, users, {}))

В результате будет выведен результат, который выглядит близко к тому, что вы хотите:

{'1': ['foo', 'baz', 'rty'],
 '3': ['zxc', 'vbn', 'vbn'],
 '2': ['bar', 'asd', 'fgh']}
Вернуться на верх