The Django Serialization framework provides a mechanism for converting Django objects into other formats, usually in the form of text-based and used to send Django objects through a pipeline, but a sequencer can handle any one format (text-based or not)
The Django serialization class is located in the serializers folder below Django.core, and the base.py file defines the base class for the sequencer and the Deserializer and some exceptions, and the __init__.py file defines how to select the corresponding sequencer based on the format. , let's take a look.
The function prototypes for the __init__.py and base.py files are as follows
def serialize (format, Queryset, * *options):"" "serialize a queryset (or any iterator that Returns database objects) Usinga certain serializer. """ =* *options)return s.getvalue () |
def Deserialize (format, stream_or_string, **options): deserialize a stream or a s Tring. Returns an iterator that yields "(obj, m2m_relation_dict) ', where ' obj ' is a instantiated--but *unsaved*--ob Ject, and ' m2m_relation_dict ' is a dictionary of ' {m2m_field_name:list_of_related_objects} '. D = Get_deserializer (format) return D (stream_or_string, **options) |
class Serializer (object): Span style= "color: #800000;" > "" " Abstract serializer base class. # Indicates if the implemented serializer is a available for # internal Django use. Internal_use_only = |
class Deserializer (object): """ Abstract base Deserializer class. """ def __init__ (Self, stream_or_string, **options): |
Well, let's start by formally explaining the Django serialization operation.
Serialization of data
At the top of the API, serializing the data is very easy to manipulate, see above function, serialize function accepts a format and Queryset, returns the serialized data:
A simple notation:
from Import = serializers.serialize ("xml", SomeModel.objects.all ())
A complex notation:
XMLSerializer = Serializers.get_serializer ("xml"== Xml_ Serializer.getvalue ()
To extract the serialized data
As simple as accepting a format and a stream of data, returning an iterator
for in Serializers.deserialize ("xml", data): do_something_with (obj)
However, the deserialize return is not a simple Django type object, but a Deserializedobject instance, and these instances are not saved, use Deserializedobject.save () method to save the data to the database
Serialization format
Django has a lot of serialization formats, some require you to install third-party supported modules, Xml,json and YAML are supported by default
Precautions
If you are using Utf-8 or other non-ASCII encoded data, then use the JSON sequencer, pay attention to wearing a ensure_ascii parameter, otherwise the output encoding will not be normal
Json_serializer = Serializers.get_serializer ("json") () json_serializer.serialize ( Queryset, Ensure_ascii=false, Stream=response)
Serialization parameters
The serialization is acceptable for additional parameters, with a total of three parameters, as follows:
Self.stream = Options.pop ("stream", Stringio ()) = Options.pop (" Fields " , None) = Options.pop ("use_natural_keys", False)
Stream
Output the serialized data to the stream stream, followed by the complex notation above:
out = open ("file.xml""w") xml_serializer.serialize ( SomeModel.objects.all (), Stream=out)
Selected_field
Select the serialized attribute, by setting the fields parameter, fields is a tuple parameter, and the element is the attribute to select to serialize
from Import = serializers.serialize ('xml', SomeModel.objects.all (), fields= (' name ','size'))
Use_natural_keys
Whether to use natural keywords, the default is False (that is, using the primary key)
The default foreign key and many-to-many relationship serialization policy is to use a primary key, which is generally good, but in some cases it is not. For example, when the foreign key to ContentType, because the ContentType is the Django database process synchronization automatically generated, their keywords are not so easy to predict.
An integer ID is also not always the most convenient way to index an object, so based on these conditions, Django provides the Use_natural_keys parameter,
A natural key is a tuple that can be used to distinguish an attribute combination of an element without using a primary key
Natural keys.Solution Serialization
Consider these two models
fromDjango.dbImportModelsclassPerson (models. Model): First_Name= Models. Charfield (max_length=100) last_name= Models. Charfield (max_length=100) Birthdate=models. Datefield ()classMeta:unique_together= (('first_name','last_name'),)classBook (models. Model): Name= Models. Charfield (max_length=100) Author= Models. ForeignKey (person)
The serialized data of the default book will be indexed to an author using an integer, for example, in JSON, the serialized data of a book is like this, 42 is the primary key of the foreign key author
{ "PK": 1, "Model":"Store.book", " Fields": { "name":"Mostly Harmless", "author": 42 }}
But that's not a good way to do it, is it? You need to know which author the primary key represents, and require that the primary key be stable and predictable. So, we can add a natural key handler function, define a Get_by_natural_key method in the corresponding model's management model, for example:
fromDjango.dbImportModelsclass Personmanager(models. Manager):def Get_by_natural_key(self, first_name, last_name):returnSelf.get (First_name=first_name, last_name=last_name)classPerson (models. Model): objects = Personmanager () first_name= Models. Charfield (max_length=100) last_name= Models. Charfield (max_length=100) Birthdate=models. Datefield ()classMeta:unique_together= (('first_name','last_name'),)
After that, the result of the serialization is presumably this:
{ "PK": 1, "Model":"Store.book", " Fields": { "name":"Mostly Harmless", "author": ["Douglas","Adams"] }}
Serialization of the Natural keys
If you want to use natural key when serializing, you must top a Natural_key method in the serialized model and use the Use_natural_keys=true attribute when serializing it as follows:
classPerson (models. Model): Objects=Personmanager () first_name= Models. Charfield (max_length=100) last_name= Models. Charfield (max_length=100) Birthdate=models. Datefield ()def Natural_key(self):return(Self.first_name, Self.last_name)classMeta:unique_together= (('first_name','last_name'),)
Serializers.serialize ('json'use_natural_keys=true)
Note: Natural_key () and Get_by_natural_key () are not defined at the same time, and if you only want to reload natural keys, then you do not have to define the Natural_key () method; If you only want to output these natural keys when serializing, then you don't have to define the Get_by_natural_key () method
Dependencies in the serialization process
Because natural keys relies on database queries to parse references, you must ensure that the data exists before the data is referenced. Look at the following example, if a book's natural key is a combination of the title and the author, you can write:
class Book (models. Model): = models. Charfield (max_length=100) = models. ForeignKey (person) def Natural_key (self): return (self.name,) + Self.author.natural_key ()
So the question is, what if author hasn't been serialized yet? Obviously, author should be serialized before the book, so we can add a dependency as follows:
def Natural_key (self): return (Self.name,) += ['example_app.person']
This ensures that the person object is serialized before the book object, and that any object that references book will be serialized only after the person and book object are serialized
The inherited model
If you are using abstract inheritance, do not care about this problem; If you are using multiple table inheritance, note that all base classes must be serialized, for example:
class Place (models. Model): = models. Charfield (max_length=50)class Restaurant (place): = models. Booleanfield ()
If you only serialize the restaurant model, you will only get a Serves_hot_dog property, the properties of the base class will be ignored, and you must serialize all the inherited models at once, as follows:
all_objects = List (Restaurant.objects.all ()) += serializers.serialize ('XML ' all_objects)
21: Serialization of Django Objects