はじめに
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