我在使用DRF3中的through参数序列化多对多关系时遇到了一些麻烦
基本上我有食谱和配料,通过中间模型结合,指定特定成分的用量和单位。
这些是我的模特:
from django.db import models
from dry_rest_permissions.generics import authenticated_users, allow_staff_or_superuser
from core.models import Tag, NutritionalValue
from usersettings.models import Profile
class IngredientTag(models.Model):
label = models.CharField(max_length=255)
def __str__(self):
return self.label
class Ingredient(models.Model):
recipe = models.ForeignKey('Recipe', on_delete=models.CASCADE)
ingredient_tag = models.ForeignKey(IngredientTag, on_delete=models.CASCADE)
amount = models.FloatField()
unit = models.CharField(max_length=255)
class RecipeNutrition(models.Model):
nutritional_value = models.ForeignKey(NutritionalValue, on_delete=models.CASCADE)
recipe = models.ForeignKey('Recipe', on_delete=models.CASCADE)
amount = models.FloatField()
class Recipe(models.Model):
name = models.CharField(max_length=255)
ingredients = models.ManyToManyField(IngredientTag, through=Ingredient)
tags = models.ManyToManyField(Tag, blank=True)
nutritions = models.ManyToManyField(NutritionalValue, through=RecipeNutrition)
owner = models.ForeignKey(Profile, on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return self.name
这些目前是我的序列化器:
from recipes.models import Recipe, IngredientTag, Ingredient
from rest_framework import serializers
class IngredientTagSerializer(serializers.ModelSerializer):
class Meta:
model = IngredientTag
fields = ('id', 'label')
class IngredientSerializer(serializers.ModelSerializer):
class Meta:
model = Ingredient
fields = ('amount', 'unit')
class RecipeSerializer(serializers.ModelSerializer):
class Meta:
model = Recipe
fields = ('id', 'url', 'name', 'ingredients', 'tags', 'nutritions', 'owner')
read_only_fields = ('owner',)
depth = 1
我搜索过SO和网络很多,但我无法弄明白。如果有人能指出我正确的方向,那就太棒了。
我可以像这样获得要返回的成分列表:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"url": "http://localhost:8000/recipes/1/",
"name": "Hallo recept",
"ingredients": [
{
"id": 1,
"label": "Koek"
}
],
"tags": [],
"nutritions": [],
"owner": null
}
]
}
但我想要的是还要返还金额和单位!
答案 0 :(得分:3)
我通过以下方式得到了我想要的东西:
from recipes.models import Recipe, IngredientTag, Ingredient
from rest_framework import serializers
class IngredientTagSerializer(serializers.ModelSerializer):
class Meta:
model = IngredientTag
fields = ('id', 'label')
class IngredientSerializer(serializers.ModelSerializer):
ingredient_tag = IngredientTagSerializer()
class Meta:
model = Ingredient
fields = ('amount', 'unit', 'ingredient_tag')
class RecipeSerializer(serializers.ModelSerializer):
ingredients = IngredientSerializer(source='ingredient_set', many=True)
class Meta:
model = Recipe
fields = ('url', 'name', 'ingredients', 'tags', 'nutritions', 'owner')
read_only_fields = ('owner',)
depth = 1
使用ingredient_tag的ingredient_set作为IngredientSerializer的来源导致我需要的响应:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://localhost:8000/recipes/1/",
"name": "Hallo recept",
"ingredients": [
{
"amount": 200.0,
"unit": "g",
"ingredient_tag": {
"id": 1,
"label": "Koek"
}
},
{
"amount": 500.0,
"unit": "kg",
"ingredient_tag": {
"id": 3,
"label": "Sugar"
}
}
],
"tags": [],
"nutritions": [],
"owner": null
}
]
}
我不知道这是不是最好的方法,所以我会等到知道他们的DRF发表评论的人,或者有人在标记答案之前发布更好的内容。
答案 1 :(得分:2)
在序列化嵌套关系时,您还必须专门序列化那些ManyToManyField。
让我举个小例子:
class RecipeSerializer(serializers.ModelSerializer):
ingredients = serializers.SerializerMethodField()
def get_ingredients(self, obj):
serializer = IngredientSerializer(obj.ingredients)
return serializer.data
class Meta:
model = Recipe
fields = ('id', 'url', 'name', 'ingredients', 'tags', 'nutritions', 'owner')
read_only_fields = ('owner',)
depth = 1
无论您的嵌套关系是什么(如成分,标签或营养),您都可以通过创建序列化方法字段来序列化它们。在该方法中,您可以使用特定的序列化程序,以便它提供您想要的json。
小心方法名称。如果您的ManyToManyField是"成分",您的方法名称应为"成分"因为DRF与" get _"。
一起使用有关详细信息,请查看:
答案 2 :(得分:0)
覆盖RecipeSerializer的方法to_representation 并将许多的实例传递给他们的序列化器,其中许多是True。或
tags = serializers.HyperlinkedRelatedField( 许多= TRUE,READ_ONLY =真, )