Home > Mobile >  Django html template getting data from nested dictionary
Django html template getting data from nested dictionary

Time:09-16

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:

Debug info showing content of the dictionary 'content'

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