如何在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
相关产品推荐
相关产品推荐

