How to get specific objects based on ManyToMany field match

Question:

I’m doing a cookbook app, which help users find meal thay can do with their ingridients. I’m using Django RestFramework, and i need to return list of avaliable meals that user can do, but don’t know how to do search by ingridients

My models.py:

#models.py
class Meal(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField(blank=True, null=True)
    recipe = models.TextField()
    is_published = models.BooleanField(default=False)
    category = ForeignKey('Category', on_delete=models.CASCADE, null=True)
    user = ForeignKey(User, verbose_name='User', on_delete= models.CASCADE)
    difficulty = ForeignKey('Difficulty', on_delete=models.PROTECT, null=True)
    ingridients = models.ManyToManyField('Ingridient')

class Ingridient(models.Model):
    name = models.CharField(max_length=100, db_index=True)
    ico = models.ImageField(upload_to="photos/%Y/%m/%d/", blank=True, null=True)
    category = ForeignKey('CategoryIngridients', on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.name

class CookBookUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ingridients = models.ManyToManyField('Ingridient')

serializer.py

class MealSerializer(serializers.ModelSerializer):
    class Meta:
        model = Meal
        fields = "__all__"

views.py

class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
    serializer_class = MealSerializer

    def get_queryset(self):
       return Meal.objects.filter(ingridients=CookBookUser.objects.filter(user_id = self.request.user.id).ingridients)

CraftWithUsersIngridientsListAPIView isn’t working and I get AttributeError ‘QuerySet’ object has no attribute ‘ingridients’, can someone help fix this?

I tried building different serializer but it doesn’t help

Asked By: Vleo

||

Answers:

class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
    serializer_class = MealSerializer

    def get_queryset(self):
        user_ingredients = CookBookUser.objects.get(user=self.request.user).ingredients.all()
        return Meal.objects.filter(ingredients__in=user_ingredients)

This way, you first get the CookBookUser instance for the current user, then get all of their ingredients, and finally, filter the Meal objects that contain those ingredients. The __in query lookup is used to check if the meal ingredients are in the user’s ingredients.