Дальнейшая фильтрация результатов queryset в django
У меня есть две основные модели в django
с именами Applications
и Status
и третья модель для отслеживания статусов приложений с именем TrackApplicationStatus
. Таким образом, каждый раз, когда статус приложения меняется, в таблицу TrackApplicationStatus
добавляется новая запись. Текущий статус каждого приложения - это статус самой последней записи этой таблицы.
Модели определяются как:
from django.db import models
class Application(models.Model):
name = models.CharField(max_length=100)
class Status(models.Model):
name = models.CharField(max_length=100, blank=False, unique=True)
class TrackApplicationStatus(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='statuses')
status = models.ForeignKey(Status, on_delete=models.SET_NULL, related_name='applications_status', null=True)
class Meta:
get_latest_by = ['created_at']
ordering = ['-created_at']
На первом этапе я получаю текущие статусы каждого приложения с помощью следующего запроса django:
current_statuses = TrackApplicationStatus.objects.order_by('application_id', '-created_at').distinct('application_id')
Созданный SQL запрос выглядит следующим образом:
SELECT
DISTINCT ON ("api_trackapplicationstatus"."application_id")
"api_trackapplicationstatus"."id",
"api_trackapplicationstatus"."created_at",
"api_trackapplicationstatus"."application_id",
"api_trackapplicationstatus"."status_id"
FROM "api_trackapplicationstatus"
ORDER BY
"api_trackapplicationstatus"."application_id" ASC, "api_trackapplicationstatus"."created_at" DESC
Далее я хочу получить все заявки с определенным статусом. В терминах SQL я бы применил предложение WHERE
к приведенной выше таблице результатов следующим образом:
SELECT sub.application_id
FROM
(
SELECT DISTINCT ON ("api_trackapplicationstatus"."application_id")
"api_trackapplicationstatus"."created_at",
"api_trackapplicationstatus"."application_id" as application_id,
"api_trackapplicationstatus"."status_id" as status
FROM "api_trackapplicationstatus"
ORDER BY "api_trackapplicationstatus"."application_id" ASC,
"api_trackapplicationstatus"."created_at" DESC
) AS sub
WHERE sub.status = 3
Как я могу добиться того же самого, используя django ORM?
Вам не нужно 3 модели. Это можно просто сделать в 1 модели.
Определите свою модель следующим образом:
class Application(model.Model):
name = model.CharField(max_length=100)
status = models.CharField(max_length=100, blank=False, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
get_latest_by = ['created_at']
ordering = ['-created_at']
Теперь вы можете просто отфильтровать заявки на основе их статуса:
Applications.objects.filter(status='3').order_by('-created_at')
Я нашел не очень хороший способ:
# The desired status
status=Status.objects.get(id=3)
# The current tracking item of each application
current_statuses = TrackApplicationStatus.objects.order_by('application_id', '-created_at').distinct('application_id')
# The tracking items with the current status 3
TrackApplicationStatus.objects.filter(status=status, id__in=Subquery(current_statuses.values('id')))
Соответствующий SQL:
SELECT "api_trackapplicationstatus"."id",
"api_trackapplicationstatus"."created_at",
"api_trackapplicationstatus"."application_id",
"api_trackapplicationstatus"."status_id"
FROM "api_trackapplicationstatus"
WHERE (
"api_trackapplicationstatus"."id"
IN (
SELECT DISTINCT ON (U0."application_id") U0."id"
FROM "api_trackapplicationstatus" U0
ORDER BY U0."application_id" ASC,
U0."created_at" DESC
)
AND "api_trackapplicationstatus"."status_id" = 3
)
ORDER BY "api_trackapplicationstatus"."created_at" DESC