.. _topics-serialization: ================================= Django オブジェクトのシリアライズ ================================= :revision-up-to: 8961 (1.0) Django の整列化フレームワークを使うと、 Django オブジェクトを他の形式に「翻 訳」できます。通常、こうした形式はテキストベースで、 Django オブジェクトを ネットワーク越しに伝送するために使われますが、 Django のシリアライザは任意 の形式 (テキストベースもそうでないものも) 扱えます。 .. _Serializing data: データのシリアライズ -------------------- 高水準では、データのシリアライズは極めて簡単な操作です:: from django.core import serializers data = serializers.serialize("xml", SomeModel.objects.all()) ``serialize`` 関数の引数には、データのシリアライズに使うフォーマット (`シリアライズの形式`_ 参照) と、シリアライズ対象の :class:`~django.db.models.QuerySet` (実際には、第二引数は Django オブジェク トを返す任意のイテレータにできますが、大抵の場合は QuerySet を使うことにな るでしょう)。 シリアライザオブジェクトを直接使ってもかまいません:: XMLSerializer = serializers.get_serializer("xml") xml_serializer = XMLSerializer() xml_serializer.serialize(queryset) data = xml_serializer.getvalue() シリアライザオブジェクトを直接使うと、以下のようにファイルライクオブジェク ト (もちろん :class:`~django.http.HttpResponse` も使えます) に対して直接シ リアライズできるので便利です:: out = open("file.xml", "w") xml_serializer.serialize(SomeModel.objects.all(), stream=out) .. _Subset of fields: 一部のフィールドだけをシリアライズする ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 一部のフィールドだけをシリアライズしたい場合には、シリアライザに ``fields`` 引数を指定します:: from django.core import serializers data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size')) 上の例では、 ``name`` と ``size`` だけがシリアライズされます。 .. note:: モデルによっては、フィールドの一部だけをシリアライズすると、そこからデ シリアライズできない場合があります。シリアライズ後のオブジェクトに、モ デル上で必須のフィールドがひとつでも抜け落ちていると、デシリアライザは デシリアライズ後のインスタンスを保存できないでしょう。 .. _Inherited Models: 継承を行っているモデルインスタンスのシリアライズ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :ref:`抽象ベースクラス ` を使って定義したモデルを扱っ ていても、モデルのシリアライズのために特に行うことはありません。単にシリア ライズしたオブジェクトに対してシリアライザを呼び出せば、完全なシリアライズ 済みオブジェクトが出力されます。 ただし、 :ref:`マルチテーブル継承 ` を使って定義さ れているモデルを扱う場合、モデルの全てのベースクラスをシリアライズする必要 があります。これは、モデルごとに固有に定義されたフィールドがシリアライズさ れるためです。例えば、以下のようなモデルを考えましょう:: 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) .. _Deserializing data: データのデシリアライズ ---------------------- データのデシリアライズもまた、かなり単純な操作です:: 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`` で行えます。 .. _serialization-formats: .. _Serialization formats: シリアライズの形式 ------------------ Django には各種形式のシリアライザが付属しています: ========== ============================================================== 名前 情報 ========== ============================================================== ``xml`` 単純な XML シリアライザです。 ``json`` JSON_ シリアライザ (Django に付属の simplejson_ を使ったも の) です。 ``python`` 「単純な」Python オブジェクト (リスト、辞書、文字列など) の シリアライザです。単体では取り立てて便利ではありませんが、 他のシリアライザのベースになっています。 ``yaml`` YAML (YAML Ain't a Markup Language) へのシリアライザです。 このシリアライザは PyYAML_ がインストールされている場合のみ 利用できます。 ========== ============================================================== .. _json: http://json.org/ .. _PyYAML: http://www.pyyaml.org/ .. _Notes For specific serialization formats: 各シリアライズ形式についての注意 -------------------------------- 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 に渡されてしま うということです。特に、 :ref:`遅延翻訳オブジェクト ` を シリアライズする場合は、 `特殊なエンコーダ`_ が必要です。以下のように書くと、 うまくいくでしょう:: 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 .. _simplejson: http://undefined.org/python/#simplejson .. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html .. _`特殊なエンコーダ`: `special encoder`_