Сравните год от DateTimeField / DateField Django ORM - PullRequest
3 голосов
/ 17 мая 2019

У меня есть модель конфигурации, как показано ниже,

class Foo(models.Model):
    start = models.DateTimeField()
    end = models.DateTimeField()

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


Неудачная попытка:

from django.db.models import F

Foo.objects.filter(start__year=F('end__year'))

возврат пустым QuerySet

1 Ответ

2 голосов
/ 17 мая 2019

SQL-запрос оператора Foo.objects.filter(start__year=F('end__year')):

SELECT "foo"."id", "foo"."start", "foo"."end" FROM "foo" <b>WHERE django_datetime_extract('year', "foo"."start", 'UTC') = ("foo"."end")</b>

Видите ..?Сравнение происходит между целым числом (извлеченным start year) и датой и временем (end datetime) .

Итак, Django вернул пустое QurySet.


Какое решение?

Мы могли бы использовать ExtractYear() дБ для извлечения Yearот DateTimeField и используйте функцию annotate() для временного сохранения.Затем сравните аннотированное поле с поиском год

from django.db.models import F
from django.db.models.functions import ExtractYear

Foo.objects.<b>annotate(start_year=ExtractYear(F('start')))</b>.filter(<b>end__year=F('start_year')</b>)

SQL-запрос

SELECT "foo"."id", "foo"."start", "foo"."end", <b>django_datetime_extract('year', "foo"."start", 'UTC') AS "start_year" </b>FROM "foo" WHERE <b>django_datetime_extract('year', "foo"."end", 'UTC') = (django_datetime_extract('year', "foo"."start", 'UTC'))</b>
...