前提
- DBはMySQLを使用
fixtureとは?
Djangoに備わっている初期データやテスト用データを用意する機能のことです
fixtureを使うことで
- DjangoのAdmin画面から一つずつ手動で入力せずにコマンド一つでデータを投入できる
- Gitで管理すればチームメンバーも同じデータをすぐに投入できる
- fixtureのデータをテストコードのデータとしても流用できる
などメリットが大きいのでぜひ使いましょう!
サンプルモデル
fixtureの説明用に簡単なModelを作成しました
- Author1人に対してBookは複数あるのでOneToMany
- Book複数に対してCustomerは複数存在するのでManyToMany
の関係になります
import uuid
from django.db import models
from django.core.validators import RegexValidator
# 本
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["title"]
db_table = "Book"
# 作者
class Author(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
book = models.ForeignKey("Book", on_delete=models.CASCADE)
name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "Author"
# お客様
class Customer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
kana = models.CharField(max_length=50)
name = models.CharField(max_length=50)
age = models.IntegerField()
post_no = models.CharField(
max_length=7, validators=[RegexValidator(r"^[0-9]{7}$", "7桁の数字を入力してください。")]
)
book = models.ManyToManyField("Book")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["name", "age"]
db_table = "Customer"
fixture用のディレクトリとファイルを用意
fixturesフォルダをアプリケーションディレクトリ配下に作り、fixtures内にデータを作成していきます
└── アプリケーションディレクトリ
└── fixtures
└── fixture用ファイル
fixtureは
- xml
- yaml
- json
の3種類のいずれかを使用することができます
今回はjsonを使用しますので下記のようにbook.jsonを用意してみました
└── アプリケーションディレクトリ
└── fixtures
└── book.json
fixtureを作成してみよう!
fixtureを作成する時は1Modelにつきデータは2つまであれば十分です
以下のように
- modelに対応するアプリケーション名とModel
- PrimaryKey
- PrimaryKey以外のカラムと対応するデータ
- 他ModelのPrimaryKeyに対応するForeignKey
を記載していきます
[
{
"model": "<アプリケーション名>.Book",
"pk":1,
"fields": {
"title":"ハリー・ポッターと賢者の石",
"created_at":"2022-07-28T00:31:09.732Z"
}
},
{
"model": "<アプリケーション名>.Book",
"pk":2,
"fields": {
"title":"ノルウェーの森",
"created_at":"2022-07-28T00:31:09.732Z"
}
},
{
"model": "<アプリケーション名>.Author",
"pk":1,
"fields": {
"book":1,
"name":"J・K・ローリング",
"created_at":"2022-07-28T00:31:09.732Z"
}
},
{
"model": "<アプリケーション名>s.Author",
"pk":2,
"fields": {
"book":2,
"name":"村上春樹",
"created_at":"2022-07-28T00:31:09.732Z"
}
},
{
"model": "<アプリケーション名>.Customer",
"pk":1,
"fields": {
"kana":"タナカイチロウ",
"name":"田中一郎",
"age":20,
"post_no":"6003333",
"book":[1,2],
"created_at":"2022-07-28T00:31:09.732Z"
}
},
{
"model": "r<アプリケーション名>.Customer",
"pk":2,
"fields": {
"kana":"ヤマダハナコ",
"name":"山田花子",
"age":20,
"post_no":"6004444",
"book":[1,2],
"created_at":"2022-07-28T00:31:09.732Z"
}
}
]
Primarykey及びForeignkey
int型のidおよびuuidは1,2と順番に割り振ることができます
many to many fieldの時
今回の例みたいにCustomerとBookの関係はManyToManyの関係なのでCustomerのModelのbookのfieldにはCustomerのPrimaryKeyを全て記載する必要があります
そのため、
"book":1
と記載すると
'int' object is not iterable: field_value was '1'
というエラーが返ってきてしまうため、例のようにList内にPrimaryKeyを全て記載します
"book":[1,2]
timezone
Djangoだとデフォルトでtimezoneが有効になっているため、
例えば
"created_at":"2022-07-28 00:31:09.732"
という風にdatetime型の表記のまま記載すると
RuntimeWarning: DateTimeField Book.date received a naive datetime while time zone support is active.
という警告が出ます
"created_at":"2022-07-28T00:31:09.732Z"
と記載することでtimezoneに対応するdatetimeをDBに入れることができます
作成したデータをDBに入れてみよう!
loaddataコマンドを実行するとデータを入れることができます
今回はbook.jsonのfixtureを使っていますがbookの箇所は自身がつけたfixtureの名前に置き換えてください
python manage.py loaddata book.json
Installed 6 object(s) from 1 fixture(s)
MySQLのテーブルを確認しましょう
以下のようにデータを入れることができたら成功です
mysql> select * from Book;
+----------------------------------+-----------------------------------------+----------------------------+
| id | title | created_at |
+----------------------------------+-----------------------------------------+----------------------------+
| 00000000000000000000000000000001 | ハリー・ポッターと賢者の石 | 2022-07-28 00:31:09.732000 |
| 00000000000000000000000000000002 | ノルウェーの森 | 2022-07-28 00:31:09.732000 |
+----------------------------------+-----------------------------------------+----------------------------+
mysql> select * from Author;
+----------------------------------+-------------------------+----------------------------+----------------------------------+
| id | name | created_at | book_id |
+----------------------------------+-------------------------+----------------------------+----------------------------------+
| 00000000000000000000000000000001 | J・K・ローリング | 2022-07-28 00:31:09.732000 | 00000000000000000000000000000001 |
| 00000000000000000000000000000002 | 村上春樹 | 2022-07-28 00:31:09.732000 | 00000000000000000000000000000002 |
+----------------------------------+-------------------------+----------------------------+----------------------------------+
+----------------------------------+-----------------------+--------------+-----+---------+----------------------------+
| id | kana | name | age | post_no | created_at |
+----------------------------------+-----------------------+--------------+-----+---------+----------------------------+
| 00000000000000000000000000000001 | タナカイチロウ | 田中一郎 | 20 | 6003333 | 2022-07-28 00:31:09.732000 |
| 00000000000000000000000000000002 | ヤマダハナコ | 山田花子 | 20 | 6004444 | 2022-07-28 00:31:09.732000 |
+----------------------------------+-----------------------+--------------+-----+---------+----------------------------+
参考