はじめに
Djangoのdjango-import-exportを使って、管理画面でデータをインポートする方法を調べました。
今回インポートするモデルにはForeignKeyフィールドが含まれるので、デフォルトでは主キーで指定する必要があります。
django-import-exportには、一意な値で代替する機能があるので利用しました。
構成
- Debian bookworm - Python 3.10.13 - pipenv 2023.10.3 - Django 5.0.3 - django-import-export 3.3.7
django-import-exportのインストール
Pythonの仮想環境にpipenvを使っているので、pipenvコマンドでインストールします。
pipenv install django-import-export
settings.py
インポート、エクスポートともにCSV、またはExcelファイルしか扱わないので設定します。
INSTALLED_APPS = [
...(省略)...
'import_export',
]
IMPORT_EXPORT_AVAILABLE_IMPORT_FORMATS = [
'xlsx', 'csv',
]
IMPORT_EXPORT_AVAILABLE_EXPORT_FORMATS = [
'xlsx', 'csv',
]
models.py
モデル定義は下記とします。
import uuid
from django.db import models
# カテゴリ
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
# フルーツ
class Fruits(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=256)
category_field = models.ForeignKey(Category, on_delete=models.PROTECT, related_name='fruits')
def __str__(self):
return self.name
admin.py
ForeignKeyフィールドであるcategory_fieldの設定などを行います。
・column_nameは、インポートするExcelファイル等に追加する列の項目名。
・attributeは、ForeignKeyのフィールド名。
・widgetは、代替する値のモデル名とフィールド名。
from django.contrib import admin
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget
from .models import Fruits
from .models import Category
# django-import-exportの設定
class FruitsResource(resources.ModelResource):
class Meta:
model = Fruits
# インポート時にデータベースの既存データと同一の場合にスキップする。
skip_unchanged = True
# スキップしたレコードの詳細を表示する。
report_skipped = True
# 毎回データベースへのクエリを発行しないため、インポート処理速度の向上が期待できる。
instance_loader_class = CachedInstanceLoader
# インポート、エクスポートの対象を指定する。
fields = ('id', 'name', 'category_field')
# エクスポートしたときの項目の並び順を指定する。(今回はfieldsと同じ。)
export_order = fields
# ForeignKeyフィールド(category_field)の設定
category_field = fields.Field(
column_name = 'category_name',
attribute = 'category_field',
widget = ForeignKeyWidget(Category, 'name')
)
# 管理サイトに表示
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'category', 'price')
# 管理サイトに表示
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name',)
項目のみのExcelファイルのダウンロード
テストサーバを起動します。
python manage.py runserver 192.168.12.34:8080
何もデータを登録していない状態で、管理画面からFruitsモデルのデータをExcel形式でエクスポートして、export_orderで指定した並び順かどうか確認します。
また、このファイルにcategory_nameの列を追加して、インポートするデータを作成します。
category_fieldの値は、category_name(Categoryのnameフィールド)で代替するので、インポートする前にCategoryモデルにデータを登録します。
データは例えば以下のようになります。
Categoryモデルには「果物」と「野菜」を登録しておきます。
idの列は、空にしておけば自動的にUUIDが割り当てられます。
id,name,category_name, ,りんご,果物, ,バナナ,果物, ,トマト,野菜,
テスト
管理画面から作成したデータをインポートして、category_nameに記述したCategoryのnameフィールドの値で登録できているかを確認します。


Comments