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

Django视图上下文未在模板渲染问题求助

问题描述

使用Python(Django框架)开发自定义报表,该逻辑在其他应用中可正常运行,但当前应用里,视图通过render传递的上下文无法在模板中渲染。Python解析器已打印出查询结果,但模板中无法显示对应内容。

相关代码

Models.py

class NegativeBehaviour(models.Model):
    behaviour = models.CharField(max_length=250, blank=True, unique=True, null=True, choices=NegativeBehaviourType)
    behaviourdesc = models.TextField(max_length=2500)
    subjects = models.CharField(max_length=250, choices=Subjects, default=None)
    module = models.CharField(max_length=250, choices=Modules, default=None)
    students = models.ForeignKey(CustomUser, related_name = "Negative_Behaviour_Students", on_delete = models.CASCADE)
    staff = models.ForeignKey(CustomUser, related_name = "Negative_Behaviour_Teachers", on_delete = models.CASCADE)
    C1 = BehaviourManagerC1()
    C2 = BehaviourManagerC2()
    C3 = BehaviourManagerC3()
    C4 = BehaviourManagerC4()
    C5 = BehaviourManagerC5()
    
    class Meta:
        verbose_name = "Behaviour",
        verbose_name_plural = "Behaviours"
        
    def __str__(self):
        return self.behaviour
        return str(self.user.id)
    
class PositiveBehaviour(models.Model):
    behaviour = models.CharField(max_length=250, blank=True, unique=True, null=True, choices=PositiveBehaviourType)
    behaviourdesc = models.TextField(max_length=2500)
    subjects = models.CharField(max_length=250, choices=Subjects, default=None)
    module = models.CharField(max_length=250, choices=Modules, default=None)
    students = models.ForeignKey(CustomUser, related_name = "Positive_Behaviour_Students", on_delete = models.CASCADE)
    staff = models.ForeignKey(CustomUser, related_name = "Positive_Behaviour_Teachers", on_delete = models.CASCADE)
    A1 = BehaviourManagerA1()
    A2 = BehaviourManagerA2()
    A3 = BehaviourManagerA3()

    class Meta:
        verbose_name = "Behaviour",
        verbose_name_plural = "Behaviours"
        
    def __str__(self):
        return self.behaviour
        return str(self.user.id)

behaviouralData.py

import pandas as pd
import math
import pyodbc
import sqlalchemy as sa
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.platypus import *
from reportlab.lib.styles import *
from reportlab.lib import *
from django.contrib.auth.models import User
import requests


class Behaviour():

    def __init__(self, result1=None, result2=None, body=None, Core=None, CoreQA=None, Specialist=None, SpecialistQA=None, DesignandMake=None, DesignandMakeQA=None, Nonexamassessment=None, NonexamassessmentQA=None):
        self.title = title
        self.subtitles = subtitles
        self.body = body
        self.Core = Core
        self.CoreQA = CoreQA
        self.Specialist = Specialist
        self.SpecialistQA = SpecialistQA
        self.DesignandMake = DesignandMake
        self.DesignandMakeQA = DesignandMakeQA
        self.Nonexamassessment = Nonexamassessment
        self.NonexamassessmentQA = NonexamassessmentQA
        
class Negative(Behaviour):
        
    def GradeOutputs(self, User):
        cnxn_str = ("Driver={SQL Server};")
                "Server=127.0.0.1;"
                "Database=Healthcare;"
                "Trusted_Connection=yes;")
        cnxn = pyodbc.connect(cnxn_str)
        cursor = cnxn.cursor()
        Core = cursor.execute("SELECT * FROM dbo.behaviour_negativebehaviour WHERE students_id = '%s'" %User)
        Result1 = cursor.fetchall()
        for row in Result1:
            print(row[0])
            print("\n")
        cnxn.commit()
        cnxn.close
        return Result1
        
class Positive(Behaviour):

    def GradeOutputs(self, User):
        cnxn_str = ("Driver={SQL Server};")
                "Server=127.0.0.1;"
                "Database=Healthcare;"
                "Trusted_Connection=yes;")
        cnxn = pyodbc.connect(cnxn_str)
        cursor = cnxn.cursor()
        Shakespheare = cursor.execute("SELECT * FROM dbo.behaviour_positivebehaviour WHERE students_id = '%s'" %User)
        Result2 = cursor.fetchall()
        for row in Result2:
            print(row[0])
            print("\n")
        cnxn.commit()
        cnxn.close
        return Result2

views.py

def Reports(request):
    User=request.user.id
    if request.method == 'GET':
        sampleset = a()
        one = sampleset.GradeOutputs(User)
        sampleset = b()
        two = sampleset.GradeOutputs(User)
        print(one, two)
    elif request.method == 'POST':
        sampleset = a()
        one = sampleset.GradeOutputs(User)
        sampleset = b()
        two = sampleset.GradeOutputs(User)  
        print(one, two)
    return render(request, 'Behaviour/Report.html', context = {"one":one, "two":two})    

Behaviour/Report.html

