Django HTML模板无法读取嵌套字典中模型字段的问题求助
Django模板无法显示关联模型字段的解决方案
问题背景
在Django项目中,通过context字典传递嵌套结构数据到HTML模板时,无法显示视图传递的模型字段,仅输出{% empty %}分支内容。已确认数据库数据正确,QuerySet已存入字典并传递到模板。
相关代码
模型定义(models.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'
视图代码(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)
模板代码(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 %}
错误原因
模板中ingredients.recipe.id的写法完全错误:ingredients是一个以菜谱ID为键的字典,而不是对象属性。这种写法无法正确获取对应菜谱的Ingredients QuerySet,导致进入{% empty %}分支。
解决方案
方案1:修复模板的字典取值方式
将模板中的循环行修改为以下两种写法之一:
写法A:使用Django模板的get过滤器
{% for item in ingredients|get:recipe.id %} {{ item.ingredient }}<br> {% empty %} <span>No ingredients provided</span> {% endfor %}
写法B:直接使用字典键取值(Django模板支持方括号语法)
{% for item in ingredients[recipe.id] %} {{ item.ingredient }}<br> {% empty %} <span>No ingredients provided</span> {% endfor %}
方案2:利用模型关联优化代码(更高效推荐)
模型中已经定义了related_name='ingredients',可以直接通过菜谱对象获取关联的食材,无需手动构建字典,还能避免N+1查询问题:
修改视图代码(views.py)
# 使用prefetch_related预取关联的ingredients,提升性能 recipes = Recipes.objects.all().order_by("category", "title").prefetch_related('ingredients') content['recipes'] = recipes return render( request, "myApp/recipes.html", context=content)
修改模板代码(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 item in recipe.ingredients.all %} {{ item.ingredient }}<br> {% empty %} <span>No ingredients provided</span> {% endfor %} </div> </div> {% endfor %}
说明
方案2不仅简化了代码,还通过prefetch_related一次性加载所有关联数据,避免了循环中多次查询数据库的性能问题,是更推荐的实现方式。
内容的提问来源于stack exchange,提问作者Volker Petersen
相关产品推荐
相关产品推荐

