154 lines
5.6 KiB
Plaintext
154 lines
5.6 KiB
Plaintext
==========================
|
|
Serializing Django objects
|
|
==========================
|
|
|
|
.. note::
|
|
|
|
This API is currently under heavy development and may change --
|
|
perhaps drastically -- in the future.
|
|
|
|
You have been warned.
|
|
|
|
Django's serialization framework provides a mechanism for "translating" Django
|
|
objects into other formats. Usually these other formats will be text-based and
|
|
used for sending Django objects over a wire, but it's possible for a
|
|
serializer to handle any format (text-based or not).
|
|
|
|
Serializing data
|
|
----------------
|
|
|
|
At the highest level, serializing data is a very simple operation::
|
|
|
|
from django.core import serializers
|
|
data = serializers.serialize("xml", SomeModel.objects.all())
|
|
|
|
The arguments to the ``serialize`` function are the format to serialize the
|
|
data to (see `Serialization formats`_) and a QuerySet_ to serialize.
|
|
(Actually, the second argument can be any iterator that yields Django objects,
|
|
but it'll almost always be a QuerySet).
|
|
|
|
.. _QuerySet: ../db-api/#retrieving-objects
|
|
|
|
You can also use a serializer object directly::
|
|
|
|
XMLSerializer = serializers.get_serializer("xml")
|
|
xml_serializer = XMLSerializer()
|
|
xml_serializer.serialize(queryset)
|
|
data = xml_serializer.getvalue()
|
|
|
|
This is useful if you want to serialize data directly to a file-like object
|
|
(which includes a HTTPResponse_)::
|
|
|
|
out = open("file.xml", "w")
|
|
xml_serializer.serialize(SomeModel.objects.all(), stream=out)
|
|
|
|
.. _HTTPResponse: ../request_response/#httpresponse-objects
|
|
|
|
Subset of fields
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
If you only want a subset of fields to be serialized, you can
|
|
specify a ``fields`` argument to the serializer::
|
|
|
|
from django.core import serializers
|
|
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
|
|
|
|
In this example, only the ``name`` and ``size`` attributes of each model will
|
|
be serialized.
|
|
|
|
.. note::
|
|
|
|
Depending on your model, you may find that it is not possible to deserialize
|
|
a model that only serializes a subset of its fields. If a serialized object
|
|
doesn't specify all the fields that are required by a model, the deserializer
|
|
will not be able to save deserialized instances.
|
|
|
|
Deserializing data
|
|
------------------
|
|
|
|
Deserializing data is also a fairly simple operation::
|
|
|
|
for obj in serializers.deserialize("xml", data):
|
|
do_something_with(obj)
|
|
|
|
As you can see, the ``deserialize`` function takes the same format argument as
|
|
``serialize``, a string or stream of data, and returns an iterator.
|
|
|
|
However, here it gets slightly complicated. The objects returned by the
|
|
``deserialize`` iterator *aren't* simple Django objects. Instead, they are
|
|
special ``DeserializedObject`` instances that wrap a created -- but unsaved --
|
|
object and any associated relationship data.
|
|
|
|
Calling ``DeserializedObject.save()`` saves the object to the database.
|
|
|
|
This ensures that deserializing is a non-destructive operation even if the
|
|
data in your serialized representation doesn't match what's currently in the
|
|
database. Usually, working with these ``DeserializedObject`` instances looks
|
|
something like::
|
|
|
|
for deserialized_object in serializers.deserialize("xml", data):
|
|
if object_should_be_saved(deserialized_object):
|
|
obj.save()
|
|
|
|
In other words, the usual use is to examine the deserialized objects to make
|
|
sure that they are "appropriate" for saving before doing so. Of course, if you trust your data source you could just save the object and move on.
|
|
|
|
The Django object itself can be inspected as ``deserialized_object.object``.
|
|
|
|
Serialization formats
|
|
---------------------
|
|
|
|
Django "ships" with a few included serializers:
|
|
|
|
========== ==============================================================
|
|
Identifier Information
|
|
========== ==============================================================
|
|
``xml`` Serializes to and from a simple XML dialect.
|
|
|
|
``json`` Serializes to and from JSON_ (using a version of simplejson_
|
|
bundled with Django).
|
|
|
|
``python`` Translates to and from "simple" Python objects (lists, dicts,
|
|
strings, etc.). Not really all that useful on its own, but
|
|
used as a base for other serializers.
|
|
|
|
``yaml`` Serializes to YAML (Yet Another Markup Lanuage). This
|
|
serializer is only available if PyYAML_ is installed.
|
|
========== ==============================================================
|
|
|
|
.. _json: http://json.org/
|
|
.. _simplejson: http://undefined.org/python/#simplejson
|
|
.. _PyYAML: http://www.pyyaml.org/
|
|
|
|
Notes for specific serialization formats
|
|
----------------------------------------
|
|
|
|
json
|
|
~~~~
|
|
|
|
If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON
|
|
serializer, you must pass ``ensure_ascii=False`` as a parameter to the
|
|
``serialize()`` call. Otherwise, the output won't be encoded correctly.
|
|
|
|
For example::
|
|
|
|
json_serializer = serializers.get_serializer("json")()
|
|
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
|
|
|
|
The Django source code includes the simplejson_ module. Be aware that if
|
|
you're serializing using that module directly, not all Django output can be
|
|
passed unmodified to simplejson. In particular, `lazy translation objects`_
|
|
need a `special encoder`_ written for them. Something like this will work::
|
|
|
|
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
|
|
|
|
.. _lazy translation objects: ../i18n/#lazy-translation
|
|
.. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html
|