{% extends "base.html" %}
{% load static %}
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href =\".\grid.css\" rel=\"stylesheet\">
    <meta charset="utf-8" />
    <title>Subjects</title>
</head>

<body>
{% block content %}
<div class = "div-1">
    <h1>Welcome to Inspired Intelligence - Education</h1>
    <a href={% url 'Education:School:Grades:Home' %}>Grade Home</a>
    <br>
    <h2>Behaviour Report</h2>
    <h3>Negative Behaviour:</h3>
    <h2>{{one.as_p}}</h2>
    <br>
    <h3>Positive Behaviour</h3>
    <h2>{{two.as_p}}</h2>
    <br>
    <br>
</div>
{% endblock content %}
</body>
</html>
问题分析与解决方案

核心问题

  1. 模板渲染逻辑错误:one和two是pyodbc的fetchall()返回的元组列表,并非Django QuerySet对象,不存在as_p()方法,因此{{one.as_p}}无法渲染内容。
  2. 类实例化错误:视图中sampleset = a()和sampleset = b()是无效调用,应对应behaviouralData.py中定义的Negative()和Positive()类。
  3. 数据库连接字符串语法错误:behaviouralData.py中cnxn_str的括号未正确闭合,会导致数据库连接失败。
  4. SQL注入风险:直接用字符串拼接'%s' %User传递参数,不符合参数化查询规范,存在安全漏洞。

修复步骤

1. 修复视图中的类实例化

修改views.py,导入正确的类并实例化:

from .behaviouralData import Negative, Positive

def Reports(request):
    user_id = request.user.id
    one = None
    two = None
    if request.method in ['GET', 'POST']:
        sampleset = Negative()
        one = sampleset.GradeOutputs(user_id)
        sampleset = Positive()
        two = sampleset.GradeOutputs(user_id)  
        print(one, two)
    return render(request, 'Behaviour/Report.html', context={"one": one, "two": two})    

2. 调整模板以遍历结果

针对元组列表的特性,在模板中循环输出内容:

{% extends "base.html" %}
{% load static %}
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="./grid.css" rel="stylesheet">
    <meta charset="utf-8" />
    <title>Subjects</title>
</head>

<body>
{% block content %}
<div class="div-1">
    <h1>Welcome to Inspired Intelligence - Education</h1>
    <a href="{% url 'Education:School:Grades:Home' %}">Grade Home</a>
    <br>
    <h2>Behaviour Report</h2>
    <h3>Negative Behaviour:</h3>
    {% if one %}
        {% for row in one %}
            <p>行为类型: {{ row.1 }}, 描述: {{ row.2 }}, 科目: {{ row.3 }}</p>
            <!-- 根据数据库表字段顺序调整索引 -->
        {% endfor %}
    {% else %}
        <p>无负面行为记录</p>
    {% endif %}
    <br>
    <h3>Positive Behaviour</h3>
    {% if two %}
        {% for row in two %}
            <p>行为类型: {{ row.1 }}, 描述: {{ row.2 }}, 科目: {{ row.3 }}</p>
            <!-- 根据数据库表字段顺序调整索引 -->
        {% endfor %}
    {% else %}
        <p>无正面行为记录</p>
    {% endif %}
    <br>
    <br>
</div>
{% endblock content %}
</body>
</html>

3. 修复数据库连接与查询安全问题

修改behaviouralData.py中的连接字符串和查询语句:

class Negative(Behaviour):
    def GradeOutputs(self, user_id):
        cnxn_str = (
            "Driver={SQL Server};"
            "Server=127.0.0.1;"
            "Database=Healthcare;"
            "Trusted_Connection=yes;"
        )
        cnxn = pyodbc.connect(cnxn_str)
        cursor = cnxn.cursor()
        # 使用参数化查询避免SQL注入
        cursor.execute("SELECT * FROM dbo.behaviour_negativebehaviour WHERE students_id = ?", (user_id,))
        Result1 = cursor.fetchall()
        for row in Result1:
            print(row[0])
            print("\n")
        cnxn.close()  # 补充括号,正确调用关闭方法
        return Result1

Positive类的GradeOutputs方法做相同修改。

4. 推荐改用Django ORM查询(更优方案)

既然已定义Django模型,直接用ORM替代pyodbc查询,更符合Django规范且安全:

# 直接在视图中查询,无需behaviouralData.py中的GradeOutputs方法
from .models import NegativeBehaviour, PositiveBehaviour

def Reports(request):
    user_id = request.user.id
    one = NegativeBehaviour.objects.filter(students_id=user_id).all()
    two = PositiveBehaviour.objects.filter(students_id=user_id).all()
    print(one, two)
    return render(request, 'Behaviour/Report.html', context={"one": one, "two": two})

此时模板可直接访问模型属性:

<h3>Negative Behaviour:</h3>
{% if one %}
    {% for item in one %}
        <p>行为类型: {{ item.behaviour }}, 描述: {{ item.behaviourdesc }}, 科目: {{ item.subjects }}</p>
    {% endfor %}
{% else %}
    <p>无负面行为记录</p>
{% endif %}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:16:03