Django фильтрует объекты, которые содержат значение поля JSON, в списке значений JSONField другой модели с тем же "ключом".
Я не уверен, что название этого поста помогло вам понять суть проблемы, но позвольте мне объяснить:
У меня есть модели:
class ItemCategory(models.Model):
name = CharField()
class Item(models.Model):
brand = CharField()
model = CharField()
category = ForeignKey(ItemCategory)
attributes = JSONField(default=dict) # e.g {"size": 1000, "power": 250}
class StockItem(models.Model):
item = ForeignKey(Item)
stock = ForeignKey(Stock)
quantity = PositiveIntegerField()
В этих моделях представлены некоторые товары на складе. Теперь я хочу реализовать функциональность, позволяющую пользователю создавать "абстрактные контейнеры", в которые он может вводить данные и отслеживать, сколько "абстрактных контейнеров" может быть произведено на основе остатков на складе.
Пример:
class Container(models.Model):
name = CharField()
class ContainerItem(models.Model):
container = models.ForeignKey(Container)
item_category = models.ForeignKey(ItemCategory)
attributes = models.JSONField(default=dict)
quantity = models.PositiveIntegerField()
Для обработки агрегации я создаю представление:
class ContainerListView(ListView):
model = models.Container
def get_queryset(self):
items_quantity_sq = models.Item.objects.filter(
item_category=OuterRef('item_category'),
attributes__contains=OuterRef('attributes'),
).values('item_category').annotate(
total_quantity=Sum('stock_items__quantity')
).values('total_quantity')
min_available_sq = models.ContainerItem.objects.filter(
container_id=OuterRef('pk')
).annotate(
available=Coalesce(Subquery(items_quantity_sq), Value(0))
).order_by('available').values('available')[:1]
base_qs = super().get_queryset().annotate(
# Attach the minimum available quantity across all items
potential=Subquery(min_available_sq)
).prefetch_related(
Prefetch(
"items",
queryset=models.ContainerItem.objects.all()
.annotate(available=Subquery(items_quantity_sq))
.order_by("available"),
)
)
return base_qs.order_by("potential")
Это работает до тех пор, пока ContainerItem
attributes
поле не содержит одно значение: {"size": 1000}
но я хочу разрешить пользователю вводить несколько значений ("size": [1000, 800]
), чтобы найти все Item
объектов, которые attributes
поле (JSONField) содержит "size": 1000
или "size": 800
.
Возможно, есть решение, использующее необработанный SQL. Но мне интересно, есть ли вообще правильный дизайн для выполнения такой агрегации в будущем? Может быть, в этом случае EAV
может быть лучшим решением?