21: Serialization of Django Objects

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.