Django中key_id比较无输出问题:原因排查与解决方法
从Data表和Key表获取数据,先在Data表按username筛选数据,再通过筛选后data中的key_id在Key表查询对应的key_name,后端代码如下:
data=Data.objects.filter(username=username) key=Key.objects.filter(key_id__in=data.values_list('key_id')) data = {'data':data, 'key':key} return render(request,'form.html', data)
在HTML模板中,尝试用嵌套循环匹配展示对应Key表的key_name,代码如下:
{% for data in data %} {% for key in key %} {% if data.key_id == key.key_id %} {{ key.key_name }} {% endif %} {% endfor %} {% endfor %}
但这段代码无任何输出。单独在if标签外输出{{ key.key_id }},结果为:
001 002 001 002
单独输出{{ data.key_id }},结果为:
001 001 002 002
请问为什么比较时无输出?该如何解决?
原因分析
核心问题是变量类型不匹配:
虽然data.key_id和key.key_id显示的内容一致,但实际存储的类型可能不同——比如Data表的key_id是字符串类型,Key表的key_id是整数类型,或者反过来。Django模板中的==是严格类型匹配,类型不同即使值看起来一样,也会判定为不相等,导致if条件永远不成立,自然没有输出。
另外,模板循环里的变量名data和key和上下文传入的变量重名了,会覆盖原变量,这也是潜在的问题(比如第一次循环后,原data列表会被单个data对象替换,后续循环逻辑会出错)。
解决方法
方法一:后端关联查询(推荐,更高效)
不用前端手动循环匹配,利用Django ORM的关联查询直接把key_name带到结果里,既避免类型问题,又提升性能:
场景1:Data表的key_id是外键关联到Key表
如果已经在Data模型里定义了外键关联Key表(比如key = models.ForeignKey(Key, on_delete=models.CASCADE, db_column='key_id')),可以直接用select_related预加载关联数据:
data = Data.objects.filter(username=username).select_related('key') data = {'data': data} return render(request, 'form.html', data)
模板代码简化为:
{% for item in data %} {{ item.key.key_name }} {% endfor %}
场景2:无外键关联,用annotate关联查询
如果没有外键,可以通过annotate直接查询出对应key_name:
from django.db.models import F data = Data.objects.filter(username=username).annotate( key_name=Key.objects.filter(key_id=F('key_id')).values('key_name')[:1] ) data = {'data': data} return render(request, 'form.html', data)
模板代码简化为:
{% for item in data %} {{ item.key_name }} {% endfor %}
方法二:前端统一类型后比较(临时方案)
如果暂时不想修改后端,可以在模板里把两个值转换成相同类型(比如都转成字符串)再比较,同时修改循环变量名避免重名:
{% for data_item in data %} {% for key_item in key %} {% if data_item.key_id|stringformat:"s" == key_item.key_id|stringformat:"s" %} {{ key_item.key_name }} {% endif %} {% endfor %} {% endfor %}
内容的提问来源于stack exchange,提问作者user58519

