我有一个具有以下属性的过滤器集:
dosFromGte = filters.DateFilter(method="search_by_dos_from_gte", lookup_expr="gte")
dosToLte = filters.DateFilter(method="search_by_dos_from_lte", lookup_expr="lte")
# One of these methods:
def search_by_dos_from_lte(self, queryset: Chart, name: str, value: str) -> Chart:
return queryset.annotate(max_dos=Min("diagnosis__dos_from")).filter(max_dos__lte=value)
# using annotate and aggregate Min().
我需要运行一些注释,然后只获取不同的 id。
queryset = self.filter_queryset(self.get_queryset().exclude(state__in=repo_exclude))
queryset = queryset.annotate(
ChartId=F("chart_id")
).values(
"ChartId"
).distinct("id")
当我应用这些过滤器时
?clientId=11&project=56&dosFromGte=2023-08-17&dosToLte=2023-08-19
,它会尝试运行Min()
,然后在ids
上进行区分。
这给出了
NotImplementedError("aggregate() + distinct(fields) not implemented.")
所以我试着解决一下
queryset.values(
"id", "ChartId"
)
# remove duplicate charts based on pk, i.e. id
df = df.drop_duplicates('id')
df = df.drop('id', axis=1)
这感觉就像是一种黑客和肮脏的工作。
有没有更干净的 ORM 方法来做到这一点?
这里的主要挑战是 Django 不支持直接在 annotate() 调用之后对字段使用distinct(),这就是你遇到 NotImplementedError 的原因。
可以使用子查询单独处理注解,然后根据注解的子查询结果过滤主查询集。这种方法避免了在注释()之后直接使用distinct()。