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

如何在Django中拼接两个QuerySet并写入xlwt格式Excel文件

问题根因

当前代码使用itertools.chain拼接两个QuerySet,会将Enrollment的查询结果作为独立行追加在Person数据之后,而非将对应Person行与Enrollment行合并为同一行,导致字段错位。同时原代码缺少return response语句,接口无法正常返回文件。

修正方案

根据模型关联关系可选择两种实现方式:

方式1:联表查询(推荐,适用于两表存在外键关联的场景)

假设Enrollment模型存在关联Person的外键字段person,直接通过ORM联表查询一次性获取所有字段,不存在行匹配错误风险:

import xlwt
from django.http import HttpResponse

def export_excel(request):
    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = 'filename="persondatas.xls"' 
    wb = xlwt.Workbook(encoding='utf-8')
    ws = wb.add_sheet('AllinOne')
    row_num = 0
    font_style = xlwt.XFStyle()
    font_style.font.bold = True

    # 已修正原表头birthpace拼写错误为birthplace
    columns = ['name', 'fulname', 'id', 'gender', 'country', 'birthdate', 'birthplace', 
              'departament', 'feature']
    for col_num in range(len(columns)):
        ws.write(row_num, col_num, columns[col_num], font_style)

    font_style = xlwt.XFStyle()
    # 外键反向引用字段名如果有自定义修改,同步调整enrollment__前缀后的字段名
    rows = Person.objects.values_list(
        'name', 'lastname', 'selfid', 'gender', 'country', 
        'dateofbirth', 'placeofbirth', 'enrollment__departament', 'enrollment__feature'
    )
    
    for row in rows: 
        row_num += 1
        for col_num in range(len(row)):
            ws.write(row_num, col_num, str(row[col_num]) if row[col_num] is not None else '', font_style)

    wb.save(response)
    return response

方式2:行合并(适用于两表无关联、查询结果行数一一对应的场景)

如果两表无关联,但查询返回行数相同、顺序一一对应,使用zip_longest合并每行数据,行数不一致时自动补空值避免报错:

import xlwt
from itertools import zip_longest
from django.http import HttpResponse

def export_excel(request):
    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = 'filename="persondatas.xls"' 
    wb = xlwt.Workbook(encoding='utf-8')
    ws = wb.add_sheet('AllinOne')
    row_num = 0
    font_style = xlwt.XFStyle()
    font_style.font.bold = True

    columns = ['name', 'fulname', 'id', 'gender', 'country', 'birthdate', 'birthplace', 
              'departament', 'feature']
    for col_num in range(len(columns)):
        ws.write(row_num, col_num, columns[col_num], font_style)

    font_style = xlwt.XFStyle()
    persons = Person.objects.values_list(
        'name', 'lastname', 'selfid', 'gender', 'country', 
        'dateofbirth', 'placeofbirth'
    )
    enrollments = Enrollment.objects.values_list('departament', 'feature')
    
    for person_row, job_row in zip_longest(persons, enrollments, fillvalue=()):
        row_num += 1
        full_row = person_row + job_row
        for col_num in range(len(full_row)):
            ws.write(row_num, col_num, str(full_row[col_num]) if full_row[col_num] is not None else '', font_style)

    wb.save(response)
    return response

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:45:05