ご覧いただきありがとうございます!
領護(りょうご)です。
Djangoのデータベースに一つずつデータを登録するのは面倒…。
そんな時はCSVを使って一括インポートしたいですよね!
今回は、CSVを利用してDjangoのデータベースにデータをインポートする方法を解説します。
上記のように、CSVをアップロードするフォームを用意し、登録ボタンをクリックするだけで、Djangoのデータベースにデータを一括インポートできます。
実行環境
Docker Desktop:4.38.0
Python:3.12.8
Django:5.1.3
Pandas:2.2.3
フォルダ構成
sample_web/
├── .env # 環境変数ファイル
├── requirements.txt # インストールするPythonライブラリの一覧
├── docker-compose.yml # Docker Compose設定ファイル
├── manage.py # Django管理スクリプト
├── sample_project/ # プロジェクト名
│ ├── asgi.py # ASGI設定ファイル
│ ├── settings.py # プロジェクト設定ファイル
│ ├── urls.py # URLルーティング
│ ├── wsgi.py # WSGI設定ファイル
│ ├── static/ # 静的ファイルディレクトリ
│ │ └── css/
│ │ └── base.css # ベースCSSファイル
│ └── templates/ # HTMLテンプレートディレクトリ
│ └── sample.html # ダウンロードページのテンプレート
├── home/ # アプリフォルダ
│ ├── admin.py # 管理サイト用の設定ファイル
│ ├── forms.py # フォーム定義ファイル
│ ├── models.py # モデル定義ファイル
│ ├── urls.py # URLルーティング
│ ├── views.py # ビューファイル
│ └── migrations/ # マイグレーションファイル
今回の解説では、上記のフォルダ構成を使用します。
主に使用するのは、requirements.txt、home/admin.py、home/forms.py、home/models.py、home/urls.py、home/views.py、templates/sample.htmlの7つのファイルです。
必要なライブラリのインストール
pip install pandas
データを扱いやすくするためのライブラリ「pandas」をインストールします。
pandas
requirements.txtを使用する場合は、「pandas」を追記してインストールしてください。
モデル定義を作成
まず初めに、例として使用する従業員モデルをhome/models.pyに作成します。
※ 既にモデルを作成済みの場合は、CSVアップロードフォームの作成までスキップしてください。
from django.db import models
from django.utils.translation import gettext_lazy as _
# 従業員モデル
class Employee(models.Model):
# 氏名
employee_name = models.CharField(verbose_name=_("氏名"), max_length=32)
# 所属名
organization_name = models.CharField(verbose_name=_("所属名"), max_length=32)
# 年齢
age = models.PositiveIntegerField(verbose_name=_("年齢"))
# 作成日時
created_at = models.DateTimeField(verbose_name=_("作成日時"), auto_now_add=True)
class Meta:
db_table = "employees"
verbose_name = _("従業員")
verbose_name_plural = _("従業員")
def __str__(self):
return self.employee_name
ID(自動付与)、氏名、所属名、年齢、作成日時の5つのフィールドを作成しています。
Django管理画面に表示
Djangoの管理画面に従業員モデルを表示する設定をhome/admin.pyに作成します。
from django.contrib import admin
from .models import *
# 従業員モデル管理画面
class EmployeeAdmin(admin.ModelAdmin):
list_display = (
"id",
"employee_name",
"organization_name",
"age",
"created_at",
)
# Django管理画面に表示する
admin.site.register(Employee, EmployeeAdmin)
ここまで完成したら、makemigrationsとmigrateを行います。
次に、CSVアップロードフォームを作成します。
CSVアップロードフォームの作成
CSVファイルをアップロードするフォームをhome/forms.pyに作成します。
forms.pyファイルがない場合は、ご自身で新規作成をしてください。
import os
from django import forms
# CSVアップロードフォーム
class CSVUploadForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
csv_file = forms.FileField(label="CSVファイルアップロード")
# 拡張子バリデーション
def clean_csv_file(self):
file = self.cleaned_data["csv_file"]
extension = os.path.splitext(file.name)[1]
if not extension.lower() in ".csv":
raise forms.ValidationError("csvファイルを選択してください")
return file
CSVファイルをアップロードするフォーム 「CSVUploadForm」 を作成しました。
さらに、CSVファイルの拡張子のみ許可するように、cleanバリデーション関数も実装しています。
続いて、CSVのデータをデータベースに保存する機能を作成します。
CSVのデータをデータベースに保存する機能をビューに作成
CSVのデータをデータベースに保存する機能をhome/views.pyに作成します。
import pandas as pd
from django.views.generic import FormView
from django.contrib import messages
from django.shortcuts import redirect
from .forms import CSVUploadForm
from .models import Employee
# サンプルページ
class SamplePage(FormView):
template_name = "sample.html"
form_class = CSVUploadForm
model = Employee
# 従業員一覧を表示(なくてもOK)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx["employees"] = self.model.objects.all()
return ctx
# CSVからDBに保存する処理
def form_valid(self, form):
# データ登録用配列
register_list = []
# スキップする行数を指定
SKIP_ROWS = 1
# カラム名を指定
COLUMNS = [
"id",
"employee_name",
"organization_name",
"age",
]
# 文字コードを指定
ENCODING = "utf-8-sig"
# CSVからデータをdf形式で取得
csv_file = form.cleaned_data["csv_file"]
df = pd.read_csv(
csv_file,
skiprows=SKIP_ROWS,
names=COLUMNS,
usecols=COLUMNS,
encoding=ENCODING,
)
# 欠損値を空白に置換
df = df.fillna("")
# データを1行ずつ取得
for row in df.itertuples():
# 未入力の行はスキップ(氏名, 所属名, 年齢を指定)
if not row.employee_name or not row.organization_name or not row.age:
continue
# モデルのフィールド名別にデータを格納
create_dict = {
"employee_name": row.employee_name,
"organization_name": row.organization_name,
"age": row.age,
}
# データ保存候補に追加
register_list.append(self.model(**create_dict))
# DBにデータを保存する処理
if register_list:
# データを一括保存
self.model.objects.bulk_create(register_list)
messages.success(self.request, f"DBにデータ登録が完了しました。")
return redirect("sample_page")
CSVのデータをデータベースに保存する機能全体のプログラムです。
詳しく解説しますね。
import pandas as pd
from django.views.generic import FormView
from django.contrib import messages
from django.shortcuts import redirect
from .forms import CSVUploadForm
from .models import Employee
必要なライブラリをインポートしています。
modelsは、ご自身が用意したモデルをインポートしてください。
formsは、先ほど作成したCSVをアップロードするフォームをインポートしてください。
template_name = "sample.html"
form_class = CSVUploadForm
model = Employee
以下のように指定しています。
template_name : 今回使用するCSVアップロードページのHTML(後に作成)
form_class : CSVアップロード用のフォームクラス(先ほど作成したCSVUploadFormを指定)
model : データを保存するモデル
# 従業員一覧を表示(なくてもOK)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx["employees"] = self.model.objects.all()
return ctx
従業員全データを画面に表示するコードです。
※ データの登録確認に使用するため、なくても問題ありません。
# CSVからDBに保存する処理
def form_valid(self, form):
# データ登録用配列
register_list = []
# スキップする行数を指定
SKIP_ROWS = 1
# カラム名を指定
COLUMNS = [
"id",
"employee_name",
"organization_name",
"age",
]
# 文字コードを指定
ENCODING = "utf-8-sig"
# CSVからデータをdf形式で取得
csv_file = form.cleaned_data["csv_file"]
df = pd.read_csv(
csv_file,
skiprows=SKIP_ROWS,
names=COLUMNS,
usecols=COLUMNS,
encoding=ENCODING,
)
# 欠損値を空白に置換
df = df.fillna("")
# データを1行ずつ取得
for row in df.itertuples():
# 未入力の行はスキップ(氏名, 所属名, 年齢を指定)
if not row.employee_name or not row.organization_name or not row.age:
continue
# モデルのフィールド名別にデータを格納
create_dict = {
"employee_name": row.employee_name,
"organization_name": row.organization_name,
"age": row.age,
}
# データ保存候補に追加
register_list.append(self.model(**create_dict))
# DBにデータを保存する処理
if register_list:
# データを一括保存
self.model.objects.bulk_create(register_list)
messages.success(self.request, f"DBにデータ登録が完了しました。")
return redirect("sample_page")
CSVのデータをデータベースに保存する主要コードです。
# スキップする行数を指定
SKIP_ROWS = 1
# カラム名を指定
COLUMNS = [
"id",
"employee_name",
"organization_name",
"age",
]
# 文字コードを指定
ENCODING = "utf-8-sig"
「SKIP_ROWS」は、CSVファイルを読み込む際にスキップする行数を指定します。
今回使用するCSVファイルは1行目に見出しを含んでいるため、1行目をスキップする設定にしています。
「COLUMNS」は、読み込む列の数と列名を指定します。
列名には、対応するモデルのフィールド名を指定すると分かりやすくなります。
「ENCODING」は、CSVファイルの文字コードを指定します。
今回は「UTF-8」を指定しています。

