2016-05-21 2 views
6

Я пытаюсь группировать записи по характеру name поля каждой записи и ограничить элементы в каждой группе, вот что я придумал:Джанго объект группы по первому символу колонки

desired_letters = ['a','b','c',..,'z'] 
some_variable = {} 
for desired_letter in desired_letters: 
    some_variable += User.objects.all().order_by("name").filter(name__startswith=desired_letter)[:10] 

И запустил этот запрос в цикле for и изменил desired_letter на мою нужную букву, есть ли другой способ оптимизировать это решение и сделать его одним запросом вместо цикла for?

+0

Итак, как мы можем помочь? –

+0

@MosesKoledoye Мне нужно оптимизировать это и, возможно, сделать его одним запросом, используя функцию 'values ​​()' – samix73

+0

Эта группа не имеет никакого смысла? Если вы группируете первую букву имени каждого пользователя, вы получите только 26 записей, это то, что вы ищете? – e4c5

ответ

8

Из комментария в другой ответ:

Я был на самом деле искал способ реализовать Group By First Character в Джанго ОРМ

Я хотел бы сделать это в следующих 3 шага:

  1. Аннотировать каждую запись первой буквой поля name. Для этого можно использовать функцию Substr вместе с Lower

    from django.db.models.functions import Substr, Lower 
    qs = User.objects.annotate(fl_name=Lower(Substr('name', 1, 1))) 
    
  2. Следующая, группа все записи с первой буквы и получить количество идентификаторов. Это может быть сделано с помощью annotate with values:

    # since, we annotated each record we can use the first letter for grouping, and 
    # then get the count of ids for each group 
    from django.db.models import Count 
    qs = qs.values('fl_name').annotate(cnt_users=Count('id')) 
    
  3. Далее, вы можете заказать эту QuerySet с первой буквы:

    qs = qs.order_by('fl_name') 
    

Объединяя все это в одном заявлении:

from django.db.models.functions import Substr, Lower 
from django.db.models import Count 

qs = User.objects \ 
     .annotate(fl_name=Lower(Substr('name', 1, 1))) \ 
     .values('fl_name') \ 
     .annotate(cnt_users=Count('id')) \ 
     .order_by('fl_name') 

На e nd, ваш запрос будет выглядеть примерно так. Обратите внимание, что я преобразовал первый символ в нижний регистр при аннотации. Если вам это не нужно, вы можете удалить Lower функцию:

[{'fl_name': 'a', 'cnt_users': 12}, 
{'fl_name': 'b', 'cnt_users': 4}, 
... 
... 
{'fl_name': 'z', 'cnt_users': 3},] 

Если вам нужен словарь письма и посчитайте:

fl_count = dict(qs.values('fl_name', 'cnt_users')) 
# {'a': 12, 'b': 4, ........., 'z': 3} 
2

Первый заказ, а затем фильтрация является излишним и напрасно. вы должны заказывать только нужные вам данные. В противном случае вы заказываете все строки по имени , а затем фильтровать и нарезать то, что вам нужно.

Я хотел бы сделать:

User.objects.filter(name__startswith=desired_letter).order_by("name")[:10] 

и .all() был излишним.

+0

спасибо за ответ, как насчет группировки, есть ли другой способ, чем использовать для цикла? – samix73

+0

@ samix73 вы можете показать свою петлю? – doniyor

+0

Я отредактировал этот вопрос, я действительно искал способ реализовать [this] (http://stackoverflow.com/questions/666525/group-by-first-character) в django orm – samix73

Смежные вопросы