利用django-import-export在Django Admin中导入自定义文件类型

众所周知,在使用Django时,经常会用到导入导出功能。Django官方为我们提供了actions插槽实现了绑定Model的一些操作。

基于此,我们可以利用该函数实现选中下载,选中上传更新等操作。但是本文不讨论该函数,感兴趣的朋友可以参考:Django Admin actions

本文讨论第三方库 django-import-export,该库基于 tablib点此查看)实现了

Excel 
JSON 
YAML
Pandas DataFrames
HTML
Jira
LaTeX
TSV
ODS
CSV
DBF

上述文件的导入与导出。但是,如果我们需要导入的文件类型不在上述列表中又该如何操作?

下面通过上传 zip 压缩文件(zipfile+django-import-export)举例进行说明,正文开始。

1、定义 Format

class ZIPFormat(TablibFormat):
    # 上传中间页显示的格式名称
    title = 'zip'
    # tablib需要定义的module名称,后续会通过split的方式进行切分校验
    TABLIB_MODULE = 'tablib.formats._zip'
    # 文件上传时校验的 request header type
    CONTENT_TYPE = 'application/x-zip-compressed'

    def create_dataset(self, in_stream, **kwargs):
        """
        创建数据集
        @params:in_stream: request content
        """
        from zipfile import ZipFile
		
        # 由于 zipfile 的原因,无法直接读取请求流,所以需要BytesIO进行转换
        f = ZipFile(io.BytesIO(in_stream), 'r')
        return f

    @classmethod
    def import_set(cls, dset, in_stream):
        """
        鉴定是否有导入权限的函数,同时对数据集进行一些设置,没有该函数页面将不会显示导入按钮
        同理,导出需实现export_set函数
        同样,我们也可以通过 can_import(self),can_export(self)函数直接返回True
        """
        dset.wipe()
        dset.dict = in_stream

2、定义 Storage

class ZipStorage(TempFolderStorage):
	"""
	这里继承了 import_export.tmp_storages中的TempFolderStorage类
	亦可以继承同级的BaseStorage类,但是需要多实现一个remove方法
	"""
    def save(self, data):
        """
        必须实现的save方法
        """
        from zipfile import ZipFile

        with ZipFile(self.get_full_path(), 'w') as file:
            file.write(data)

    def read(self):
        """
        必须实现的read方法,这里返回了使用zipfile读取文件后的压缩包内部数据
        """
        from zipfile import ZipFile
        with ZipFile(self.get_full_path(), 'r') as file:
            return file.infolist()

3、编写 Resource

class ZIPResource(resources.ModelResource):
    """
    这里通过绑定指定类进行编写,实际使用时仅显示不校验
    """
    class Meta:
        model = BookModel
        fields = ('avator', )

    def import_data(self, dataset, dry_run=False, raise_errors=False, use_transactions=None, collect_failed_rows=False, rollback_on_validation_errors=False, **kwargs):
        """
        一步到位直接重写import_data方法,自定义自己所需要的操作
        @params:dataset: 前文中的dataset
        其余参数这里不再赘述
        """
        
        # 指定上传路径
        ep = Path(BASE_DIR, "images", 'upload').resolve()
        # 获取压缩包内的图片数量
        nums = dataset.infolist()
        # 解压
        dataset.extractall(ep, nums)
        # 自定义操作,model更新等...
        custom_operation(nums)
        # 自定义返回对象
        result = self.get_result_class()()
        # 设置返回对象的总添加数
        # 可以根据需求对更新数量同步更改
        result.totals = len(nums)
        return result

4、注册自定义的 Format

from tablib.formats import registry

# 导入tablib的registry实例对自定义的Format进行注册
registry.register("zip", ZIPFormat())

5、(可选)自定义返回消息

from django.contrib import messages

from import_export.admin import ImportMixin


class CustomImportMixin(ImportMixin):
    """
    自定义mixin工具类,继承ImportMixin,export同理
    """

    def add_success_message(self, result, request):
        """
        请求成功时页面弹出的消息
        通过 django 的 messages 进行消息的通信
        """
        success_message = '文件上传成功, 本次共解压 %s 张图片.' % result.totals
        messages.success(request, success_message)

通过上述步骤,我们便可以在 Django Admin中实现自定文件类型的操作,同时避免了绑定Model的操作。

当然,上述的操作只是作为初级使用文档,更多的好玩用法可以参考官方文档与阅读源码。

最后

凡有所学,皆成性格。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于您的问题,我可以为您提供一些指导。如果您想自定义批量导入界面,您可以使用 Django-import-export 库提供的一些功能。 首先,您需要在您的 Django 项目安装 Django-import-export 库。您可以使用以下命令安装: ``` pip install django-import-export ``` 之后,您可以在您的 Django 应用程序导入 `django-import-export` 模块并使用提供的类。在您的模型,您可以使用 `ImportExportModelAdmin` 类来管理导入和导出操作。您可以使用此类的以下属性和方法来自定义批量导入界面: - `import_template_name`:指定导入模板的名称。 - `import_formats`:指定可用于导入的格式。 - `before_import`:指定在导入操作之前执行的方法。 - `after_import`:指定在导入操作之后执行的方法。 例如,在您的模型,您可以定义一个新的 `ImportExportModelAdmin` 类,并使用以下代码来自定义批量导入界面: ``` from import_export.admin import ImportExportModelAdmin, ImportMixin from import_export import resources class MyModelResource(resources.ModelResource): class Meta: model = MyModel class MyModelAdmin(ImportExportModelAdmin): resource_class = MyModelResource import_template_name = 'myapp/import.html' import_formats = [ 'csv', 'xls' ] def before_import(self, dataset, using_transactions, dry_run, **kwargs): # Do some processing before the import pass def after_import(self, dataset, result, using_transactions, dry_run, **kwargs): # Do some processing after the import pass admin.site.register(MyModel, MyModelAdmin) ``` 在上面的示例,我们首先创建了一个自定义 `resources.ModelResource`,并将其定义为 `MyModelResource`。接下来,我们创建了一个自定义 `ImportExportModelAdmin` 类,并将其定义为 `MyModelAdmin`。 在 `MyModelAdmin` 类,我们指定了 `resource_class` 为我们刚刚定义的 `MyModelResource`。我们还对导入模板名称和可用格式进行了自定义,并指定了 `before_import` 和 `after_import` 方法来执行导入操作之前和之后的处理。最后,我们使用 `admin.site.register` 函数将我们的模型注册到管理站点。 希望这可以帮助您自定义批量导入界面。如果您需要更多帮助,请随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值