Django數據導入導出神器django-import-export使用

前言

Django以快速開發聞名,可是若是處理數據的導出導入還須要本身寫腳本,那就有違「Python之禪」了……html

並且導數據一般須要不一樣的格式,Excel、csv、json等,每種格式的數據就要寫一個腳本太麻煩了,這時直接祭出django-import-export這個神器,官方一句話介紹:django-import-export is a Django application and library for importing and exporting data with included admin integration.java

特色:python

  • support multiple formats (Excel, CSV, JSON, ... and everything else that tablib support)
  • admin integration for importing
  • preview import changes
  • admin integration for exporting
  • export data respecting admin filters

反正好用就完事了,下面我開始上使用介紹linux

首先安裝

pip install django-import-export

而後得添加到INSTALLED_APPS 裏面android

# settings.py
INSTALLED_APPS = (
    ...
    'import_export',
)

編寫Resource

不得不說,這很Djangogit

Resource的寫法與Model、Form相似,就是定義你要導入或者導出的數據格式。github

這裏借用一下官方的例子,首先上Model代碼數據庫

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField('Book name', max_length=100)
    author = models.ForeignKey(Author, blank=True, null=True)
    author_email = models.EmailField('Author email', max_length=75, blank=True)
    imported = models.BooleanField(default=False)
    published = models.DateField('Published', blank=True, null=True)
    price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    categories = models.ManyToManyField(Category, blank=True)

    def __str__(self):
        return self.name

如今要導入數據到Book表,開始編寫咱們的Resource,我是在app所在目錄下建立一個resource.py來放Resource定義代碼django

from import_export import resources
from core.models import Book

class BookResource(resources.ModelResource):

    class Meta:
        model = Book

這樣一個最簡單的Resource就定義好了,可使用代碼進行數據導出,但如今我不想用,由於我要把導出功能放在DjangoAdmin後臺裏面json

配置Admin

修改admin.py,修改的地方就是把咱們定義的Admin類本來繼承的admin.ModelAdmin改爲ImportExportModelAdmin,代碼以下

from .models import Book
from import_export.admin import ImportExportModelAdmin

class BookAdmin(ImportExportModelAdmin):
    resource_class = BookResource

admin.site.register(Book, BookAdmin)

這樣就能夠在後臺看到有導出和導入的按鈕了。

只想導出不想有導入功能咋辦,改爲這樣:

from .models import Book
from django.contrib import admin
from import_export.admin import ExportMixin

class BookAdmin(ExportMixin, admin.ModelAdmin):
    resource_class = BookResource

admin.site.register(Book, BookAdmin)

只導入不導出也行,把ExportMixin換成ImportMixin就行。

固然這些只是最簡單的用法,實際需求是比較複雜的,接下來我列舉幾個我用到的。

調整字段順序

要導入的數據(Excel、csv這些),可能字段順序和Model定義的字段順序不同,這時就得在Resource裏手動調整一下

因爲我本身寫的代碼涉及到公司業務,因此繼續借用官網的代碼例子:

class BookResource(resources.ModelResource):

    class Meta:
        model = Book
        fields = ('id', 'name', 'author', 'price',)
        export_order = ('id', 'price', 'author', 'name')

其中export_order 是導出的字段順序,fields是指定哪些字段須要導入,導入的時候是根據數據文件的列名來導入的,因此Excel、csv或者json文件裏面字段名就要和fields裏的或者是Model裏的字段名同樣,才能夠進行導入。

排除字段

顧名思義,就拿那個Book的模型來講,Model定義裏沒有指定主鍵,那Django會安排一個默認的主鍵字段id,可是咱們導入數據的Excel裏應該是沒有這個id的,這樣就無法導入,因而咱們得把這個id字段排除了,很簡單,在Meta裏這行代碼

exclude = ['id']

設置主鍵字段

也是顧名思義,假如咱們數據庫原本就有不少書了,如今須要經過導入一個Excel來更新這批書的數據,那我就得把找一個字段來設置成主鍵字段,否則導入就變成新增了,跟前面提到的同樣,通常Excel裏不會有數據庫主鍵id的,因此這裏我選擇了書名(假設咱們這是一個小書店,書名都不重複的)

代碼:

import_id_fields = ['name']

自定義列名

按照前文配置導出來的Excel,列名全是字段名,也就是英文的,但我想中文列名啊,也能夠,就是須要花一點代碼(這裏就再也不借用官網代碼了,我本身手打)

from import_export.fields import Field

class BookResource(resources.ModelResource):
    id = Field(attribute='id', column_name='編號')
    name = Field(attribute='name', column_name='書籍名稱')

    class Meta:
        model = Book
        export_order = ('id', 'name', 'author', 'price',)

這樣就實現了,so easy。其中Field裏的attribute是指這個字段對應Model裏的屬性也就是字段名,column_name顧名思義就是列名。

而後可能有同窗要問,Model裏已經給每一個字段都設置了verbose_name了,這裏還要在column_name裏再寫一遍是否是重複了?

別急,也很簡單,既然有verbose_name,那直接拿來用就完事啦~

name = Field(attribute='name', column_name=Book.name.field.verbose_name)

這就完事美滋滋啦~

加入自定義的列

最後一個,若是想在導出的數據中加入Model裏不存在的字段,行不?

那確定行啊,也很簡單,直接代碼:

from import_export.fields import Field

class BookResource(resources.ModelResource):
    id = Field(attribute='id', column_name='編號')
    name = Field(attribute='name', column_name='書籍名稱')
    new_field = Field(column_name='一個新的字段')

    class Meta:
        model = Book
        export_order = ('id', 'name', 'author', 'price', 'new_field')

    @staticmethod
    def dehydrate_new_field(instance: Book):
        return '新字段內容'

能夠看到就是先在export_order 裏添加這個字段,而後再加這行new_field = Field(column_name='一個新的字段'),而後下面加一個類方法來實現生成這個字段的值,這個方法是以dehydrate_字段名這樣的格式來命名的,具體能夠根據實際來寫。

總結

django-import-export 這個插件還有不少其餘的功能,不過現階段已經知足了個人工做須要,因此我也沒有再去深刻,還有什麼功能須要能夠直接翻文檔吧。

目前我用到的仍是以導出爲主,導入的就是更新和新增這一塊,沒多少花樣,若是接下來遇到其餘新的需求,我會再更新一篇文章來介紹更新這個插件的功能~

參考資料

歡迎交流

程序設計實驗室專一於互聯網熱門新技術探索與團隊敏捷開發實踐,在公衆號「程序設計實驗室」後臺回覆 linux、flutter、c#、netcore、android、kotlin、java、python 等可獲取相關技術文章和資料,同時有任何問題均可以在公衆號後臺留言~

相關文章
相關標籤/搜索