Django オブジェクトのシリアライズ

revision-up-to:7193 (0.97pre SVN)

Note

この API は現在まだ開発のまっただなかにあり,おそらく将来劇的に変化する でしょう.

注意してください.

Django の整列化フレームワークを使うと, Django オブジェクトを他の形式に「翻 訳」できます.通常,こうした形式はテキストベースで, Django オブジェクトを ネットワーク越しに伝送するために使われますが, Django のシリアライザは任意 の形式 (テキストベースもそうでないものも) 扱えます.

データのシリアライズ

高水準では,データのシリアライズは極めて簡単な操作です:

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

serialize 関数の引数には,データのシリアライズに使うフォーマット (シリアライズの形式 参照) と,シリアライズ対象の QuerySet を指定します (実際には,第二引数は Django オブジェクトを返す任意のイテレータにできますが, 大抵の場合は QuerySet を使うことになるでしょう).

シリアライザオブジェクトを直接使ってもかまいません:

XMLSerializer = serializers.get_serializer("xml")
xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()

シリアライザオブジェクトを直接使うと,以下のようにファイルライクオブジェク ト (もちろん HTTPResponse も使えます) に対して直接シリアライズできるので便 利です:

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

一部のフィールドだけをシリアライズする

一部のフィールドだけをシリアライズしたい場合には,シリアライザに fields 引数を指定します:

from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))

上の例では, namesize だけがシリアライズされます.

Note

モデルによっては,フィールドの一部だけをシリアライズすると,そこからデ シリアライズできない場合があります.シリアライズ後のオブジェクトに,モ デル上で必須のフィールドがひとつでも抜け落ちていると,デシリアライザは デシリアライズ後のインスタンスを保存できないでしょう.

データのデシリアライズ

データのデシリアライズもまた,かなり単純な操作です:

for obj in serializers.deserialize("xml", data):
    do_something_with(obj)

見ての通り, deserialize 関数は serialize 関数と同様,文字列または データストリームを引数にとり,イテレータを返します.

しかしながら,少しだけややこしい部分もあります. deserialize イテレータ の返すオブジェクトは単純な Django オブジェクト ではなくDeserializedObject という特殊なインスタンスです.このインスタンスは 作成されただけでまだ保存されていないデータであり,リレーションも張られてい ません.

DeserializedObject.save() を呼び出すと,データベースにオブジェクトを保 存します.

上のような仕様から,デシリアライズは,たとえシリアライズされていたデータの 表現形式が現在のデータベースの構成と一致していなかったとしても非破壊的な操 作になるよう保証されています.通常, DeserializedObject インスタンスの 操作は以下のように行います:

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

すなわち,デシリアライズしたオブジェクトを保存する場合,前もって保存に適し ているかどうかを調べるのが普通のやり方なのです.もちろん,データソースを信 頼できるのなら,単にデータを保存してもかまいません.

Django オブジェクト自体に対するインスペクションは, deserialized_object.object で行えます.

シリアライズの形式

Django には各種形式のシリアライザが付属しています:

名前 情報
xml 単純な XML シリアライザです.
json JSON シリアライザ (Django に付属の simplejson を使ったも の) です.
python 「単純な」Python オブジェクト (リスト,辞書,文字列など) の シリアライザです.単体では取り立てて便利ではありませんが, 他のシリアライザのベースになっています.
yaml YAML (Yet Another Markup Language) へのシリアライザです. このシリアライザは PyYAML がインストールされている場合のみ 利用できます.

各シリアライズ形式についての注意

json

UTF-8 (や,非 ASCII エンコーディング) でエンコードされたデータを JSON シリ アライザで扱うには, serialize() のパラメタに ensure_ascii=False を 指定してください.さもないと,出力のエンコードがおかしくなってしまいます.

例:

json_serializer = serializers.get_serializer("json")()
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)

Django のソースコードには simplejson モジュールが付属しています。注意して ほしいのは、このモジュールを直接使ってシリアライズを実行すると、一部の Django オブジェクトは何らかの変更が加えられた上で simplejson に渡されてしま うということです。特に、 遅延翻訳オブジェクト をシリアライズする場合は、 特殊なエンコーダ が必要です。以下のように書くと、うまくいくでしょう:

from django.utils.functional import Promise
from django.utils.encoding import force_unicode

class LazyEncoder(simplejson.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Promise):
            return force_unicode(obj)
        return obj