включить дополнительное поле во вложенный сериализатор через модель Django - PullRequest
1 голос
/ 23 мая 2019

Я пишу трекер еды, поэтому есть две модели Recipe и Ingredient, которые связаны через модель RecipeIngredient с дополнительным полем quantity.

Вот мои модели.py:

class Recipe(models.Model):
    name = models.CharField(max_length=100)
    recipe = models.CharField(max_length=200)
    ingredients = models.ManyToManyField(Ingredient, through="RecipeIngredient", related_name='recipes')

class RecipeIngredient(models.Model):
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, unique=False)
    ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
    quantity = models.IntegerField(blank=False)

class Ingredient(models.Model):
    id = models.AutoField(primary_key=True, db_column='ingredient_id')
    name = models.CharField(max_length=100)
    calories = models.IntegerField(blank=True)

views.py:

class RecipeViewSet(viewsets.ModelViewSet):
    queryset = Recipe.objects.all()
    serializer_class = RecipeSerializer
    permission_classes = (AllowAny,)

    def get_queryset(self):
        return Recipe.objects.annotate(
            total_ingredients=Count('ingredients'),
            total_calories=Sum('ingredients__calories'),
            total_quantity=Sum('recipeingredient__quantity')
        )
class IngredientViewSet(viewsets.ModelViewSet):
    queryset = Ingredient.objects.all()
    serializer_class = IngredientSerializer
    permission_classes = (AllowAny,)

serialziers.py:

class RecipeSerializer(serializers.ModelSerializer):
    ingredient_list = IngredientSerializer(source='ingredients', many=True, required=False)
    total_ingredients = serializers.IntegerField(required=False)
    total_calories = serializers.IntegerField(required=False)
    total_quantity = serializers.IntegerField(required=False)
    class Meta:
        model = Recipe
        fields = ('id', 'name', 'ingredient_list', 'recipe', 'total_ingredients', 'total_calories', 'total_quantity')
        depth = 1

class IngredientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Ingredient
        fields = ['id', 'name', 'calories']

Пока мой ответ выглядит так:

  {
      "id": 1,
      "name": "testrecipe",
      "ingredient_list": [
            {
                "id": 1,
                "name": "ing0",
                "calories": 2
            },
            {
                "id": 2,
                "name": "ing1",
                "calories": 4
            },
            {
                "id": 3,
                "name": "ing2",
                "calories": 4
            }
        ],
        "recipe": "recipe discription here",
        "total_ingredients": 3,
        "total_calories": 10,
        "total_quantity": 30
   },

Я хочу включить quantity для каждого ингредиента в списке, чтобы ответ мог выглядеть следующим образом:

  {
      "id": 1,
      "name": "testrecipe",
      "ingredient_list": [
            {
                "id": 1,
                "name": "ing0",
                "calories": 2,
                "quantity":10
            },
            {
                "id": 2,
                "name": "ing1",
                "calories": 4,
                "quantity":15
            },
            {
                "id": 3,
                "name": "ing2",
                "calories": 4,
                "quantity":5
            }
        ],
        "recipe": "recipe discription here",
        "total_ingredients": 3,
        "total_calories": 10,
        "total_quantity": 30
   },

Я могу получить количество ингредиента на <ingredient instance>.recipeingredient_set.all()[0].quantity, учитывая, что этот ингредиент тольков одном рецепте, но как включить это поле в сериализаторе и в каком?

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Используйте SerializerMethodField в вашем IngredientSerializer, как показано ниже,

class IngredientSerializer(serializers.ModelSerializer):
    <b>quantity = serializers.SerializerMethodField()

    def get_quantity(self, ingredient_instance):
        recipe = ingredient_instance.recipeingredient_set.all().first()
        if recipe:
            return recipe.quantity
        else:
            return None</b>

    class Meta:
        model = Ingredient
        fields = ['id', 'name', 'calories', <b>'quantity'</b>]
0 голосов
/ 23 мая 2019

Замените ваш IngredientSerializer следующими кодами

class IngredientSerializer(serializers.ModelSerializer):
quantity = serializers.SerializerMethodField('get_ingredient_quantity')

class Meta:
    model = Ingredient
    fields = ['id', 'name', 'calories','quantity']


def get_ingredient_quantity(self, obj):
    quantity = RecipeIngredient.objects.get(ingredient=obj).quantity
    return quantity
...