返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Django

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 | | ---- |

曦远 (DealiAxy)约 18 分钟
目录8 个章节

Introduction

I've previously written two articles related to this plugin, which you can review:

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

idnameprice
1book110
2book220
3book330

Excel table to import

idnamepricetax
4book4405
5book5506
6book6607

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 of Resource is responsible for importing data from a given dataset.

dataset is required and expected to be a tablib.Dataset with a header row.

dry_run is a Boolean which determines if changes to the database are made or if the import is only simulated. It defaults to False.

raise_errors is a Boolean. If True, import should raise errors. The default is False, which means that eventual errors and traceback will be saved in Result instance.

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

idnameauthor_email
1Some booktest@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

IDNAMEAUTHORAUTHOR_EMAILIMPORTEDPUBLISHEDPUBLISHED_TIMEPRICEADDEDCATEGORIES
New1Some booktest@example.com099

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

_EOF_

Controlling the Data Import Process with the Django-Import-Export Plugin

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

Django-Import-Export插件关于外键的处理

前言 Django-Import-Export是一款很好用很方便的Django数据导出导入插件,可以和DjangoAdmin管理后台完美集成,只需要少量的代码配置即可方便实现你要的多种格式导出导入,关于这个插件的使用更多可以看我之前的文章:这里放文章链接 之前我在使用中都是专门做了一个原始数据的表来存导入的数据,然后再对原始数据表做一些数据处理,把数据存到其他表才能真正使用这些数据。(不是很好的做

2022-04-02 · Django · 约 1 分钟

Django应用部署:Docker容器化实践

在此之前,我一直用uwsgi+virtualenv+nginx方式进行应用部署,操作起来比较麻烦,而且依赖于服务器上的Python版本,服务的管理方面单纯uwsgi + pid算不上特别麻烦但总没有docker compose方便,无奈原本的服务器是32位系统的用不上docker,现在又增加了一个新服务器,所以赶紧把docker安排上~ 不得不说真的太简单太方便了,全程傻瓜式操作,也基本没像之前u

2021-12-18 · Django · 约 1 分钟

DjangoRestFramework框架三种分页功能的实现 - 在DjangoStarter项目模板中封装

前言 继续Django后端开发系列文章。刚好遇到一个分页的需求,就记录一下。 Django作为一个“全家桶”型的框架,本身啥都有,分页组件也是有的,但默认的分页组件没有对API开发做优化,所以DjangoRestFramework这个专门写API的框架又把Django的分页组件包装了一层,集成在viewsets里的时候会更方便。 不过我们不可能一直用viewsets,有一部分API还是要用自由度更

2022-08-26 · Django · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…