Я использую Django 1.10
У меня есть запрос, который зависит от полученного параметра - это зависит от того, имеет ли 'job_name' значение None или нет:
def delete_jobs_by_age_and_name(days_ago, job_name=None):
date_to_delete_from = datetime.today() - timedelta(days=days_ago
if job_name is not None:
jobs_to_delete = AsyncJob.objects.filter(
name=job_name,
created_at__lte=date_to_delete_from
)
else:
jobs_to_delete = AsyncJob.objects.filter(created_at__lte=date_to_delete_from)
Я хотел бы сделать это одним запросом. Например что-то вроде:
job_name = ANY if job_name is None
jobs_to_delete = AsyncJob.objects.filter(
name=job_name,
created_at__lte=date_to_delete_from
)
Есть такой вариант?
Вы можете составлять запросы.
jobs_to_delete = AsyncJob.objects.filter(created_at__lte=date_to_delete_from)
if job_name is not None:
jobs_to_delete = jobs_to_delete.filter(name=job_name)
Это действительно запускает запрос только один раз. Наборы запросов ленивы, а filter () фактически не выполняет никаких вызовов базы данных.
Я считаю, что функция должна вернуть значение jobs_to_delete.
Самый короткий (2 строки) способ, о котором я могу думать:
jobs_to_delete = AsyncJob.objects.filter(created_at__lte=date_to_delete_from)
return jobs_to_delete.filter(name=job_name) if job_name else jobs_to_delete
Таким образом, вы используете встроенный оператор if, который сокращает написанный код и сохраняет все читабельным и простым.
Спасибо за этот фрагмент кода, который может оказать некоторую немедленную помощь. правильное объяснение значительно улучшило бы его долгосрочную ценность, показывая Зачем, это хорошее решение проблемы, которое сделает его более полезным для будущих читателей с другими похожими вопросами. Пожалуйста, редактировать свой ответ, чтобы добавить некоторые пояснения, включая сделанные вами предположения.
Вы можете передать свои аргументы filter
в качестве словаря, который вы можете изменить заранее, чтобы вам понадобился только один вызов filter
, а затем просто распакуйте словарь в вызове filter
. Что-то вроде этого:
filter_kwargs = {'created_at__lte': date_to_delete_from}
if job_name is not None:
filter_kwargs['name'] = job_name
jobs_to_delete = AsyncJob.objects.filter(**filter_kwargs)
Отличная идея. Спасибо.
Я искал способ выполнить запрос только один раз. Спасибо