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'))
上の例では、 name と size だけがシリアライズされます。
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 がインストールされている場合のみ 利用できます。 |
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
Aug 31, 2012