Django rest framework aggregation
Я пытаюсь сгруппировать ингредиенты по продуктам, позвольте мне объяснить.
models.py
class Product(models.Model):
name = models.CharField(
"nome del prodotto",
max_length=25,
unique=True,
)
cost = models.DecimalField(
"costo",
max_digits= 5,
decimal_places= 2,
)
classification = models.ForeignKey(
Classification,
on_delete=models.SET_NULL,
null=True,
related_name="prodotti",
verbose_name="classificazione"
)
def __str__(self) -> str:
return f"{self.name}"
class Meta:
verbose_name = "Prodotto"
verbose_name_plural = "Prodotti"
class Ingredient(models.Model):
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name="ingredienti",
verbose_name="prodotto"
)
ingredient = models.ForeignKey(
Product,
on_delete=models.PROTECT,
related_name="ingrediente",
verbose_name="ingrediente"
)
quantity = models.FloatField("quantità")
class Meta:
verbose_name = "ingrediente"
verbose_name_plural = "ingredienti"
serializers.py
class IngredientSerializers(serializers.ModelSerializer):
class Meta:
model = Ingredient
fields = "__all__"
views.py
class IngredientViewsets(viewsets.ReadOnlyModelViewSet):
queryset = Ingredient.objects.all()
serializer_class = IngredientSerializers
прямо сейчас просмотрите этот, несгруппированный список
{
"id": 1,
"quantity": 250.0,
"product": 6,
"ingredient": 7
},
{
"id": 2,
"quantity": 100.0,
"product": 6,
"ingredient": 9
},
{
"id": 3,
"quantity": 100.0,
"product": 6,
"ingredient": 8
},
я хотел бы получить что-то вроде этого, список с сгруппированными товарами и список ингридиента как этот
{
"id": 1,
"quantity": 250.0,
"product": 6,
"ingredient":[
{
"ingredient": 7,
"quantity": 250.0,
},
{
"ingredient": 9
"quantity": 100.0,
},
{
"ingredient": 8
"quantity": 100.0,
},
]
}
Короче говоря, я пытался выяснить, как это можно сделать, но я не знаю, с чего начать, может быть, кто-нибудь сможет решить эту проблему для меня. Спасибо за помощь и прошу прощения за плохой английский
Я бы разработал код следующим образом:
Модели
class Ingredient(models.Model):
# Put here ingredient info
class Meta:
verbose_name = "ingrediente"
verbose_name_plural = "ingredienti"
class Product(models.Model):
name = models.CharField(
"nome del prodotto",
max_length=25,
unique=True,
)
cost = models.DecimalField(
"costo",
max_digits= 5,
decimal_places= 2,
)
classification = models.ForeignKey(
Classification,
on_delete=models.SET_NULL,
null=True,
related_name="prodotti",
verbose_name="classificazione"
)
def __str__(self) -> str:
return f"{self.name}"
class Meta:
verbose_name = "Prodotto"
verbose_name_plural = "Prodotti"
class IngredientProductRelation(models.Model):
"""
This is an intermediate model used to relate ingredients and products
"""
# You can also use a ManyToManyField with a through model, but i think that in this case is not convenient
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name="ingredients",
verbose_name="prodotto"
)
ingredient = models.ForeignKey(
Ingredient,
on_delete=models.PROTECT,
related_name="products",
verbose_name="ingrediente"
)
quantity = models.FloatField("quantità")
Сериализаторы:
class IngredientProductRelationSerializer(serializers.ModelSerializer):
"""
Serializes a IngredientProductRelation instance
"""
class Meta:
model = IngredientProductRelation
fields = ['ingredient', 'quantity']
class ProductSerializer(serializers.ModelSerializer):
"""
Serializes a Product instance
"""
ingredients = IngredientProductRelationSerializer(read_only=True, many=True)
class Meta:
model = Product
fields = ['id', 'name', 'classification', 'ingredients']
Виды:
class ProductViewsets(viewsets.ReadOnlyModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
Сериализованный экземпляр продукта должен выглядеть следующим образом:
{
"id": 1,
"name": "example",
"classification": "example",
"ingredients":[
{
"ingredient": 7,
"quantity": 250.0,
},
{
"ingredient": 1,
"quantity": 100.0,
},
]
}
Вы также можете получить доступ к продуктам, связанным с определенным ингредиентом, например:
ingredient_product_relations = ingredient.products.all()
for ingredient_product_relation in list(ingredient_product_relations):
print(ingredient_product_relation.product.name)