I'm having a problem with an html template not displaying model fields sent from a view in a context dictionary called content. This dictionary holds a nested dictionary like:
content = {'indredients': {recipe id1: QuerySet 1,
recipe id2: QuerySet 2, ... } }
In model.py:
class Ingredients(models.Model):
id = models.IntegerField(primary_key=True)
recipe = models.ForeignKey(Recipes, on_delete=models.CASCADE, related_name='ingredients')
ingredient = models.CharField(max_length=128)
class Meta:
managed = False
db_table = 'ingredients'
verbose_name_plural = 'Ingredients'
def __str__(self):
return f"{self.id} {self.recipe} - {self.ingredient}"
class Recipes(models.Model):
id = models.IntegerField(primary_key=True)
category = models.TextField(db_column='Category', null=False)
submitted_by = models.TextField(
db_column='Submitted_By', null=False)
origin = models.TextField(db_column='Origin', null=False)
title = models.TextField(db_column='Title', null=False)
directions = models.TextField(
db_column='Directions', null=False)
comments = models.TextField(db_column='Comments', null=False)
created = models.DateTimeField(null=False)
modified = models.DateTimeField(null=True)
def __str__(self):
return f"{self.id} - {self.title}"
class Meta:
managed = False
db_table = 'recipes'
verbose_name_plural = 'Recipes'
In views.py:
recipes = Recipes.objects.all().order_by(
"category", "title")
content['ingredients'] = {}
for recipe in recipes:
ingredients = Ingredients.objects.filter(
recipe=recipe.id).order_by("id")
content['ingredients'][recipe.id] = ingredients
content['recipes'] = recipes
return render(
request,
"myApp/recipes.html",
context=content)
In recipes.html:
{% for recipe in recipes %}
<div id="id-{{recipe.id}}" >
<div >
<div >
{% for queryQbject in ingredients.recipe.id %}
{{ queryQbject.ingredient }}<br>
{% empty %}
<span>No ingredients provided</span>
{% endfor %}
</div>
</div>
{% endfor %}
I do get the correct data from the sqlite database and the Queryset is stored in the dictionary 'content' that is passed correctly into the html file. However, the html template doesn't display any of the data and only prints the 'No ingredients provided' {% empty %} case.
See debug info:
What do I need to do to fix this problem?
CodePudding user response:
nigel239's answer got me thinking and researching some more. I found this post https://fedingo.com/how-to-lookup-dictionary-value-with-key-in-django-template/ to write a custom filter to lookup a dictionary value with a key.
This is my custom_tags.py:
@register.filter
def get_item(dictionary, key):
try:
key = int(key)
value = dictionary.get(key)
except:
value = None
return value
and my updated recipes.html:
<div >
{% for queryset in ingredients|get_item:recipe.id %}
{{ queryset.ingredient }}<br>
{% empty %}
<span>No ingredients provided</span>
{% endfor %}
</div>
Now the code correctly pulls all the ingredients from the Django Queryset that was passed into the html template in a dictionary called 'ingredients' using the 'recipe.id' as keys.
CodePudding user response:
You are trying to loop over the ID, which is an integer. Not an iterable. Change
{% for queryQbject in ingredients.recipe.id %}
To
{% for queryQbject in ingredients.recipe %}