Подсчитывать различные значения подзапроса
У меня есть эти модели:
class Component(models.Model)
name = models.CharField(max_length=50)
class ComponentAttribute(models.Model)
component = models.ForeignKey(Component)
context = models.ForeignKey(Context)
subcategory = models.ForeignKey(SubCategory)
material = models.ForeignKey(Material)
measurement = models.ForeignKey(Measurement)
value = models.FloatField()
Я хочу указать количество уникальных атрибутов для каждого компонента в наборе запросов. Атрибут является уникальным, когда он содержит уникальную комбинацию контекста, подкатегории и материала для данного компонента.
Основываясь на других публикациях здесь и документации по Django, я создал запрос на основе подзапроса.
# Create a subquery that counts the distinct combinations
float_attributes_count = Subquery(
ComponentAttributeFloat.objects
.filter(component=OuterRef('pk'))
.order_by(
'subcategory_id',
'context_id',
'material_id')
.distinct(
'subcategory_id',
'context_id',
'material_id')
.values("component__id")
.annotate(count=Count('id'))
.values('count'))
components = Component.objects.annotate(
unique_attributes=float_attributes_count
)
Когда я сейчас попытаюсь сопоставить этот запрос с этим базовым циклом, чтобы вывести свой результат.
for component in components:
print(f'{component}: {component.unique_attributes}')
Я получаю сообщение об ошибке:
NotImplementedError: annotate() + distinct(fields) is not implemented.
Похоже, что комбинация требований, которые у меня есть, приводит к невыполнимому запросу, и я не могу найти примеры, в которых были бы установлены все флажки для меня. Кто-нибудь может помочь мне с рабочим запросом, используя другой путь? (Для справки я использую базу данных PostgreSQL, которая должна поддерживать это отдельное утверждение, см.: https://docs.djangoproject.com/en/5.2/ref/models/querysets/#django.db.models.запрос.Набор запросов.distinct)
Возможно, вы можете подсчитать комбинации значений, например:
from django.db.models import CharField, Value
from django.db.models.functions import Cast, Concat
sep = Value(',')
float_attributes_count = Subquery(
ComponentAttributeFloat.objects.filter(component=OuterRef('pk'))
.annotate(
count=Count(
Concat(
Cast('subcategory_id', output_field=CharField()),
sep,
Cast('context_id', output_field=CharField()),
sep,
Cast('material_id', output_field=CharField()),
),
distinct=True,
)
)
.values('count')
)
components = Component.objects.annotate(unique_attributes=float_attributes_count)