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

Django带复选框的CSV下载问题:表单清空与URL跳转无法获选中值

解决选中条目导出CSV的表单问题

问题背景

需要导出页面中复选框选中的条目为CSV文件,现有两种方案均存在问题:

  1. 表单提交方案:能获取选中值,但提交后表单被清空,无法再次下载
  2. URL跳转方案:无法获取复选框选中值,因为表单未提交

复选框代码:

<td><input type="checkbox" name="checked" value="{{ row.CI }}" class="checkboxAll"></td>

可行解决方案

方案1:表单提交+新窗口打开(保留原页面状态)

给表单添加target="_blank"属性,让表单在新窗口提交处理下载,原页面的复选框状态不会被清空,可多次点击下载。

修改后的表单按钮代码:

<!-- 确保form标签添加target="_blank" -->
<form method="GET" target="_blank">
  <!-- 其他表单内容 -->
  <button type="submit" class="btn" value="csv_download" name="csv_download">
    <i class="fa-solid fa-file-csv" style="padding-left: 5px; font-size: 9px;"></i> csv_form
  </button>
</form>

视图代码调整(确保过滤选中条目):

def v_base(request):
    if request.GET.get('csv_download'):
        checked = request.GET.getlist('checked')
        response = download_csv(request, checked)
        return response

def download_csv(request, checked=None):
    checked = checked or request.GET.getlist('checked')
    db_sel_columns, column = get_column_selected(request)
    # 仅保留选中的条目
    rows = Vbase.objects.filter(CI__in=checked).values(*db_sel_columns)
    rows_filter = baseFilter(request.GET, queryset=rows)

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=download.csv'
    writer = csv.writer(response)
    writer.writerow(db_sel_columns)
    for row in rows_filter.qs:
        writer.writerow([row['CI'], row['Description']])
    return response

方案2:JavaScript收集选中值,拼接GET参数跳转

通过JS获取所有选中的复选框值,拼接到下载URL的查询参数中,跳转后视图可正常获取checked值。

修改后的按钮代码:

<button type="button" class="btn" onclick="downloadSelectedCsv()">
  <i class="fa-solid fa-file-csv" style="padding-left: 5px; font-size: 9px;"></i> csv_download
</button>

<script>
function downloadSelectedCsv() {
    // 获取所有选中的复选框
    const checkedItems = document.querySelectorAll('input[name="checked"]:checked');
    // 提取选中值组成数组
    const checkedValues = Array.from(checkedItems).map(item => item.value);
    // 拼接原有查询参数
    const existingParams = new URLSearchParams(window.location.search);
    checkedValues.forEach(val => existingParams.append('checked', val));
    // 生成下载URL并打开新窗口
    const downloadUrl = "{% url 'download_csv' %}?" + existingParams.toString();
    window.open(downloadUrl, '_blank');
}
</script>

视图代码保持原逻辑即可:

def download_csv(request):
    checked = request.GET.getlist('checked')
    db_sel_columns, column = get_column_selected(request)
    rows = Vbase.objects.filter(CI__in=checked).values(*db_sel_columns)
    rows_filter = baseFilter(request.GET, queryset=rows)

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=download.csv'
    writer = csv.writer(response)
    writer.writerow(db_sel_columns)
    for row in rows_filter.qs:
        writer.writerow([row['CI'], row['Description']])
    return response

方案3:AJAX无刷新下载

如果需要页面无刷新完成下载,可通过AJAX请求获取CSV内容,再通过Blob创建下载链接:

JS代码:

<button type="button" class="btn" onclick="downloadSelectedCsvAjax()">
  <i class="fa-solid fa-file-csv" style="padding-left: 5px; font-size: 9px;"></i> csv_ajax
</button>

<script>
function downloadSelectedCsvAjax() {
    const checkedItems = document.querySelectorAll('input[name="checked"]:checked');
    const checkedValues = Array.from(checkedItems).map(item => item.value);
    const formData = new FormData();
    
    checkedValues.forEach(val => formData.append('checked', val));
    // 添加原有查询参数
    const existingParams = new URLSearchParams(window.location.search);
    existingParams.forEach((val, key) => formData.append(key, val));

    fetch("{% url 'download_csv' %}", {
        method: 'POST',
        body: formData,
        headers: {
            'X-CSRFToken': '{{ csrf_token }}' // Django需携带CSRF令牌
        }
    }).then(response => response.blob())
      .then(blob => {
          const url = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = url;
          a.download = 'download.csv';
          document.body.appendChild(a);
          a.click();
          // 清理临时链接
          URL.revokeObjectURL(url);
          document.body.removeChild(a);
      });
}
</script>

视图修改为支持POST请求:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def download_csv(request):
    # 兼容GET和POST方式获取选中值
    if request.method == 'POST':
        checked = request.POST.getlist('checked')
    else:
        checked = request.GET.getlist('checked')
    
    db_sel_columns, column = get_column_selected(request)
    rows = Vbase.objects.filter(CI__in=checked).values(*db_sel_columns)
    rows_filter = baseFilter(request.GET if request.method == 'GET' else request.POST, queryset=rows)

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=download.csv'
    writer = csv.writer(response)
    writer.writerow(db_sel_columns)
    for row in rows_filter.qs:
        writer.writerow([row['CI'], row['Description']])
    return response

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:57:22