Django v1.0 documentation

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

revision-up-to:8961 (1.0)

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

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

継承を行っているモデルインスタンスのシリアライズ

抽象ベースクラス を使って定義したモデルを扱っ ていても、モデルのシリアライズのために特に行うことはありません。単にシリア ライズしたオブジェクトに対してシリアライザを呼び出せば、完全なシリアライズ 済みオブジェクトが出力されます。

ただし、 マルチテーブル継承 を使って定義さ れているモデルを扱う場合、モデルの全てのベースクラスをシリアライズする必要 があります。これは、モデルごとに固有に定義されたフィールドがシリアライズさ れるためです。例えば、以下のようなモデルを考えましょう:

class Place(models.Model):
    name = models.CharField(max_length=50)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()

ここで、 Restaurant モデルだけをシリアライズしたとします:

data = serializers.serialize('xml', Restaurant.objects.all())

シリアライズ後の出力には、 serves_hot_dogs という属性しか入りません。 ベースクラスの name 属性は無視されるのです。

上の Restaurant インスタンスを完全にシリアライズするには、以下のように して Place モデルもシリアライズする必要があります:

all_objects = list(Restaurant.objects.all()) + list(Place.objects.all())
data = serializers.serialize('xml', all_objects)

データのデシリアライズ

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

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 (YAML Ain't a 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