Frederick
Frederick

Reputation: 470

Django Rest API ManyToMany gives nothing [] in API

at the moment I try to get recipes from my API. I have a Database with two tables one is with recipes and their ids but without the ingredients, the other table contains the ingredients and also the recipe id. Now I cant find a way that the API "combines" those. Maybe its because I added in my ingredient model to the recipe id the related name, but I had to do this because otherwise, this error occurred:

ERRORS:
recipes.Ingredients.recipeid: (fields.E303) Reverse query name for 'Ingredients.recipeid' clashes with field name 'Recipe.ingredients'.
        HINT: Rename field 'Recipe.ingredients', or add/change a related_name argument to the definition for field 'Ingredients.recipeid'.

Models

from django.db import models

class Ingredients(models.Model):
    ingredientid = models.AutoField(db_column='IngredientID', primary_key=True, blank=True)
    recipeid = models.ForeignKey('Recipe', models.DO_NOTHING, db_column='recipeid', blank=True, null=True, related_name='+')
    amount = models.CharField(blank=True, null=True, max_length=100)
    unit = models.CharField(blank=True, null=True, max_length=100)
    unit2 = models.CharField(blank=True, null=True, max_length=100)
    ingredient = models.CharField(db_column='Ingredient', blank=True, null=True, max_length=255)
    
    class Meta:
        managed = True
        db_table = 'Ingredients'  

class Recipe(models.Model):
    recipeid = models.AutoField(db_column='RecipeID', primary_key=True, blank=True)  # Field name made lowercase.
    title = models.CharField(db_column='Title', blank=True, null=True, max_length=255)  # Field name made lowercase.
    preperation = models.TextField(db_column='Preperation', blank=True, null=True)  # Field name made lowercase.
    images = models.CharField(db_column='Images', blank=True, null=True, max_length=255)  # Field name made lowercase.
    #ingredients = models.ManyToManyField(Ingredients) 
    ingredients = models.ManyToManyField(Ingredients, related_name='recipes')
    class Meta:
        managed = True
        db_table = 'Recipes'

When there is no issue it has to be in the serializer or in the view.

Serializer

class IngredientsSerializer(serializers.ModelSerializer):
   # ingredients = serializers.CharField(source='ingredients__ingredients')

    class Meta:
        model = Ingredients
        fields = ['ingredient','recipeid']

class FullRecipeSerializer(serializers.ModelSerializer):

    ingredients = IngredientsSerializer(many=True)

    class Meta:
        model = Recipe
        fields = ['title','ingredients']

View

class FullRecipesView(generics.ListCreateAPIView):
    serializer_class = FullRecipeSerializer
    permission_classes = [
        permissions.AllowAny
    ]
    queryset = Recipe.objects.all()

This is at the moment my output But I want e.g. the recipe with id 0 and all the ingredients which have also recipe id 0. I really hope that you can help me. Thank you so much!

Upvotes: 0

Views: 170

Answers (1)

JPG
JPG

Reputation: 88589

From the doc of ForeignKey.related_name,

If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'.

So, change the related_name of Ingredients.recipeid field to

class Ingredients(models.Model):
    # rest of the fields
    recipeid = models.ForeignKey(
        'Recipe',
        models.DO_NOTHING,
        db_column='recipeid',
        blank=True,
        null=True,
        related_name="ingredients_ref" # Changed the related name 
    )

Then, migrate the database using python manage.py makemigrations and python manage.py migrate

Then, update your FullRecipeSerializer class as,

class FullRecipeSerializer(serializers.ModelSerializer):
    ingredients_forward = IngredientsSerializer(many=True, source="ingredients")
    ingredients_backward = IngredientsSerializer(many=True, source="ingredients_ref")

    class Meta:
        model = Recipe
        fields = ['title', 'ingredients_forward', 'ingredients_backward']

Note that, here I have added two fields named ingredients_forward and ingredients_backward because there existing two types of relationships between Recipe and Ingredients and I am not sure which one you are seeking.

Upvotes: 1

Related Questions