2015-05-16 6 views
0

У меня возникли проблемы filtering annotations. Модели:Django: Фильтрация Аннотации не работают

class VenueBookmark(models.Model): 
    venue = models.ForeignKey(Venue) 
    cost_per_guest = models.DecimalField(max_digits=19, decimal_places=2, blank=True, null=True) 

class Venue(DateAwareModel): 
    name = models.CharField(max_length=255) 

И на мой взгляд, я в основном имеют:

venues = venues.annotate(min_cost=Min('venuebookmark__cost_per_guest')) 
venues = venues.filter(min_cost__lte=user_input) 

Однако, я все еще получаю результаты,> user_input. Какие-нибудь идеи по этому поводу?

Edit:

Я попытался преобразовать user_input в десятичный тип, но все-таки получить тот же результат:

venues = venues.filter(min_cost__lte=Decimal(user_input)) 

Это также большую часть SQL я получил от Django Debug Toolbar :

SELECT "venue_search_venue"."name", MIN("bookmarks_venuebookmark"."cost_per_guest") AS "min_cost" 
FROM "venue_search_venue" 
LEFT OUTER JOIN "bookmarks_venuebookmark" ON ("venue_search_venue"."id" = "bookmarks_venuebookmark"."venue_id") 
GROUP BY "venue_search_venue"."id", "venue_search_venue"."name" 
HAVING MIN("bookmarks_venuebookmark"."cost_per_guest") <= %s 
DESC LIMIT 9' - PARAMS = ("Decimal('100')",) 

После запроса к базе данных напрямую и сравнивая результаты, я подозреваю, что проблема Джанго Отрисовывает user_input как строка вместо числа, например.

HAVING MIN("bookmarks_venuebookmark"."cost_per_guest") <= '100' 

вместо:

HAVING MIN("bookmarks_venuebookmark"."cost_per_guest") <= 100 

ответ

0

Это забавный вопрос. Ответ прост, вы должны изменить min по max:

venues = venues.annotate(max_cost=Max('venuebookmark__cost_per_guest')) 
venues = venues.filter(max_cost__lte=max_cost) 

иллюстрируя его с например:

venues VenueBookmark Cost 
    1  5 
    1  7 
  • С вашим фактическим состоянием, если взять 6 в max_cost, центры номера 1 появится в результирующем наборе, потому что min of VenueBookmark Cost - 5 и 5 < 6.
  • Изменение min по max, центры номер 1 не будут включены в результаты, потому что 7 is not < than 6

Edit

Кроме того, включают в себя order_by() очистить упорядоченность по умолчанию:

venues = (venues 
    .order_by() 
    .annotate(min_cost=Min('venuebookmark__cost_per_guest')) 
    ) 

По умолчанию упорядочивая введенные поля сортировки по статье group by.

+0

Спасибо за ответ, но я хочу взять мин. Используя ваши данные образца, если я устанавливаю фильтр (min_cost__lte = 4), я все равно получаю место 1, которое появляется в наборе результатов, что не похоже на ожидаемое поведение. – wasabigeek

+0

Просто для теста. Добавить '.order_by()' в цепочку запросов. Таким образом, без параметров. Перед '.annotate'. Такое поведение может быть вызвано сортировкой defaut. – danihp

+0

Привет @danihp, попробовал, и он все еще не помогает. Правильно ли SQL? – wasabigeek

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