注意!
もし上記のようなエラーが発生する場合は、指定した文字コードが正しくない可能性があります。
CSVファイルの文字コードを確認し、適切な文字コードを指定してください。
# CSVからデータをdf形式で取得
csv_file = form.cleaned_data["csv_file"]
df = pd.read_csv(
csv_file,
skiprows=SKIP_ROWS,
names=COLUMNS,
usecols=COLUMNS,
encoding=ENCODING,
)
# 欠損値を空白に置換
df = df.fillna("")
フォームから取得したCSVファイルを、先ほど指定したパラメーターを適用し、pandasを使って読み込みます。
また、データに欠損があった場合は、欠損値(NaN)を空白に置換するように設定しています。
# データを1行ずつ取得
for row in df.itertuples():
# 未入力の行はスキップ(氏名, 所属名, 年齢を指定)
if not row.employee_name or not row.organization_name or not row.age:
continue
# モデルのフィールド名別にデータを格納
create_dict = {
"employee_name": row.employee_name,
"organization_name": row.organization_name,
"age": row.age,
}
# データ保存候補に追加
register_list.append(self.model(**create_dict))
# DBにデータを保存する処理
if register_list:
# 配列からデータを一括保存
self.model.objects.bulk_create(register_list)
messages.success(self.request, f"DBにデータ登録が完了しました。")
return redirect("sample_page")
CSVのデータをデータベースにインポートする主要な処理部分は、以下の手順で行っています。
- 読み込んだCSVのデータを1行ずつ取り出します。
- 氏名、所属名、年齢が全て入力済みか確認し、どれか一つでも未入力があればその行をスキップします。
- モデルのフィールド名ごとにデータを格納する辞書を作成します。
- データベースに保存するための配列に辞書データを追加します。
- 格納した配列を 「bulk_create」 関数を使用して、データベースに一括登録します。
- 処理が完了したら、CSVアップロードフォームページにリダイレクトします。
# モデルのフィールド名別にデータを格納
create_dict = {
"employee_name": row.employee_name,
"organization_name": row.organization_name,
"age": row.age,
}
今回は、氏名、所属名、年齢のみをCSVからデータを取得して保存します。
IDと作成日時は自動でデータが追加されるため、含めていません。
urls.pyを作成
ビューを表示するためにhome/urls.pyも作成しておきます。
from django.urls import path
from . import views
urlpatterns = [
path(
"",
views.SamplePage.as_view(),
name="sample_page",
),
]
以上で、CSVのデータをデータベースに保存する機能の作成が完了しました。
次に、CSVアップロードフォームと登録ボタンの設置、そしてモデルデータを確認するためのコードを作成します。
CSVアップロードフォームと登録ボタンの設置とモデルデータ確認画面の作成
CSVアップロードフォームと登録ボタンの設置とモデルデータ確認画面をtemplates/sample.htmlに作成します。
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{% static 'css/base.css' %}">
<title>CSVファイルからDBにデータを保存するページ</title>
</head>
<body>
<main>
<h1>CSVファイルからDBにデータを保存するページ</h1>
<section>
<h2>CSVアップロードフォーム</h2>
<form class="form" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.csv_file }}
<!-- 成功メッセージを表示 -->
<div class="success">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
<!-- エラーメッセージを表示 -->
<div class="error">
{% if form.csv_file.errors %}
{{ form.csv_file.errors }}
{% endif %}
</div>
<button type="submit">CSVからデータをDBに登録する</button>
</form>
</section>
<!-- ここのsectionは無くてもOK -->
<section>
<h2>従業員一覧を表示</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>氏名</th>
<th>所属名</th>
<th>年齢</th>
<th>作成日時</th>
</tr>
</thead>
<tbody>
{% for employee in employees %}
<tr>
<td>{{ employee.id }}</td>
<td>{{ employee.employee_name }}</td>
<td>{{ employee.organization_name }}</td>
<td>{{ employee.age }}</td>
<td>{{ employee.created_at }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
</main>
</body>
</html>
CSVアップロードフォームと登録ボタンの設置とモデルデータ確認画面全体のプログラムです。
詳しく解説しますね。
<section>
<h2>CSVアップロードフォーム</h2>
<form class="form" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.csv_file }}
<!-- 成功メッセージを表示 -->
<div class="success">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
<!-- エラーメッセージを表示 -->
<div class="error">
{% if form.csv_file.errors %}
{{ form.csv_file.errors }}
{% endif %}
</div>
<button type="submit">CSVからデータをDBに登録する</button>
</form>
</section>
CSVをアップロードするフォームと登録ボタンを表示します。
アップロード成功時と失敗時のメッセージも表示できるようにしています。
※ 必須ではありませんが、あったほうが親切ですね!
注意!
ファイルをアップロードする際は、form タグに必ず「enctype="multipart/form-data"」を指定してください。良く忘れがちなので、注意しましょう!
<!-- ここのsectionは無くてもOK -->
<section>
<h2>従業員一覧を表示</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>氏名</th>
<th>所属名</th>
<th>年齢</th>
<th>作成日時</th>
</tr>
</thead>
<tbody>
{% for employee in employees %}
<tr>
<td>{{ employee.id }}</td>
<td>{{ employee.employee_name }}</td>
<td>{{ employee.organization_name }}</td>
<td>{{ employee.age }}</td>
<td>{{ employee.created_at }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
CSVから登録した従業員の全データを表示します。
※ データが正しくインポートされたか確認するためのコードなので、なくても問題ありません。
これでCSVアップロードフォームと登録ボタンの設置、そしてモデルデータ確認画面が完成しました!
実際に動作を確認してみます。
CSVのデータをデータベースに保存する動作確認

今回は、このような従業員CSVデータをデータベースにインポートしてみます。

- データベースに登録したいCSVファイルをアップロードフォームから選択します。
- 「CSVからデータをDBに登録する」ボタンをクリックします。

データベースにインポートが完了し、従業員一覧にもデータが表示されました!
また、「DBにデータ登録が完了しました。」と成功メッセージも表示されていますね!

Django管理画面にも、問題なくデータが反映されています!

もしアップロードされたファイルがCSVでない場合は、エラーメッセージも表示されます。
最後に
CSVを利用してDjangoのデータベースにデータをインポートする方法を解説しました。
CSV形式でデータを作成して、サクッとインポートできるようにしておけばデータの扱いが楽ですよね!
テストデータを作成したり、マスタデータを作成したい時に是非試してみてくださいね!