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>
问题分析与解决方案
核心问题
- 模板渲染逻辑错误:
one和two是pyodbc的fetchall()返回的元组列表,并非Django QuerySet对象,不存在as_p()方法,因此{{one.as_p}}无法渲染内容。 - 类实例化错误:视图中
sampleset = a()和sampleset = b()是无效调用,应对应behaviouralData.py中定义的Negative()和Positive()类。 - 数据库连接字符串语法错误:
behaviouralData.py中cnxn_str的括号未正确闭合,会导致数据库连接失败。 - 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
相关产品推荐
相关产品推荐

