按特定条件限制 prefetch_related 为 1
Limit prefetch_related to 1 by a certain criteria
所以我有这样的模型
class Status(models.Mode):
name = models.CharField(max_length=255, choices=StatusName.choices, unique=True)
class Case(models.Model):
# has some fields
class CaseStatus(models.Model):
case = models.ForeignKey("cases.Case", on_delete=models.CASCADE, related_name="case_statuses")
status = models.ForeignKey("cases.Status", on_delete=models.CASCADE, related_name="case_statuses")
created = models.DateTimeField(auto_now_add=True)
我需要根据案例状态过滤案例,但问题是只应考虑最新的案例状态。
要根据所有案例状态获取案例对象,此查询有效:
Case.objects.filter(case_statuses__status=status_name)
但我需要获取 Case 对象,以便仅考虑其最新的 case_status 对象(降序创建)。我正在寻找这样的东西:
Case.objects.filter(case_statuses__order_by_created_first__status=status_name)
我也尝试过 Prefetch,但似乎不适用于我的用例
sub_query = CaseStatus.objects.filter(
id=CaseStatus.objects.select_related('case').order_by('-created').first().id)
Case.objects.prefetch_related(Prefetch('case_statuses', queryset=sub_query)).filter(
case_statuses__status=status_name)
这在原始 postgres 中使用限制 1 很容易解决。但不确定如何在 Django ORM 中实现它。
您可以 annotate 您的案例及其最后状态,然后根据您想要的状态过滤。
from django.db.models import OuterRef
status_qs = CaseStatus.objects.filter(case=OuterRef('pk')).order_by('-created').values('status__name')[:1]
Case.objects.annotate(last_status=status_qs).filter(last_status=status_name)
所以我有这样的模型
class Status(models.Mode):
name = models.CharField(max_length=255, choices=StatusName.choices, unique=True)
class Case(models.Model):
# has some fields
class CaseStatus(models.Model):
case = models.ForeignKey("cases.Case", on_delete=models.CASCADE, related_name="case_statuses")
status = models.ForeignKey("cases.Status", on_delete=models.CASCADE, related_name="case_statuses")
created = models.DateTimeField(auto_now_add=True)
我需要根据案例状态过滤案例,但问题是只应考虑最新的案例状态。
要根据所有案例状态获取案例对象,此查询有效:
Case.objects.filter(case_statuses__status=status_name)
但我需要获取 Case 对象,以便仅考虑其最新的 case_status 对象(降序创建)。我正在寻找这样的东西:
Case.objects.filter(case_statuses__order_by_created_first__status=status_name)
我也尝试过 Prefetch,但似乎不适用于我的用例
sub_query = CaseStatus.objects.filter(
id=CaseStatus.objects.select_related('case').order_by('-created').first().id)
Case.objects.prefetch_related(Prefetch('case_statuses', queryset=sub_query)).filter(
case_statuses__status=status_name)
这在原始 postgres 中使用限制 1 很容易解决。但不确定如何在 Django ORM 中实现它。
您可以 annotate 您的案例及其最后状态,然后根据您想要的状态过滤。
from django.db.models import OuterRef
status_qs = CaseStatus.objects.filter(case=OuterRef('pk')).order_by('-created').values('status__name')[:1]
Case.objects.annotate(last_status=status_qs).filter(last_status=status_name)