Issue
I’m creating a recipe app, and to avoid duplication I want to store the tools without using foreign keys to avoid duplicates. Currently, each ingredient uses a recipe as a foreign key, as ingredients can come in different measurements, but I’d like to have the tools only able to be in the database once.
Here are the relevant models:
class Recipe(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=200)
servings = models.IntegerField(default=1, blank=False)
def __str__(self):
return self.name
class Instruction(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
description = models.CharField(max_length=400)
def __str__(self):
return f"Step #{self.id} - {self.description[:20]}"
class Tool(models.Model, unique=True):
name = models.CharField(max_length=50)
description = models.CharField(max_length=200)
def __str__(self):
return self.name
For ingredients, I’m using a forloop to create a table (below), but I’m unsure how to do the same for tools related to a recipe without having multiple entries in the database for tools be the same, apart from the related recipe, i.e "Frying pan" more than once.
<h3>Ingredients:</h3>
<table id ="ingredients">
<tr>
<th>Ingredient</th>
<th>Quantity</th>
</tr>
<tr>
{% for ingredient in recipe.ingredient_set.all %}
</tr>
<tr>
<td> {{ ingredient.name }} </td>
<td>{{ ingredient.quantity}} {% if ingredient.units == "UN" %}{% else %}{{ ingredient.get_units_display.title }}{% endif %}</td>
</tr>
{% endfor %}
</table>
<h3>Tools:</h3>
Table for tools goes here
Solution
If a recipe can use many tools and single tools can be used in many recipes, then you have a many-to-many relationship and can create that as per the docs https://docs.djangoproject.com/en/4.0/topics/db/examples/many_to_many/
In a nutshell, place the following in your recipe model and migrate your DB
tools = models.ManyToManyField(Tools)
This creates a behind-the-scenes table that links recipe ids and tool ids for efficient lookups. You can handle this table manually if you need to define other things about the relationship, but you don’t have to worry about it if that isn’t an issue.
Once in place, you can pass recipe.tools.all() to your template and cycle through that.
Answered By – SamSparx
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0