2016-02-29 3 views
1

Вот мой запрос:запроса оптимизации с Django

  • У меня есть Personne модель, которая может иметь один или несколько поездок через PersonneTravel.
  • В PersonneTravel, то travel поле является внешним ключом к TagWithValue
  • s является «начало» дата, как «1954-05-01»
  • e является дата окончания, как «1999-05-01»
  • travel является строкой, как «Париж, Франция»

Так я делаю основной «поиск» для фильтрации, который сделал путешествие и когда.

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

  1. я получить все pk из TagWithValue, которые имеют соответствующие value
  2. я получить все pkPersonneTravel, которые имеют соответствующий ход те рк, прежде чем
  3. я получить все Personne, который соответствует PersonneTravel рк перед тем

Я хотел бы вернуться только один присоединиться, как это (это не хорошо SQL конечно, но только, чтобы получить большую идею):

SELECT ALL PersonneTravel PT 
JOIN Personne P on P.personne_travel__pk = PT.pk 
JOIN TagWithValue T 
WHERE T.personne__pk = P.pk 
AND T.value = "Paris, France" 
AND T.tag = TYPE_GOOGLEMAPS 

Есть ли способ, чтобы оптимизировать это и сделайте это с помощью моего следующего кода?

q = Q() 
if s: 
    q = q & Q(date_start__gte=s) 
if e: 
    q = q & Q(date_end__lte=e) 
retour = [a[0] for a in TagWithValue.objects.filter(
    type_tag__exact=BaseTag.TYPE_GOOGLEMAPS, 
    value__exact=travel).values_list('pk')] 
retour = PersonneTravel.objects.filter(Q(travel__in=retour) & q)\ 
    .values_list('personne__pk') 
if len(retour): 
    retour = Personne.objects.filter(pk__in=retour) 
+0

Пожалуйста, разместите ваши модели. – ilse2005

+0

Это было бы, если бы вы могли предоставить информацию о модели. Предполагая структуру, я добавил ответ. Пожалуйста, 'Примите' и' Upvote' мой ответ, если он решит вашу проблему :) –

ответ

1

Там нет необходимости использовать Q() здесь. Используйте flat=True с values_list(), чтобы получить список значений вместо списка типов значений. Это решение может быть дополнительно упрощено с использованием related_name в столбце ForeignKey модели Django.

key = {} 
if s: 
    key['date_start__gte'] = s 
if e: 
    key['date_end__lte'] = e 
key[travel__type_tag__exact] = BaseTag.TYPE_GOOGLEMAPS 
key[travel__value__exact] = travel 

retour = PersonneTravel.objects.filter(**key)\ 
    .values_list('personne__pk', flat=True) 

if len(retour): 
    retour = Personne.objects.filter(pk__id__in=retour) 

Пример с related_name: Пусть говорят related_personne является related_name для Personne соответственно в PersonneTravel модели.

key = {} 
key['related_personne__travel__type_tag__exact'] = BaseTag.TYPE_GOOGLEMAPS 
key['related_personne__travel__value__exact'] = travel 
if s: 
    key['related_personne__date_start__gte'] = s 
if e: 
    key['related_personne__date_end__lte'] = e 

retour = Personne.objects.filter(**key) 
0

Я думаю, что вы можете сделать это без Q-objects с помощью __ синтаксиса Джанго:

query = Personne.objects.filter(personnetravel__travel__value__exact=travel, 
           personnetravel__travel__type_tag__exact=BaseTag.TYPE_GOOGLEMAPS) 

# because django querysets are lazy you can add the date filters now 
if s: 
    query = query.filter(personnetravel__date_start__gte=s) 
if e: 
    query = query.filter(personnetravel__date_end__lte=e) 
Смежные вопросы