Django ORM: добавьте целые дни в DateField, чтобы аннотировать next_service и отфильтровать его (PostgreSQL)Python

Программы на Python
Ответить
Anonymous
 Django ORM: добавьте целые дни в DateField, чтобы аннотировать next_service и отфильтровать его (PostgreSQL)

Сообщение Anonymous »

Я пытаюсь аннотировать набор запросов с помощью next_service = Last_service + Verification_ periodicity_in_days, а затем фильтровать по этой дате. Я использую Django 5.2.6 с PostgreSQL. Last_service — это DateField. verification_ periodicity хранится в связанной подкатегории и представляет собой количество дней (целое число).
Модели (минимальные):

Код: Выделить всё

# main/models.py

class Category(models.Model):
name = models.CharField(max_length=100)

class SubCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='subcategories')
name = models.CharField(max_length=100)
verification_periodicity = models.IntegerField()  # days

class Asset(models.Model):
sub_category = models.ForeignKey(SubCategory, on_delete=models.PROTECT)
last_service = models.DateField(null=True, blank=True)
Цель:
Вычислить next_service = число дней Last_service + Verification_ periodicity в базе данных, представить его в API и поддержать фильтрацию, например ?next_date__gte=2025-12-06.
Что я пробовал:
  • Простое приведение и умножить:

Код: Выделить всё

from django.db.models import ExpressionWrapper, F, DateField, IntegerField
from django.db.models.functions import Cast

qs = qs.annotate(
next_service = ExpressionWrapper(
F('last_service') + Cast(F('sub_category__verification_periodicity'), IntegerField()) * 1,
output_field=DateField()
)
)
Это не меняется по дням и позже вызывает проблемы с типом. Фильтрация по аннотированной дате также не сработала должным образом.
  • Использование временной разницы Python:

Код: Выделить всё

from datetime import timedelta

qs = qs.annotate(
next_service = F('last_service') + timedelta(days=1) * F('sub_category__verification_periodicity')
)
Это привело к получению продолжительности в секундах в сериализованном выводе. Пример: "next_service": "86400.0" для одного дня, а не правильной даты. Мне нужна дата.
Ошибки, замеченные по пути:
  • Код: Выделить всё

    ProgrammingError: operator does not exist: interval * interval
    когда мне пришлось перемножить два интервала в SQL.
  • Код: Выделить всё

    "next_service": "86400.0"
    , что предполагает, что я создал продолжительность, а не дату.
Окружающая среда:
  • Django 5.2.6
  • Python 3.11.5
  • PostgreSQL (AWS RDS и локальный)
  • Пример URL-адреса, который должен работать:

    Код: Выделить всё

    GET /api/main/assets/?next_date__gte=2025-12-06
Вопросы:
  • Какое правильное идиоматическое выражение ORM в Django для вычисления дней Last_service + Verification_ periodicity как дата в PostgreSQL?
  • Как следует определить выходное_поле, чтобы аннотация представляла собой дату, а не дату продолжительность?
  • Как правильно фильтровать по этой аннотированной дате в том же запросе, например next_service__gte=?


Подробнее здесь: https://stackoverflow.com/questions/798 ... and-filter
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»