джанго:sql-запросы datediff?
Вопрос
Я пытаюсь сделать эквивалент следующего SQL в Django:
ВЫБЕРИТЕ * У кандидата, ГДЕ date_out - date_in >= 1 И date_out - date_in <= 6
Я могу сделать это как НЕОБРАБОТАННЫЙ sql-запрос, но это становится неприятным при работе с RawQuerySet вместо обычного объекта QuerySet, поскольку я хотел бы иметь возможность фильтровать его позже в коде.
Решение
Вы можете использовать extra()
метод и пройти в where
Аргумент ключевого слова. Значение where
должен быть список, который содержит SQL WHERE
пункт запроса выше. Я проверил это с PostgreSQL 8.4, и это то, что он выглядел в моем случае:
q = Applicant.objects.extra(where = ["""date_part('day', age(date_out, date_in)) >= 1 and
date_part('day', age(date_out, date_in)) <= 6"""])
Это вернет вам действительный QuerySet
экземпляр.
Другие советы
Я столкнулся с проблемой того, что Django изначально не поддерживает Datediff
(и другие эквиваленты базы данных), и необходимо было использовать такую функцию много раз для конкретного проекта.
При дальнейшем чтении стало ясно, что реализация вычисления интервала между двумя датами сильно отличается в разных вариантах использования основных баз данных.Вероятно, именно поэтому в Django пока нет собственной функции абстракции.Итак, я написал свою собственную функцию Django ORM для datediff
:
Видишь: репозиторий mike-db-tools на Github
Вы увидите различный синтаксис между серверными частями базы данных, написанный в docstrings для соответствующих баз данных.Datediff поддерживает sqlite, MySQL / MariaDB, PostgreSQL и Oracle.
Использование (Django 1.8+):
from db_tools import Datediff
# Define a new dynamic fields to contain the calculated date difference
applicants = Applicant.objects.annotate(
days_range=Datediff('date_out','date_in', interval='days'),
)
# Now you can use this dynamic field in your standard filter query
applicants = applicants.filter(days_range__gte=1, days_range__lte=6)
Я действительно довольно дерганый, когда дело доходит до моего кода, поэтому я призываю вас разветвляться и совершенствоваться.