Django-Import-Export插件控制数据导入流程
前言 之前写过两篇跟这个插件有关的文章,可以回顾一下: Django数据导入导出神器django-import-export使用 Django-Import-Export插件关于外键的处理 最近有个朋友留言问我一个关于django-import-export插件的问题 为了形象表达这个问题,我举个书籍管理的例子来描述一下 数据库表 | id | name | price | | ---- |
目录8 个章节
前言
之前写过两篇跟这个插件有关的文章,可以回顾一下:
最近有个朋友留言问我一个关于django-import-export插件的问题
为了形象表达这个问题,我举个书籍管理的例子来描述一下
数据库表
id name price 1 book1 10 2 book2 20 3 book3 30 要导入的Excel表
id name price tax 4 book4 40 5 5 book5 50 6 6 book6 60 7 可以看到,Excel里每本书都有价格和税两个属性,但数据库只有价格一个属性
导入的时候,需要把每本书的价格+税,才是要存入数据的最终价格
在以前,这种问题场景我会建议直接用pandas来处理数据然后导入,django-import-export插件只用来做数据导出,因为它的文档很简陋,给的例子很难解决实际问题,往往某个需求用pandas手动处理只需要很少时间,用这个插件还得去啃源码和简陋的文档,效率太低了。
不过本着折腾的精神,还是来研究一下这个用django-import-export到底能不能实现这个功能。(结果当然是可以的,不然也没有这篇文章了)
分析
首先是看官网文档,有一个节点叫import data workflow
地址:https://django-import-export.readthedocs.io/en/latest/import_workflow.html
import_data(dataset, dry_run=False, raise_errors=False)The
import_data()method ofResourceis responsible for importing data from a given dataset.
datasetis required and expected to be atablib.Datasetwith a header row.
dry_runis a Boolean which determines if changes to the database are made or if the import is only simulated. It defaults toFalse.
raise_errorsis a Boolean. IfTrue, import should raise errors. The default isFalse, which means that eventual errors and traceback will be saved inResultinstance.
根据文档,在导入数据的时候,我们可以通过import_data这个hook来对要导入的数据进行处理
然后这个hook有个参数,dataset,这个是tablib的东西
关于这个tablib,我之前没用过,查了一下,是requests作者做的库,那想来应该不会差
官网文档是:https://tablib.readthedocs.io/en/stable/tutorial.html
写代码
直接把官方的代码例子拿来用
代码仓库:https://github.com/django-import-export/django-import-export
同样是这个书籍管理的
Models代码
来看看它的model设计
class Book(models.Model):
name = models.CharField('Book name', max_length=100)
author = models.ForeignKey(Author, blank=True, null=True, on_delete=models.CASCADE)
author_email = models.EmailField('Author email', max_length=75, blank=True)
imported = models.BooleanField(default=False)
published = models.DateField('Published', blank=True, null=True)
published_time = models.TimeField('Time published', blank=True, null=True)
price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
added = models.DateTimeField(blank=True, null=True)
categories = models.ManyToManyField(Category, blank=True)
def __str__(self):
return self.name
很多字段
要导入的数据
依然是官方提供的,各种格式都有,我选csv的,比较方便
id,name,author_email
1,Some book,test@example.com
转换成表格长这样
| id | name | author_email |
|---|---|---|
| 1 | Some book | test@example.com |
可以看到字段比model定义的少很多
我们要在导入的时候,给dataset加上价格(price)属性
Resources代码
这是原本的代码
class BookResource(ModelResource):
class Meta:
model = Book
def for_delete(self, row, instance):
return self.fields['name'].clean(row) == ''
return super(BookResource, self).import_data(
dataset, dry_run, raise_errors, use_transactions,
collect_failed_rows, rollback_on_validation_errors, **kwargs
现在我们要加一个hook来处理导入的数据
代码如下
def import_data(self, dataset: tablib.Dataset, dry_run=False, raise_errors=False,
use_transactions=None, collect_failed_rows=False,
rollback_on_validation_errors=False, **kwargs):
cols = []
for item in dataset['id']:
cols.append(int(item) * 99)
dataset.append_col(cols, header='price')
return super(BookResource, self).import_data(
dataset, dry_run, raise_errors, use_transactions,
collect_failed_rows, rollback_on_validation_errors, **kwargs
)
使用DataSet的append_col方法来添加一个新的列
关于这个DataSet的更多操作请参考Tablib的文档
这部分的具体操作可以根据实际需求来做修改,这里我直接简单粗暴的把ID乘以99
处理完DataSet之后记得要执行父类的import_data,完成数据导入的操作。
效果
在admin后台执行导入,可以得到以下的结果
可以看到price属性变成99
| ID | NAME | AUTHOR | AUTHOR_EMAIL | IMPORTED | PUBLISHED | PUBLISHED_TIME | PRICE | ADDED | CATEGORIES | |
|---|---|---|---|---|---|---|---|---|---|---|
| New | 1 | Some book | test@example.com | 0 | 99 |
就OK了,搞定~
其实还挺简单的,只是官方文档太简陋了,连个例子的没有,只能自己摸索一下
参考资料
虽然前面都有链接,这里再总结一下吧
_EOF_
Django-Import-Export插件控制数据导入流程
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
如何优雅地在Django项目里生成不重复的ID?
在生成唯一 ID 这件事上,Django 和其他后端框架没啥不同的,思路都是类似的,只不过可以借助 Python 生态偷懒一下…
2024-12-08 · Django · 约 1 分钟
Django更换数据库和迁移数据方案
前言 双十一光顾着买东西都没怎么写文章,现在笔记里还有十几篇半成品文章没写完… 今天来分享一下 Django 项目切换数据库和迁移数据的方案,网络上找到的文章方法不一,且使用中容易遇到各类报错,本文根据 Django 官方文档和工作中的经验,稳定可靠,在博客中长期更新~ 如果你遇到同样的问题,阅读本文应该能得到比较好的解决方案。 基本步骤 Django 默认使用 SQLite 数据库方便开发,同时
2022-11-12 · Django · 约 1 分钟
DjangoAdmin使用合集
DjangoAdmin DjangoAdmin本身就是一套大而全的系统,官方文档中介绍了很多配置方法,但仍然有大量的骚操作是文档中没有的,所以遇到特殊需求的时候,求助文档不一定有用。 在我看来 DjangoAdmin 虽然能快速生成一套管理后台,但如果要做大量特殊需求的定制,其成本不亚于用 Vue/React 重新开发一套,简单的使用成本不高,但深入定制的话需要对 DjangoAdmin 的工作流
2023-04-09 · Django · 约 1 分钟
DjangoRestFramework框架三种分页功能的实现 - 在DjangoStarter项目模板中封装
前言 继续Django后端开发系列文章。刚好遇到一个分页的需求,就记录一下。 Django作为一个“全家桶”型的框架,本身啥都有,分页组件也是有的,但默认的分页组件没有对API开发做优化,所以DjangoRestFramework这个专门写API的框架又把Django的分页组件包装了一层,集成在viewsets里的时候会更方便。 不过我们不可能一直用viewsets,有一部分API还是要用自由度更
2022-08-26 · Django · 约 1 分钟
讨论
共 0 条加载评论中…