Search code examples
pythondjangomanytomanyfield

manyToManyField question


Hay guys, I'm writing a simple app which logs recipes.

I'm working out my models and have stumbled across a problem

My Dish models needs to have many Ingredients. This is no problem because i would do something like this

ingredients = models.ManyToManyfield(Ingredient)

No problems, my dish now can have many ingrendients.

However, the problem is that the ingredient needs to come in different quantities.

I.E 4 eggs, 7 tablespoons sugar

My Ingredient Model is very simple at the moment

class Ingredient(models.Model):
    name = models.TextField(blank=False)
    slug = models.SlugField(blank=True)

How would i go about work out this problem? What fields would i need to add, would i need to use a 'through' attribute on my ManyToManyfield to solve this problem?


Solution

  • I think you got the right answer with a "through" table ( http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany )

    Model

    class Recipe(models.Model):
        name = models.TextField(blank=False)
        ingredients = models.ManyToManyField(Ingredient, through='Components')
    
    class Ingredient(models.Model):
        name = models.TextField(blank=False)
        slug = models.SlugField(blank=True)
    
    class Components(models.Model):
        recipe = models.ForeignKey(Recipe)
        ingredient = models.ForeignKey(Ingredient)
        quantity = models.DecimalField()
    

    You can put unit of quantity (gram, kilo, tablespoon, etc) on Ingredient level, but I think it is better on Ingredients level (for example you can have 1 recipe with 10 Cl of milk but one other with 1L ... So "different" units for a same ingredient.

    Data Creation

    By Dish you mean Recipe right ? If you have a look to previous link (http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany), they give you a good example (based on the beatles). Basically :

    1.Create a Recipe:

    cake=Recipe.objects.create(name="Simple Cake")
    

    2.Create several Ingredient (if they doesn't already exist from a previous recipe ;)):

    egg = Ingredient.objects.create(name="Egg")
    milk = Ingredient.objects.create(name="milk")
    

    3.Create the relationship:

    cake_ing1 = Components.objects.create(recipe=cake, ingredient=egg,quantity = 2)  
    cake_ing2 = Components.objects.create(recipe=cake, ingredient=milk,quantity = 200)
    

    and so on. Plus, I'm now quite sure that unit should go to Components level, with a default unit as "piece" (that would be for yours eggs ...), and would be something like "mL" for milk.

    Data Access

    In order to get ingredients (Components) of a recipe just do :

    cake = Recipe.objects.get(name = "Simple Cake")
    components_cake = Components.objects.get(recipe = cake)