Django ListView选中项导出CSV失败,无法获取选中值
解决Django选中记录导出CSV时无法获取选中项的问题
问题根源
- 表单结构错误:每条记录单独嵌套
<form>标签,导出按钮不在任何表单范围内,点击按钮仅触发GET跳转,不会提交复选框选中数据 - 参数名称不匹配:模板中复选框
name为form.choices,但后端视图用request.GET.getlist('choices')获取,名称不一致 - 视图逻辑错误:CSV写入循环中误用
cd_fields(整个查询集)替代单个记录对象;响应的Content-Type设置格式错误
修复步骤
1. 修正模板表单与复选框
将所有复选框放入同一个表单,导出按钮作为表单提交按钮,同时统一复选框name为choices:
<!-- list_cds.html --> ... {% block content %} <br> <form method="POST" action="{% url 'export_to_csv' %}"> {% csrf_token %} <button type="submit" value="listbatchview">Batch Export CSV</button> <TABLE id="list_table"> <TR BGCOLOR="#B0B0FF"> <TD></TD> <TD></TD> <TD ALIGN="Center">Artist Name</TD> <TD ALIGN="Center">Cd Name</TD> <TD BGCOLOR="99CCFF" ALIGN="Center">Cd Length</TD> <TD BGCOLOR="#CC99CC" ALIGN="Center">Run time</TD> <TD BGCOLOR="#8DF1BF" ALIGN="Center">Remaining Time</TD> </TR> {% for cd in object_list %} <TR BGCOLOR="#B0B0FF"> <TD ALIGN="Center" rowspan="1" height="33" width="33"> <input type="checkbox" value="{{cd.pk }}" name="choices"> <TD ALIGN="Center" rowspan="1" height="33" width="33"> <A href="{% url 'cd_update' cd.pk %}"> <IMG SRC="{% static 'images/edit.gif' %}"> </A> </TD> <TD ALIGN="CENTER">{{ cd.artist_name|truncatechars:30 }}</TD> <TD ALIGN="CENTER">{{ cd.cd_title }}</TD> <TD BGCOLOR="#99CCFF" ALIGN="CENTER">{{ cd.cd_total_time|time:"H:i:s" }}</TD> <TD BGCOLOR="#CC99CC" ALIGN="CENTER">{{ cd.cd_run_time|time:"H:i:s" }}</TD> {% if cd.cd_run_time_delta > cd.cd_total_time_delta %} <TD BGCOLOR="#8DF1BF" ALIGN="CENTER"> (-{{ cd.cd_remaining_time|time:"H:i:s" }})</TD> {% else %} <TD BGCOLOR="#8DF1BF" ALIGN="CENTER"> {{ cd.cd_remaining_time|time:"H:i:s" }}</TD> {% endif %} </TR> {% endfor %} </TABLE> </form> {% endblock content %}
2. 修正导出视图逻辑
改为从request.POST获取选中项,修复CSV写入错误,调整响应格式:
# views.py import csv from django.http import HttpResponse, HttpResponseRedirect from django.urls import reverse from .models import Cd class List_Cds(ListView): model = Cd template_name = 'list_cds.html' def export_to_csv(request): if request.method == 'POST': choices = request.POST.getlist('choices') print("In export_to_csv choices selected were: %s" % choices) cd_export = Cd.objects.filter(id__in=choices) response = HttpResponse(content_type='text/csv') response['Content-Disposition']= 'attachment; filename=cdlist.csv' writer = csv.writer(response) writer.writerow(['Artist', 'Cd Title', 'CD Run Time']) # 遍历单个记录写入CSV for cd in cd_export.values_list('artist_name','cd_title', 'cd_total_time'): writer.writerow(cd) return response # GET请求重定向回列表页 return HttpResponseRedirect(reverse('list_cds'))
3. 可选:表单验证优化(非必须)
如果要使用定义好的BatchListForm做验证,可修改视图并传递表单到模板:
# views.py import csv from django.http import HttpResponse, HttpResponseRedirect from django.urls import reverse from .models import Cd from .forms import BatchListForm class List_Cds(ListView): model = Cd template_name = 'list_cds.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 初始化表单,传入所有CD的ID作为选项 context['batch_form'] = BatchListForm(choices=[(cd.pk, cd.cd_title) for cd in self.get_queryset()]) return context def export_to_csv(request): if request.method == 'POST': form = BatchListForm(request.POST) if form.is_valid(): choices = form.cleaned_data['choices'] print("In export_to_csv choices selected were: %s" % choices) cd_export = Cd.objects.filter(id__in=choices) response = HttpResponse(content_type='text/csv') response['Content-Disposition']= 'attachment; filename=cdlist.csv' writer = csv.writer(response) writer.writerow(['Artist', 'Cd Title', 'CD Run Time']) for cd in cd_export.values_list('artist_name','cd_title', 'cd_total_time'): writer.writerow(cd) return response return HttpResponseRedirect(reverse('list_cds'))
验证效果
修改完成后,选中复选框点击导出按钮,服务器日志将打印选中的ID列表,生成的CSV文件会包含选中记录的完整数据。
内容的提问来源于stack exchange,提问作者Todd B
相关产品推荐
相关产品推荐

