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

如何将含外键的Django模型数据导出至CSV文件

解决Django模型导出CSV时外键仅显示ID的问题

嘿,我来帮你搞定这个外键导出的问题!你现在的代码能导出数据,但外键只显示ID,是因为values_list()默认只会获取外键字段存储的主键值。要把关联模型的具体信息也导出到同一行,有两种常用的方法,我给你详细说说:

方法一:用双下划线直接指定外键关联字段

Django的查询集支持用**双下划线(__)**来访问外键关联模型的字段,你可以直接在values_list()里指定这些字段,这样就能一次性拿到关联对象的具体值,不用额外循环处理。

修改后的视图代码

import csv
from django.http import HttpResponse
from .models import session

def exportsCSV(request):
    # 提前用select_related拉取外键数据,避免N+1查询问题
    sessions = session.objects.select_related('responden', 'mark', 'order').all()
    
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=sessions.csv'
    writer = csv.writer(response)
    
    # 先写入CSV表头(根据你的需求自定义字段名)
    writer.writerow([
        'ID', 'Responden信息', '认知分数', '社交分数', 
        '身体分数', '总分', '开始时间', '结束时间', 
        '时长', '标记信息', '顺序信息'
    ])
    
    # 用双下划线指定外键的具体字段(这里假设responden有name字段,sessionMark有title字段,sessionOrder有number字段,你要换成自己模型的实际字段)
    sess_data = sessions.values_list(
        'id',
        'responden__name',  # 访问responden模型的name字段
        'kognitifScore',
        'sosioScore',
        'fisikScore',
        'totalScore',
        'timeStart',
        'timeEnd',
        'duration',
        'mark__title',     # 访问sessionMark模型的title字段
        'order__number'    # 访问sessionOrder模型的number字段
    )
    
    # 写入所有数据行
    writer.writerows(sess_data)
    
    return response

方法二:手动遍历对象获取外键属性(更灵活)

如果你的外键可能为空,或者需要对关联字段做自定义处理(比如格式化显示),可以直接遍历每个session对象,手动构建每一行的数据,这样能更灵活地控制输出内容。

示例代码

import csv
from django.http import HttpResponse
from .models import session

def exportsCSV(request):
    # 同样用select_related优化查询
    sessions = session.objects.select_related('responden', 'mark', 'order').all()
    
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=sessions.csv'
    writer = csv.writer(response)
    
    # 写入表头
    writer.writerow([
        'ID', 'Responden信息', '认知分数', '社交分数', 
        '身体分数', '总分', '开始时间', '结束时间', 
        '时长', '标记信息', '顺序信息'
    ])
    
    # 逐个处理每个session对象
    for sess in sessions:
        # 处理外键为空的情况,避免报错
        responden_info = sess.responden.name if sess.responden else '无数据'
        mark_info = sess.mark.title if sess.mark else '无数据'
        order_info = sess.order.number if sess.order else '无数据'
        
        # 构建当前行的数据
        row = [
            sess.id,
            responden_info,
            sess.kognitifScore,
            sess.sosioScore,
            sess.fisikScore,
            sess.totalScore,
            sess.timeStart.strftime('%Y-%m-%d %H:%M:%S'),  # 格式化时间
            sess.timeEnd.strftime('%Y-%m-%d %H:%M:%S'),
            sess.duration,
            mark_info,
            order_info
        ]
        writer.writerow(row)
    
    return response

关键注意点

  1. 避免N+1查询问题:一定要在查询集里加上select_related('responden', 'mark', 'order'),这样Django会一次性把关联的外键数据从数据库拉取出来,否则每次访问sess.responden都会触发新的数据库查询,数据量大会很慢。
  2. 替换实际字段名:上面代码里的responden__name、mark__title等都是示例,你要换成自己responden、sessionMark、sessionOrder模型里实际存在的字段(比如姓名、状态、序号等)。
  3. 处理空值:如果外键字段允许为空(null=True),记得像方法二那样做判断,避免出现AttributeError。

内容的提问来源于stack exchange,提问作者Andi Fathul Mukminin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:42:46