如何在Django/Python中实现动态视图?寻求技术指导
Django动态视图实现指导(根据下拉菜单展示对应数据)
先看你代码里存在的几个核心问题:
- 视图函数参数错误:Django视图的第一个参数必须是
request,不是self,self是类方法专用的,函数视图不需要 - 未获取前端传递的选择值:代码里的
dropdown变量未定义,得从请求里提取前端传过来的参数 - 代码极度冗余:一堆重复的
elif逻辑完全可以用字典映射简化 - 拼写错误:比如判断条件里的
AplasticAneamia和导入的AplasticAnaemia不一致,Sicklecelldiseases和导入的Sicklecelldisease多了个s,会导致匹配失败 - 返回格式不友好:直接返回
HttpResponse(x)用户看不到友好展示,建议返回JSON或者渲染模板
第一步:修正并优化视图函数
先把导入的别名改清晰,再用字典映射类名到对应类,砍掉冗余代码:
from django.shortcuts import render from django.http import HttpResponseBadRequest, JsonResponse from Healthcare.Conditions.Blood.blood import ( AcuteMyeloidLeukemia, ChronicMyeloidLeukemia, AcuteLymphoblasticLeukemia, NonHodkinLeukemia, HodgkinLymphoma, Myeloma, MyelodysplasticSyndrome, AplasticAnaemia, Autoimmunediseases, Sicklecelldisease, Thalassaemia ) # 建立类名到类的映射字典,替代一堆elif CONDITION_CLASSES = { 'AcuteMyeloidLeukemia': AcuteMyeloidLeukemia, 'ChronicMyeloidLeukemia': ChronicMyeloidLeukemia, 'AcuteLymphoblasticLeukemia': AcuteLymphoblasticLeukemia, 'NonHodkinLeukemia': NonHodkinLeukemia, 'HodgkinLymphoma': HodgkinLymphoma, 'Myeloma': Myeloma, 'MyelodysplasticSyndrome': MyelodysplasticSyndrome, 'AplasticAnaemia': AplasticAnaemia, 'Autoimmunediseases': Autoimmunediseases, 'Sicklecelldisease': Sicklecelldisease, 'Thalassaemia': Thalassaemia } def symptoms_view(request): # 从GET请求里取下拉菜单的选择值,也可以用POST,看前端提交方式 dropdown_value = request.GET.get('condition') if not dropdown_value: return HttpResponseBadRequest("请选择一个疾病类型") # 从映射字典里获取对应类 ConditionClass = CONDITION_CLASSES.get(dropdown_value) if not ConditionClass: return HttpResponseBadRequest("无效的疾病类型") # 实例化并获取症状数据 condition_instance = ConditionClass() symptoms = condition_instance.my_symptoms().values() # 返回JSON格式方便前端处理;如果要渲染模板就用render return JsonResponse(list(symptoms), safe=False)
第二步:前端实现下拉菜单交互
两种方案选适合你的:
方案1:表单提交(页面刷新)
创建模板symptoms.html,用表单提交选择值:
<!DOCTYPE html> <html> <head> <title>疾病症状查询</title> </head> <body> <form method="get" action="{% url 'symptoms_view' %}"> <label for="condition">选择疾病类型:</label> <select name="condition" id="condition" onchange="this.form.submit()"> <option value="">请选择</option> <option value="AcuteMyeloidLeukemia">急性髓系白血病</option> <option value="ChronicMyeloidLeukemia">慢性髓系白血病</option> <!-- 其他疾病选项依次添加 --> </select> </form> {% if symptoms %} <h3>症状列表:</h3> <ul> {% for symptom in symptoms %} <li>{{ symptom }}</li> {% endfor %} </ul> {% endif %} </body> </html>
对应的视图要改成渲染模板:
def symptoms_view(request): dropdown_value = request.GET.get('condition') symptoms = [] if dropdown_value: ConditionClass = CONDITION_CLASSES.get(dropdown_value) if ConditionClass: condition_instance = ConditionClass() symptoms = list(condition_instance.my_symptoms().values()) return render(request, 'symptoms.html', {'symptoms': symptoms})
方案2:AJAX异步加载(无刷新)
用JS监听下拉菜单变化,异步请求数据并展示:
<!DOCTYPE html> <html> <head> <title>疾病症状查询</title> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> </head> <body> <label for="condition">选择疾病类型:</label> <select name="condition" id="condition"> <option value="">请选择</option> <option value="AcuteMyeloidLeukemia">急性髓系白血病</option> <option value="ChronicMyeloidLeukemia">慢性髓系白血病</option> <!-- 其他疾病选项依次添加 --> </select> <div id="symptoms-container"></div> <script> $('#condition').change(function() { var condition = $(this).val(); if (!condition) { $('#symptoms-container').empty(); return; } $.ajax({ url: "{% url 'symptoms_view' %}", data: { 'condition': condition }, success: function(data) { var html = '<h3>症状列表:</h3><ul>'; data.forEach(function(symptom) { html += '<li>' + symptom + '</li>'; }); html += '</ul>'; $('#symptoms-container').html(html); }, error: function() { $('#symptoms-container').html('<p>加载失败,请重试</p>'); } }); }); </script> </body> </html>
这种方案用之前返回JsonResponse的视图即可。
第三步:配置URL
在app的urls.py里添加路由:
from django.urls import path from . import views urlpatterns = [ path('symptoms/', views.symptoms_view, name='symptoms_view'), ]
额外注意点
- 确保
my_symptoms()方法返回可迭代对象(比如字典),这样values()能正常取值 - 生产环境建议对前端传入的参数做更严格校验,防止恶意请求
- 可以从
CONDITION_CLASSES的键动态生成下拉菜单选项,避免前端硬编码
内容的提问来源于stack exchange,提问作者Neil Faulkner
相关产品推荐
相关产品推荐

