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)
Вернуться на верх