読者です 読者をやめる 読者になる 読者になる

へっぽこびんぼう野郎のnewbie日記

けろけーろ(´・ω・`)!

jsonファイルやxmlファイルからDjangoのmodelにデータを移動する方法

やりたいこと

data.json

{

{"name": "yamada", "age":26},
{"name": "takemura", "age":31},

}

のようなデータを
DJangoのmodelに突っ込みまくりたいときがあるとする。
(要はデータベースに格納したい)
これを、import simplejsonみたいなことして、for文で回転させて入れるのはかなりめんどくさい。

Djangoにはなんとこれを簡略化してくれる驚きの機能があった。

シリアライズとデシリアライズ(直列化)

pickleのjsonとかxml版のものが、Djangoには用意されていた。

Serializing Django objects | Django documentation | Django

シリアライズは、
データベースに格納されているデータをmodelから
jsonの形とか、xmlの形とかの文字列にしてくれるすぐれものだ。
要はこんな形で出力できる。

serialized.json

{

{"field": {"name": "yamada", "age":26}, "model": "apps.person_model", "pk": 1}
{"field": {"name": "takemura", "age":31}, "model": "apps.person_model", "pk": 2}

}

とりあえずシリアライズの方法(かきこみ)

ひとまずDjangoのシェル機能を

$ python manage.py shell

で立ち上げて

from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all())

してあげれば、str型のデータを得られる。重要なのはパッと見た感じリストやらディクショナリに見えるけど、よく見ると文字列なことだ。
SomeModelのとこは好きなモデルを選んでね!(もちろんmodelの場所をimportしないとダメだ)

ファイルに書き出したいときはこうする。(これはxmlだけど、別にjsonにしてもいい)

with open("file.xml", "w") as out:
xml_serializer.serialize(SomeModel.objects.all(), stream=out)

シリアライズの方法(読み込み)のための下ごしらえ

読み込みするために

data.json

{

{"name": "yamada", "age":26},
{"name": "takemura", "age":31},

}

data.json

{

{"field": {"name": "yamada", "age":26}, "model": "apps.person_model", "pk": 1}
{"field": {"name": "takemura", "age":31}, "model": "apps.person_model", "pk": 2}

}

のように変えてあげよう!

これは、Djangoシリアライズするときにこういうフォーマットになるので、読み込むときは逆にこの形でないといけないためだ。
"model"の値は、読み込みをさせるmodelのクラスを書く。よくわからないが小文字でいいらしい。
結構めんどくさいが、めんどくさいと言っても
行頭に{"field": 、行末に"model": "apps.person_model", "pk": 連番数字}のようにしていくだけなので
vimのマクロとかを使えば一瞬で終わるはず。

シリアライズ

さっきのjsonファイルを読み込む。
読み込むと言っても、import jsonのように、モジュールを使って読み込まなくてもいい。
普通にファイルを読み込むようにしてあげればいいはず。

f = open('data.json')
data = f.read()

これでdataにファイルがまるごとstr型で格納された。

でその後、データベースへ入れていく

for obj in serializers.deserialize("json", data):
obj.save()

でも公式ドキュメントによるとこっちのほうが推奨だからこっち使ったほうが良さそう。

for deserialized_object in serializers.deserialize("xml", data):
if object_should_be_saved(deserialized_object):
deserialized_object.save()

おわりに

データベースってなんかこうガーッ!と、使えないのかな。