django - как это сделать с kwargs

Мне интересно, когда я касаюсь базы данных при выполнении запросов. точнее, когда выполняется запрос:

у меня есть этот kwargs dic:

kwargs = {'name__startswith':'somename','color__iexact':'somecolor'}

но только для name__startswith запроса мне нужно distinct(). а не для color__iexact.

Я подумал, что я бы установил для name__startswith цикл distinct() in следующим образом:

for q in kwargs: 
  if q == 'name__startswith':
    Thing.objects.filter(name__startswith=somename).distinct('id')

а затем запросить все динамически:

allthings = Thing.objects.filter(**kwargs)

но это как-то неправильно, я, кажется, делаю здесь две разные вещи..

как я могу сделать эти два запроса динамически?


person doniyor    schedule 21.05.2013    source источник


Ответы (2)


наборы запросов django являются ленивыми, поэтому запросы не оцениваются , пока вы не используете данные .

allthings = Thing.objects.filter(**kwargs)

if 'name__startswith' in kwargs:
  allthings = allthings.distinct('id')   

Никакие запросы не должны выполняться выше, пока вы фактически не используете данные. Это отлично подходит для фильтрации запросов, как вы хотите сделать


Из документов:

QuerySets ленивы — процесс создания QuerySet не связан с какой-либо работой с базой данных. Вы можете складывать фильтры вместе в течение всего дня, и Django фактически не будет выполнять запрос, пока QuerySet не будет оценен. Взгляните на этот пример:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

Хотя это выглядит как три обращения к базе данных, на самом деле обращение к базе данных происходит только один раз, в последней строке (print(q)). Как правило, результаты QuerySet не извлекаются из базы данных до тех пор, пока вы не «запросите» их. Когда вы это сделаете, QuerySet оценивается путем доступа к базе данных. Дополнительные сведения о том, когда именно выполняется оценка, см. в разделе Когда оцениваются наборы запросов.

person dm03514    schedule 21.05.2013
comment
спасибо, чувак, я решил distinct по всем запросам, что ничего не повредит. все равно спасибо за помощь - person doniyor; 21.05.2013
comment
Использование distinct может значительно замедлить ваш запрос: stackoverflow.com/questions/1977739/ - person Bernhard Vallant; 21.05.2013

Вы можете использовать модели.Q для создания динамических запросов в django.

query = models.Q(name__startswith=somename)

query &= models.Q('color__iexact':'somecolor')

all_things = Thing.objects.filter(query).distinct('name')

Также прочитайте Динамическое построение запросов фильтра Django с аргументами и кварги

person Pratik Mandrekar    schedule 21.05.2013
comment
но ты distinct делаешь еще и для color__iexact, мне нужно еще и для name__startswith - person doniyor; 21.05.2013
comment
Нет, отличие принимает имя столбца, и вы можете просто указать столбец, для которого вы хотите иметь отличие. Обновлен мой ответ, чтобы он отличался по имени - person Pratik Mandrekar; 21.05.2013
comment
окей, отлично. Огромное спасибо. Я ничего не знал о Q. Вы дали мне новый подход. спасибо в тоннах - person doniyor; 21.05.2013
comment
И, чтобы быть немного более явным, он не будет различаться на color, если вам нужны разные комбинации цвета и имени, вы можете сделать distinct('name', 'color') - person Pratik Mandrekar; 21.05.2013