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

如何在Django Admin导出CSV时包含反向FK的最新Clothes记录?

问题:如何在导出Person的CSV时添加对应Clothes的最新记录?

我有以下模型:

class Person(models.Model):
    name = models.CharField(max_length=45)
    etc...
class Clothes(models.Model):
    person = models.ForeignKey(Person)
    etc...

我的admin.py中有如下代码:

class ExportCsvMixin:
    def export_as_csv(self, request, queryset):
        meta = self.model._meta
        field_names = [field.name for field in meta.fields]
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
        writer = csv.writer(response)
        writer.writerow(field_names)
        for obj in queryset:
            row = writer.writerow([getattr(obj, field) for field in field_names])
        return response
export_as_csv.short_description = "Export Selected as CSV"
class PersonAdmin(admin.ModelAdmin, ExportCsvMixin):
    actions = ["export_as_csv"]
    etc...

当前代码可成功导出包含Person所有字段的CSV文件,请问如何在导出的CSV中添加每个Person对应的Clothes模型的最新记录?


解决方案

嘿,这个需求很好实现,咱们只需要修改ExportCsvMixin里的export_as_csv方法,让它能关联获取每个Person的最新Clothes记录就行,具体步骤如下:

1. 确定要添加的Clothes字段

首先你得明确要把Clothes里的哪些字段加到CSV里,比如假设Clothes有clothes_type(衣物类型)、purchase_date(购买日期)这两个字段,咱们就把这两个字段的信息加进去。

2. 修改字段名列表

在原来的field_names基础上,追加咱们要添加的Clothes相关字段名,方便CSV里的列能清晰识别:

field_names = [field.name for field in meta.fields]
# 追加Clothes相关的字段名,命名可以根据实际需求调整
field_names += ['latest_clothes_type', 'latest_clothes_purchase_date']

3. 获取每个Person的最新Clothes记录并生成行数据

在循环处理每个Person对象时,通过反向关联(clothes_set,如果给ForeignKey设置了related_name就用自定义的名称)获取最新记录,同时要处理没有Clothes记录的情况,避免代码报错。

完整修改后的代码

import csv
from django.http import HttpResponse

class ExportCsvMixin:
    def export_as_csv(self, request, queryset):
        meta = self.model._meta
        field_names = [field.name for field in meta.fields]
        # 追加需要导出的Clothes字段名
        field_names += ['latest_clothes_type', 'latest_clothes_purchase_date']
        
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
        writer = csv.writer(response)
        writer.writerow(field_names)
        
        for obj in queryset:
            # 先获取Person本身的字段值
            person_fields = [getattr(obj, field) for field in meta.fields]
            # 获取最新的Clothes记录,这里假设按id倒序取最新,也可以换成created_at之类的时间字段
            latest_clothes = obj.clothes_set.order_by('-id').first()
            # 处理没有Clothes记录的情况,给默认值
            if latest_clothes:
                clothes_type = latest_clothes.clothes_type
                purchase_date = latest_clothes.purchase_date
            else:
                clothes_type = '-'
                purchase_date = '-'
            # 把Person字段和Clothes字段合并成一行
            full_row = person_fields + [clothes_type, purchase_date]
            writer.writerow(full_row)
        return response

export_as_csv.short_description = "Export Selected as CSV"

class PersonAdmin(admin.ModelAdmin, ExportCsvMixin):
    actions = ["export_as_csv"]
    etc...

关键说明

  • 如果你给Clothes的ForeignKey设置了related_name,比如person = models.ForeignKey(Person, related_name='clothes'),那就要把obj.clothes_set改成obj.clothes。
  • 取最新记录的排序字段可以根据业务调整,比如有created_at时间字段的话,用order_by('-created_at').first()会更贴合“最新”的业务逻辑。
  • 没有对应Clothes记录的情况,这里用'-'作为默认值,你也可以改成空字符串或者其他符合需求的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:08:14