2015-03-31 3 views
0

Способ ограничения возвращаемого набора результатов из набора запросов Django выполняется с помощью среза массива. Например, чтобы получить первые 5 человек:Ограничение количества результатов из QuerySet Django без использования фрагмента

People.objects.all()[0:5] 

Или, чтобы получить их упорядоченный по имени:

People.objects.order_by(name)[0:5] 

Или заказать по названию, но только тех, кто старше 65:

People.objects.order_by(name).filter(age__gt=65)[0:5] 

Фактически только активность Я могу придумать по запросу, который не имеет, имеет функцию ограничения.

Что я хотел бы знать, это метод (внутренний, документированный или иной), который может быть вызван на QuerySet, который действует как предел или срез? Если нет, то как лучше всего это сделать?


Примечание:

  • Да, это, вероятно, плохая идея, нет, я не супер увлечен его реализации, но если бы было хорошей причины для того, чтобы быть сделано, не так ли?
  • Да, я знаю, что кусочки выполняются лениво, это не то, о чем я прошу.
  • This is not a duplicate of this question, как принято ответ говорит:

    ли results[:max_count] в целях, после .order_by().

+1

Что вы пытаетесь достичь или избежать, не используя кусочек? –

+0

Ничего особенного. Я искал какой-то код для библиотеки django, который мог бы только возвращать список, а не набор запросов, и возникла проблема с его срезанием, потому что ленивый аспект среза не имел значения, поскольку он сначала преобразовал весь запрос в список , –

+1

В соответствии с [документацией] (https://docs.djangoproject.com/en/1.7/topics/db/queries/#limiting-querysets) разрезание - единственный способ сделать это. – thefourtheye

ответ

1

Просмотр кода Django Querysets, its not as blackboxy, как это казалось

def __getitem__(self, k): 
    """ 
    Retrieves an item or slice from the set of results. 
    """ 

    # ... trimmed ... 

    if isinstance(k, slice): 
     qs = self._clone() 
     if k.start is not None: 
      start = int(k.start) 
     else: 
      start = None 
     if k.stop is not None: 
      stop = int(k.stop) 
     else: 
      stop = None 
     qs.query.set_limits(start, stop) 
     return list(qs)[::k.step] if k.step else qs 

    qs = self._clone() 
    qs.query.set_limits(k, k + 1) 
    return list(qs)[0] 

Ключом линия здесь:

qs.query.set_limits(start, stop) 

Причина ломтик ленив, потому что он просто берет start и stop и передает их другому методу.

Which corresponds to a call to the sql.Query object here:

def set_limits(self, low=None, high=None): 

Так что можно (хотя, вероятно, не рекомендуется), чтобы нарезать QuerySet так:

people = People.objects.order_by(name).filter(age__gt=65) # unevaluated 
people.query.set_limits(start, stop) # still unevaluated 
for person in people: # now its evaluated 
    person.do_the_thing() 
+0

Я до сих пор не вижу смысла в этом вопросе: если вы можете получить запрос на вызов 'set_limits', вы также можете нарезать его, и все ограничения на то, что вы можете сделать для набора запросов после нарезки, также будут применяться после вызова 'set_limits'. Может быть, если вы изучаете реализацию запросов в исследовательских целях? –

+0

Это был очень академический вопрос. Мне было любопытно, можно ли это сделать. –

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