Controlling the Data Import Process with the Django-Import-Export Plugin
Introduction I've previously written two articles related to this plugin, which you can review: Using django-import-export, a Django Data Import/Export Powerhouse Handling Foreign Keys with the Django-Import-Export Plugin Recently a friend left a comment asking me a question about the django-import-export plugin To illustrate this problem more vividly, I'll use a book management example Database table | id | name | price | | ---- |
目录8 个章节
Introduction
I've previously written two articles related to this plugin, which you can review:
- Using django-import-export, a Django Data Import/Export Powerhouse
- Handling Foreign Keys with the Django-Import-Export Plugin
Recently a friend left a comment asking me a question about the django-import-export plugin
To illustrate this problem more vividly, I'll use a book management example
Database table
id name price 1 book1 10 2 book2 20 3 book3 30 Excel table to import
id name price tax 4 book4 40 5 5 book5 50 6 6 book6 60 7 As you can see, each book in the Excel file has two attributes, price and tax, but the database only has the price attribute
When importing, you need to add each book's price + tax; that is the final price to store in the database
In the past, for this kind of scenario I would suggest using pandas to process the data and then import it, and only using the django-import-export plugin for data export, because its documentation is quite sparse, and the examples it provides can hardly solve real-world problems. Often a requirement that takes very little time to handle manually with pandas would require digging through the source code and sparse documentation with this plugin, which is far too inefficient.
But in the spirit of tinkering, let's still look into whether django-import-export can actually implement this feature. (Of course it can, otherwise this article wouldn't exist)
Analysis
First, looking at the official documentation, there's a section called import data workflow
Address: 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.
According to the documentation, when importing data, we can process the data to be imported through the import_data hook
Then this hook has a parameter, dataset, which is a tablib thing
I hadn't used tablib before. After looking it up, it's a library made by the author of requests, so it shouldn't be bad
Official documentation: https://tablib.readthedocs.io/en/stable/tutorial.html
Writing the Code
Let's just use the official code example
Code repository: https://github.com/django-import-export/django-import-export
It's also about book management
Models Code
Let's look at its model design
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
Lots of fields
Data to Import
Still provided by the official project, available in various formats. I chose CSV, which is more convenient
id,name,author_email
1,Some book,test@example.com
Converted to a table it looks like this
| id | name | author_email |
|---|---|---|
| 1 | Some book | test@example.com |
As you can see, there are far fewer fields than defined in the model
We need to add a price attribute to the dataset when importing
Resources Code
This is the original code
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
Now we need to add a hook to process the imported data
The code is as follows
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
)
Use the append_col method of DataSet to add a new column
For more operations on this DataSet, please refer to the Tablib documentation
The specific operations in this part can be modified according to actual needs. Here I simply and crudely multiply the ID by 99
After processing the DataSet, remember to call the parent class's import_data to complete the data import operation.
Results
After performing the import in the admin backend, you can get the following result
You can see that the price attribute has become 99
| ID | NAME | AUTHOR | AUTHOR_EMAIL | IMPORTED | PUBLISHED | PUBLISHED_TIME | PRICE | ADDED | CATEGORIES | |
|---|---|---|---|---|---|---|---|---|---|---|
| New | 1 | Some book | test@example.com | 0 | 99 |
That's it, done~
It's actually quite simple, it's just that the official documentation is too sparse, without even an example, so you have to figure it out yourself
References
Although the links are already given above, let me summarize them here
- Plugin documentation: https://django-import-export.readthedocs.io/en/latest/import_workflow.html
- Plugin project homepage: https://github.com/django-import-export/django-import-export
- Tablib documentation: https://tablib.readthedocs.io/en/stable/tutorial.html
_EOF_
Controlling the Data Import Process with the Django-Import-Export Plugin
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
给Django-Admin添加验证码和多次登录尝试限制
Django自带的Admin很好用,但是放到生产环境总还差了点什么= = 看看admin的介绍: Django奉行Python的内置电池哲学。它自带了一系列在Web开发中用于解决常见问题或需求的额外的、可选工具。这些工具和插件,例如django.contrib.redirects都必须在settings中的INSTALLED_APPS处进行注册,有的还需要执行manage.py migrate命令
2021-12-18 · Django · 约 1 分钟
Django统一包装接口返回数据格式
前言 最近实在太忙了,开始了一个新的项目,为了快速形成产品,我选择了Django来实现后端,然后又拿起了之前我封装了项目脚手架「DjangoStarter」。 由于前段时间我写了不少.NetCore的后端代码,对CRUD的接口开发又有了一些新的理解,所以肯定也要把DjangoStarter改造一番,改得更加顺手~ 题外话:话说我在前端终于真正用上react,不得不说 ts + react 真好用,
2022-08-26 · Django · 约 1 分钟
Django项目引入NPM和gulp管理前端资源
前言 之前写了一篇《Asp-Net-Core开发笔记:使用NPM和gulp管理前端静态文件》,现在又来用Django开发项目了,之前我搞了一个Django的快速开发脚手架「DjangoStarter」,正好给升级一下~ 关于npm和gulp我就不多重复了,之前那篇文章都写了,直接上操作 安装依赖 安装依赖的操作跟上一篇文章是一样的,不过我这里直接提供package.json文件,复制到项目根目录里
2022-04-02 · Django · 约 1 分钟
Django:为模板渲染加入Markdown支持
两种方法 Django 的django-markdown-deux模块 Python模块 markdown django-markdown-deux 首先需要安装: pip install django-markdown-deux 修改setting.py 把markdown-deux添加进去 INSTALLED_APPS = [ 'markdown-deux', ] 在模板里添加tags
2022-04-02 · Django · 约 1 分钟
讨论
共 0 条加载评论中…