You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Django原生SQL查询结果渲染为表头与字段名一致的HTML表格

解决方案

方案说明

你使用Post.objects.raw()执行原生SQL返回的是RawQuerySet实例,每个元素依然是Post模型的实例,和普通ORM查询得到的对象属性完全一致,仅需补充表头元数据到上下文即可实现通用渲染,无需硬编码HTML表格结构。


1 视图层调整(含安全修复)

首先修正原有代码的SQL注入风险,不要用f字符串拼接SQL参数,改用raw方法的params传参,同时补充要展示的字段和表头信息到上下文:

def posts_discussione(request,pk):
    discussione = Discussione.objects.get(pk=pk)
    # 定义你需要展示的字段列表,可按需增减
    display_fields = ['autorePost', 'dataCreazione', 'contenuto']
    # 自动获取模型字段的verbose_name作为表头,也可自定义列表如['作者','日期','内容']
    headers = [Post._meta.get_field(field).verbose_name for field in display_fields]
    # 修复SQL注入风险,参数通过params传入
    posts = Post.objects.raw('SELECT * from forum_post where discussione_id = %s order by dataCreazione ASC', [pk])
    context = {
        'posts':posts,
        'discussione':discussione,
        'headers': headers,
        'display_fields': display_fields
    }
    return render(request,'posts-discussione.html',context)

2 模板层调整

修改HTML模板,动态生成表头和表格内容,无需硬编码字段:

<table>
    <thead>
        <tr>
        {% for header in headers %}
            <th>{{header}}</th>
        {% endfor %}
        </tr>
    </thead>
    <tbody>
    {% for post in posts %}
        <tr>
        {% for field in display_fields %}
            <td>{{ post|getattr:field }}</td>
        {% endfor %}
        </tr>
    {% endfor %}
    </tbody>
</table>

注:如果模板不支持getattr过滤器,可自行注册一个简单的模板过滤器,代码如下:

# 在你的app下的templatetags/custom_filters.py中添加
from django import template
register = template.Library()

@register.filter
def getattr(obj, attr):
    return getattr(obj, attr, '')

在模板顶部引入即可使用:{% load custom_filters %}


无模型绑定原生查询适配方案

如果你后续使用完全不绑定模型的原生查询(比如直接用connection.cursor执行SQL),可以直接获取表头和查询结果字典传入上下文:

from django.db import connection

def your_view(request):
    with connection.cursor() as cursor:
        cursor.execute('SELECT id,name,create_time from some_table where status = %s', [1])
        # 获取表头
        headers = [col[0] for col in cursor.description]
        # 获取结果字典列表
        rows = [dict(zip(headers, row)) for row in cursor.fetchall()]
    return render(request, 'your_template.html', {'headers': headers, 'rows': rows})

模板使用方式和上述一致,仅需把post|getattr:field换成{{ row.field }}即可。


内容的提问来源于stack exchange,提问作者kris9951

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:15:02