views:

2359

answers:

2

I have a few model classes with basic one-to-many relationships. For example, a book has many recipes, and each recipe has many ingredients:

class Book(models.Model):
    name = models.CharField(max_length=64)

class Recipe(models.Model):
    book = models.ForeignKey(Book)
    name = models.CharField(max_length=64)

class Ingredient(models.Model):
    text = models.CharField(max_length=128)
    recipe = models.ForeignKey(Recipe)

I'd like a flat list of all ingredients in all recipes from a particular book. What's the best way to express this in Python?

If I was using LINQ, I might write something like this:

var allIngredients = from recipe in book.Recipes
                     from ingredient in recipe.Ingredients
                     select ingredient;
A: 

To print each recipe and its ingredients:

mybook = Book.objects.get(name="Jason's Cookbook")
for recipe in mybook.recipe_set.all():
    print recipe.name
    for ingredient in recipe.ingredients:
        print ingredient.text

And if you just want to get a list of all ingredient objects:

mybook = Book.objects.get(name="Jason's Cookbook")
ingredient_list = []
for recipe in mybook.recipe_set.all():
    for ingredient in recipe.ingredients:
        ingredient_list.append(ingredient)

Documentation.

Harley
Hm, I'm not exactly looking to print the ingredients, but collect them into a list. I'm imagining there's probably an idiom here that I'm missing.
Jason Anderson
I've updated the answer with what I think you're after.
Harley
+6  A: 

Actually, it looks like there's a better approach using filter:

my_book = Book.objects.get(pk=1)
all_ingredients = Ingredient.objects.filter(recipe__book=my_book)
Jason Anderson
Well I suppose if you want to do it in the simple, one-line kind of way you could do this. ;)
Harley