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

django-import-export从Excel导入ImageField仅存路径问题解决

问题复现

使用django-import-export导入file.xlsx时,PhotoProduct模型的image字段仅存储了Excel中填写的本地绝对路径字符串,实际图片文件未存入upload_to指定的images/produits目录。
现有代码如下:

models.py

class Product(models.Model):
    name         = models.CharField( max_length=200, verbose_name='Nom')
    slug         = models.SlugField( max_length=150, unique= True, verbose_name='URL')
    reference    = models.CharField( max_length=200, verbose_name='Référence', unique=True, 
                    blank=True, null=True)
    def __str__(self):
        return self.name

class PhotoProduct(models.Model):

    image     = models.ImageField(upload_to='images/produits') 
    actif     = models.BooleanField(verbose_name='actif', default=True)
    product   = models.ForeignKey(Product, related_name="photos", on_delete=models.CASCADE)
    def __str__(self):
        return str(self.product)

ressources.py

class PhotoProductAdminResource(resources.ModelResource):
    product   = fields.Field(column_name='product', attribute='product', 
                       widget=ForeignKeyWidget(Product, field='id'))
    class Meta:
        model = PhotoProduct
        fields = ( 
            'id',
            'product',
            'actif',
            'image',
        )

admin.py

@admin.register(PhotoProduct)
class PhotoProductAdmin(ImportExportModelAdmin):
    list_display = ('id', 'product', 'actif')
    list_display_links = ('id','product', )
    list_editable = [ 'actif']
    resource_class = PhotoProductAdminResource 
    form = PhotoProductModelForm
原因

django-import-export默认的字段处理逻辑不会主动读取本地路径对应的实体文件,仅将单元格内的字符串直接写入数据库,完全没有触发Django文件存储的写入流程,所以不会把文件拷贝到指定的媒体目录。

解决方法
  1. 自定义专门处理本地图片导入的Widget,在ressources.py头部加入依赖导入和控件实现:
import os
from django.core.files import File
from import_export.widgets import Widget

class LocalImageWidget(Widget):
    def clean(self, value, row=None, *args, **kwargs):
        if not value:
            return None
        # 标准化Windows路径,避免反斜杠转义问题
        file_path = os.path.normpath(value.strip())
        if not os.path.isfile(file_path):
            raise ValueError(f"Invalid image path: {file_path}")
        # 读取文件封装为Django认可的File对象,触发存储上传逻辑
        file_name = os.path.basename(file_path)
        with open(file_path, 'rb') as f:
            return File(f, name=file_name)
  1. 修改PhotoProductAdminResource中image字段的配置,绑定自定义Widget:
class PhotoProductAdminResource(resources.ModelResource):
    product   = fields.Field(
        column_name='product', 
        attribute='product', 
        widget=ForeignKeyWidget(Product, field='id')
    )
    # 新增image字段配置
    image = fields.Field(
        column_name='image',
        attribute='image',
        widget=LocalImageWidget()
    )
    class Meta:
        model = PhotoProduct
        fields = ( 
            'id',
            'product',
            'actif',
            'image',
        )
注意事项
  • 运行Django服务的系统账号必须对Excel中填写的图片路径有读取权限,否则会触发文件不存在报错
  • Excel中填写的图片路径必须是Django服务所在机器的本地绝对路径,如果图片存放在其他设备,需要先将图片目录同步到服务本机再填写对应路径
  • 导入完成后图片会自动存入MEDIA_ROOT/images/produits目录,数据库存储的路径为相对路径,和后台手动上传的文件逻辑完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 04:09:31