Django中如何基于CreateView表单选择过滤ListView列表?
解决方案
问题A:客户过滤报错修复
报错核心原因是customer_id为数值类型,而includes()是字符串专属方法,直接调用会触发类型错误。同时当前过滤逻辑完全错误——应该用选中的客户ID匹配Program的customer_id,而非用Program名称匹配选中值;此外下拉框应监听change事件(选值触发)而非click事件(点击就触发)。
问题B:显示客户名称而非ID
当前序列化数据仅包含customer_id,缺少客户名称字段。需要在视图层关联查询出CustomerName的company属性,前端直接调用该字段即可,且完全不影响基于customer_id的过滤逻辑。
修改后的完整代码
1. 视图代码(更新序列化逻辑)
import json from django.urls import reverse_lazy from django.views.generic import CreateView, ListView from .models import ProgramName class ProgramAddView(CreateView, ListView): template_name = 'app/ProgramAdd.html' form_class = Programform model = ProgramName success_url = reverse_lazy('Part Number Add') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 关联查询获取客户名称,只序列化需要的字段 program_data = ProgramName.objects.values('id', 'program', 'customer_id', 'customer__company') context["qs_json"] = json.dumps(list(program_data)) return context
2. HTML及JS代码(修正模板结构、过滤逻辑、显示内容)
{% extends 'base.html' %} {% block content %} <h2>Program</h2> <form method="post" class='formarea'> <div id='formarea' class='formdiv'> {{ form.media.js }} <table> {{ form.as_table }} </table> {% csrf_token %} <button type="submit">Save</button> <a href="{% url 'HomePage' %}">Nevermind</a> </div> </form> <h2>Program List</h2> <table class="table table-hover"> <thead> <tr> <th scope="col">Program</th> <th scope="col">Customer</th> </tr> </thead> <tbody id="program-table-body"> <!-- 初始渲染所有数据 --> {% for item in object_list %} <tr> <td>{{ item.program }}</td> <td>{{ item.customer.company }}</td> </tr> {% empty %} <tr> <td colspan="2">No objects yet.</td> </tr> {% endfor %} </tbody> </table> {% endblock %} {% block scripts %} <script> // 用safe过滤器避免Django自动转义引号,无需手动替换& const rdata = JSON.parse('{{ qs_json|safe }}'); const customerSelect = document.getElementById('id_customer'); const tableBody = document.getElementById('program-table-body'); // 监听下拉框选值事件 customerSelect.addEventListener('change', () => { const selectedCustomerId = parseInt(customerSelect.value); tableBody.innerHTML = ""; // 过滤逻辑:匹配数值类型的customer_id,未选则显示全部 const filteredArr = selectedCustomerId ? rdata.filter(program => program.customer_id === selectedCustomerId) : rdata; if (filteredArr.length > 0) { filteredArr.forEach(program => { const row = document.createElement('tr'); row.innerHTML = ` <td><b>${program.program}</b></td> <td><b>${program.customer__company}</b></td> `; tableBody.appendChild(row); }); } else { tableBody.innerHTML = '<tr><td colspan="2"><b>No results found...</b></td></tr>'; } }); </script> {% endblock scripts %}
额外优化说明
- 模板中使用
{{ qs_json|safe }}替代手动转义,更安全简洁 - 将列表改为表格结构,贴合业务展示逻辑
- 增加“未选择客户时显示全部数据”的逻辑
- 用
forEach替代map(仅渲染无需返回数组),性能更优
内容的提问来源于stack exchange,提问作者ItchyPancake
相关产品推荐
相关产品推荐

