Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

python - Problems on through model with Django Rest Framework

This happens when I list to Recipe objects. Trying to do as here, I get no errors, but the response I'm getting is as the following:

# response of Recipe.objects.all()
[
    {
        "user": 1,
        "name": "sandwich",
        "ingredients": [
            {},
            {}
        ],
        "created": "2021-01-11T00:47:04.932071-03:00",
        "modified": "2021-01-11T00:47:04.932167-03:00"
    }
]

When the models are:

class Recipe(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, null=False)
    name = models.CharField(blank=False, max_length=50)
    ingredients = models.ManyToManyField('recipes.Ingredient', through='recipes.IngredientComposition')
    # some other fields...

class Ingredient(BaseModel):
    name = models.CharField(blank=False, max_length=25, unique=True
                            error_messages={'unique': 'Ingredient already exists'})

class IngredientComposition(models.Model):    
    ingredient = models.ForeignKey('Ingredient', on_delete=models.CASCADE, null=False)
    recipe = models.ForeignKey('recipes.Recipe', on_delete=models.CASCADE, null=False)
    quantity = models.DecimalField(max_digits=21, decimal_places=3, null=False, default=1)

And their serializers:

class RecipeSerializer(serializers.ModelSerializer):
    ingredients = IngredientCompositionSerializer(read_only=True, many=True)
    class Meta:
        model = Recipe
        fields = ['user', 'name', 'ingredients', 'created', 'modified']

class IngredientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ingredient
        fields = ['name', 'created', 'modified']

class IngredientCompositionSerializer(serializers.HyperlinkedModelSerializer):
    name = serializers.ReadOnlyField(source='ingredient.name')
    class Meta:
        model = IngredientComposition
        fields = ['name', 'quantity']

The expected response is:

[
    {
        "user": 1,
        "name": "sandwich",
        "ingredients": [
            {"name": "bread", "quantity": 2.0},
            {"name": "cheese", "quantity": 3.0}
        ],
        "created": "2021-01-11T00:47:04.932071-03:00",
        "modified": "2021-01-11T00:47:04.932167-03:00"
    }
]

What am I missing?

question from:https://stackoverflow.com/questions/65661607/problems-on-through-model-with-django-rest-framework

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

add a related name to recipe

class IngredientComposition(models.Model):    
    ingredient = models.ForeignKey('Ingredient', on_delete=models.CASCADE, null=False)
    recipe = models.ForeignKey('recipes.Recipe', on_delete=models.CASCADE, null=False, related_name='ingredients_list') # change here
    quantity = models.DecimalField(max_digits=21, decimal_places=3, null=False, default=1)

then add that field in RecipeSerializer

class RecipeSerializer(serializers.ModelSerializer):
    ingredients_list = IngredientCompositionSerializer(read_only=True, many=True) # change here
    class Meta:
        model = Recipe
        fields = ['user', 'name', 'ingredients_list', 'created', 'modified'] # change here 'ingredients_list'

as ingredients is already ManyToManyField in model Recipe it it causing that problem.

PS: In my opinion you should not need ingredients = models.ManyToManyField('recipes.Ingredient', through='recipes.IngredientComposition') field but I dont know rest of your business logic...

the solution should work regardless.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...