Volker Petersen
Volker Petersen

Reputation: 293

Django html template getting data from nested dictionary

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}}" class="grid-item {{recipe.category}} {{recipe.submitted_by}}">
        <div class="row">
            <div class="col-12 col-md-3 ingredients">
                {% 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:

Debug info showing content of the dictionary 'content'

What do I need to do to fix this problem?

Upvotes: 0

Views: 99

Answers (2)

Volker Petersen
Volker Petersen

Reputation: 293

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 class="col-12 col-md-3 ingredients">
    {% 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.

Upvotes: 1

nigel239
nigel239

Reputation: 1755

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 %}

Upvotes: 0

Related Questions