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

Django Admin导出CSV仅获图片URL,无法导出实际图片问题求助

解决Django Admin导出图片而非URL的问题

Django Admin默认导出ImageField时只会输出存储路径/URL,要导出实际图片可通过以下几种方式实现:

方案1:使用django-import-export导出带图片的Excel文件

这是最实用的方案——CSV格式本身不支持嵌入图片,而Excel可以直接把图片插入对应单元格。

  1. 安装依赖:
pip install django-import-export openpyxl
  1. 在settings.py中注册应用:
INSTALLED_APPS = [
    # ... 其他已注册应用
    'import_export',
]
  1. 自定义Resource类处理图片字段:
from import_export import resources
from import_export.fields import Field
from import_export.widgets import Widget
from openpyxl.drawing.image import Image
from openpyxl.utils import get_column_letter
from .models import YourModel  # 替换为你的模型类

class ImageWidget(Widget):
    def render(self, value, obj=None):
        return value.path if value else None

class YourModelResource(resources.ModelResource):
    image = Field(widget=ImageWidget())

    class Meta:
        model = YourModel
        fields = ('id', 'name', 'image')  # 按需选择需要导出的字段

    def export(self, queryset=None, *args, **kwargs):
        workbook = super().export(queryset, *args, **kwargs)
        worksheet = workbook.active

        # 遍历行插入图片
        for row_idx, row in enumerate(worksheet.iter_rows(min_row=2), start=2):
            image_path = row[2].value  # 假设图片字段在第3列(索引从0开始为第2位)
            if image_path:
                img = Image(image_path)
                # 调整图片大小
                img.width = 100
                img.height = 100
                worksheet.add_image(img, f'{get_column_letter(3)}{row_idx}')
                # 清空单元格的路径文本
                row[2].value = None

        return workbook
  1. 在Admin中注册Resource:
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from .models import YourModel
from .resources import YourModelResource

@admin.register(YourModel)
class YourModelAdmin(ImportExportModelAdmin):
    resource_class = YourModelResource

完成以上配置后,导出Excel时图片会直接嵌入对应单元格,替代原有的URL路径。

方案2:自定义Admin导出动作,打包CSV和图片文件

如果需要保留CSV格式,同时获取实际图片,可以自定义导出动作,把CSV和所有图片打包成ZIP文件:

from django.contrib import admin
from django.http import HttpResponse
from django.utils.text import slugify
import zipfile
import csv
import os
from io import StringIO
from .models import YourModel

@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
    actions = ['export_data_with_images']

    def export_data_with_images(self, request, queryset):
        # 创建内存ZIP文件
        response = HttpResponse(content_type='application/zip')
        response['Content-Disposition'] = f'attachment; filename="{slugify(YourModel._meta.verbose_name_plural)}_with_images.zip"'

        with zipfile.ZipFile(response, 'w') as zipf:
            # 写入CSV文件
            csv_filename = f'{slugify(YourModel._meta.verbose_name_plural)}.csv'
            csv_buffer = StringIO()
            writer = csv.writer(csv_buffer)
            # 写入表头
            headers = ['ID', '名称', '图片文件名']  # 替换为你的字段名
            writer.writerow(headers)
            # 写入数据行
            for obj in queryset:
                image_filename = obj.image.name.split('/')[-1] if obj.image else ''
                writer.writerow([obj.id, obj.name, image_filename])
            zipf.writestr(csv_filename, csv_buffer.getvalue())

            # 写入图片文件
            for obj in queryset:
                if obj.image and os.path.exists(obj.image.path):
                    zipf.write(obj.image.path, arcname=f'images/{obj.image.name.split("/")[-1]}')

        return response

    export_data_with_images.short_description = '导出数据及对应图片(ZIP打包)'

执行该动作后,会下载一个ZIP包,包含记录图片文件名的CSV文件,以及所有对应图片文件。

方案3:CSV中嵌入Base64编码的图片(不推荐)

CSV本身不支持图片,但可以把图片转成Base64编码字符串写入字段,部分工具(如Excel)可识别并显示:

import base64
from django.contrib import admin
from django.http import HttpResponse
from django.utils.text import slugify
import csv
import os
from .models import YourModel

@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
    actions = ['export_data_with_base64_images']

    def export_data_with_base64_images(self, request, queryset):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename="{slugify(YourModel._meta.verbose_name_plural)}.csv"'
        writer = csv.writer(response)
        headers = ['ID', '名称', '图片(Base64)']
        writer.writerow(headers)

        for obj in queryset:
            base64_img = ''
            if obj.image and os.path.exists(obj.image.path):
                with open(obj.image.path, 'rb') as img_file:
                    base64_img = base64.b64encode(img_file.read()).decode('utf-8')
            writer.writerow([obj.id, obj.name, base64_img])

        return response

    export_data_with_base64_images.short_description = '导出数据及Base64编码图片(CSV)'

注意:这种方式会让CSV文件体积大幅增加,仅适合少量图片场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:45:34