BuzzLog / バズログ

BuzzLog / バズログはニュースとエンターテインメントを伝えるメディアです

Django の Fixture を使ってデータ生成する

Django で Web アプリケーションを作っていて、
試しにデータ作成したいなぁと思うときが多々あります。
いつもいちいち /admin にアクセスして GUI でデータ作ってしまってます..
「達人プログラマー」では、

人間はコンピュータのように繰り返し作業が得意ではありません。それを期待することも間違っているのです。

という一節がありました。
とても耳が痛いです。
面倒で単調な動作はできるだけプログラムにやらせようということで、
コードベースでデータを自動生成できる仕組みを導入します。

新装版 達人プログラマー 職人から名匠への道

新装版 達人プログラマー 職人から名匠への道

結論からすると「Fixture 使え」ということになって、
Providing initial data for models を読め!
ってので終わりますが、ここでは備忘録代わりに、自分が辿った作業手順をダンプしておきます。

Fixture を直接書くのはしんどい。。

各アプリの model で定義しているデータフォーマット見て、json, yaml を直打ちするのが直接的なアプローチかと思いますが、それしんどくないですか…?

ここでは、「ファイル作成 -> データ注入 -> できた!」という順方向の思考プロセスではなくて、
「既存サイトのデータをダンプ -> ダンプされたファイルを読んで理解 -> ファイル作成」
というアプローチをとります。

admin ページからデータ生成

まずは既存サイト(ここでは Djangoチュートリアルを読み進めて出来る mysite, polls なやつ)で、admin ページから GUI ベースで適当にデータ作成します。
createsuperuser でその名の通りスーパーユーザー作ります。

$ python manage.py createsuperuser --username myname --email myname@email.com

サーバー起動して admin ページにアクセスしましょう。

$ python manage.py runserver

http://localhost:8000/admin にアクセスして適当にデータ作りましょう。

dumpdata でデータフォーマットを確認

以下のコマンドでデータ出力します。
パイプ経由で jq 使っていい感じに見やすくダンプしてみます。

$ python manage.py dumpdata polls | jq .

[
  {
    "model": "polls.question",
    "pk": 1,
    "fields": {
      "question_text": "this is a sample question1",
      "pub_date": "2017-01-28T07:54:09Z"
    }
  },
  {
    "model": "polls.question",
    "pk": 2,
    "fields": {
      "question_text": "this is a sample question2",
      "pub_date": "2017-01-28T07:54:09Z"
    }
  },
  {
    "model": "polls.question",
    "pk": 3,
    "fields": {
      "question_text": "this is a sample question3",
      "pub_date": "2017-01-28T07:54:09Z"
    }
  },
  {
    "model": "polls.choice",
    "pk": 1,
    "fields": {
      "question": 1,
      "choice_text": "sample choice 1",
      "votes": 100
    }
  },
  {
    "model": "polls.choice",
    "pk": 2,
    "fields": {
      "question": 2,
      "choice_text": "sample choice 2",
      "votes": 200
    }
  },
  {
    "model": "polls.choice",
    "pk": 3,
    "fields": {
      "question": 3,
      "choice_text": "sample choice 3",
      "votes": 300
    }
  }
]

あー、こんな風にデータ出力されるのね。
GUI ベースで入れたデータとの整合性を把握しつつ、
どこを修正すればいいかはサクッと理解できました。

loaddata でデータを注入

先程ダンプしたデータをファイルに吐いて、
今度はファイルからデータ生成してみましょう。
Django では主に json or yaml フォーマットで fixture を作成できるようです。
さっきのコマンド流用しつつ以下のコマンドでファイルにダンプします。

python manage.py dumpdata polls | jq . > polls/fixtures/polls_json.json

どうやら、ファイルは Django が認識出来るようにするため、 fixtures/ 以下に置く必要があるようです。

json ファイルからデータ注入

(ファイル名若干変だけどご愛嬌) polls_json.json に記載したデータが、
データベースに適切に取り込まれるかを以下のコマンドで確認します。

$ python manage.py loaddata polls_json

Installed 6 object(s) from 1 fixture(s)

みたいなのがダンプされれば OK /admin にアクセスしてみて確かに反映されていることを確認しました。

ついでに yaml でも

以下の内容で polls/fixtures/polls_yaml.yaml を作成します。

- model: polls.question
  pk: 1
  fields:
    question_text: this is a sample question1
    pub_date: 2017-01-28T07:54:09Z

- model: polls.question
  pk: 2
  fields:
    question_text: this is a sample question2
    pub_date: 2017-01-28T07:54:09Z

- model: polls.question
  pk: 3
  fields:
    question_text: this is a sample question3
    pub_date: 2017-01-28T07:54:09Z

# Choice ----------
- model: polls.choice
  pk: 1
  fields:
    question: 1
    choice_text: sample choice 1
    votes: 100

- model: polls.choice
  pk: 2
  fields:
    question: 2
    choice_text: sample choice 2
    votes: 200

- model: polls.choice
  pk: 3
  fields:
    question: 3
    choice_text: sample choice 3
    votes: 300

yaml ファイルからデータ注入

yaml でも取り込めることを確認。

$ python manage.py loaddata polls_yaml

参考図書

入門 Python 3

入門 Python 3

Lightweight Django

Lightweight Django