2007-09-15 13:32:29 +08:00
# -*- coding: utf-8 -*-
2006-06-29 00:00:37 +08:00
"""
2007-12-02 05:18:45 +08:00
42. Serialization
2006-06-29 00:00:37 +08:00
` ` django . core . serializers ` ` provides interfaces to converting Django querysets
to and from " flat " data ( i . e . strings ) .
"""
from django . db import models
class Category ( models . Model ) :
2007-08-05 13:14:46 +08:00
name = models . CharField ( max_length = 20 )
2006-06-29 00:00:37 +08:00
class Meta :
ordering = ( ' name ' , )
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
def __unicode__ ( self ) :
2006-06-29 00:00:37 +08:00
return self . name
class Author ( models . Model ) :
2007-08-05 13:14:46 +08:00
name = models . CharField ( max_length = 20 )
2006-06-29 00:00:37 +08:00
class Meta :
ordering = ( ' name ' , )
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
def __unicode__ ( self ) :
2006-06-29 00:00:37 +08:00
return self . name
class Article ( models . Model ) :
author = models . ForeignKey ( Author )
2007-08-05 13:14:46 +08:00
headline = models . CharField ( max_length = 50 )
2006-06-29 00:00:37 +08:00
pub_date = models . DateTimeField ( )
categories = models . ManyToManyField ( Category )
class Meta :
ordering = ( ' pub_date ' , )
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
def __unicode__ ( self ) :
2006-06-29 00:00:37 +08:00
return self . headline
2007-01-27 21:42:51 +08:00
class AuthorProfile ( models . Model ) :
author = models . OneToOneField ( Author )
date_of_birth = models . DateField ( )
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
def __unicode__ ( self ) :
return u " Profile of %s " % self . author
2007-09-15 13:32:29 +08:00
class Actor ( models . Model ) :
name = models . CharField ( max_length = 20 , primary_key = True )
class Meta :
ordering = ( ' name ' , )
def __unicode__ ( self ) :
return self . name
class Movie ( models . Model ) :
actor = models . ForeignKey ( Actor )
title = models . CharField ( max_length = 50 )
class Meta :
ordering = ( ' title ' , )
def __unicode__ ( self ) :
return self . title
2007-09-22 21:21:54 +08:00
class Score ( models . Model ) :
score = models . FloatField ( )
2007-01-27 21:42:51 +08:00
2006-08-27 21:59:47 +08:00
__test__ = { ' API_TESTS ' : """
2006-06-29 00:00:37 +08:00
# Create some data:
>> > from datetime import datetime
>> > sports = Category ( name = " Sports " )
>> > music = Category ( name = " Music " )
>> > op_ed = Category ( name = " Op-Ed " )
>> > sports . save ( ) ; music . save ( ) ; op_ed . save ( )
>> > joe = Author ( name = " Joe " )
>> > jane = Author ( name = " Jane " )
>> > joe . save ( ) ; jane . save ( )
>> > a1 = Article (
. . . author = jane ,
. . . headline = " Poker has no place on ESPN " ,
. . . pub_date = datetime ( 2006 , 6 , 16 , 11 , 00 ) )
>> > a2 = Article (
. . . author = joe ,
. . . headline = " Time to reform copyright " ,
2007-09-22 21:21:54 +08:00
. . . pub_date = datetime ( 2006 , 6 , 16 , 13 , 00 , 11 , 345 ) )
2006-06-29 00:00:37 +08:00
>> > a1 . save ( ) ; a2 . save ( )
>> > a1 . categories = [ sports , op_ed ]
>> > a2 . categories = [ music , op_ed ]
# Serialize a queryset to XML
>> > from django . core import serializers
>> > xml = serializers . serialize ( " xml " , Article . objects . all ( ) )
# The output is valid XML
>> > from xml . dom import minidom
>> > dom = minidom . parseString ( xml )
# Deserializing has a similar interface, except that special DeserializedObject
# instances are returned. This is because data might have changed in the
# database since the data was serialized (we'll simulate that below).
>> > for obj in serializers . deserialize ( " xml " , xml ) :
. . . print obj
< DeserializedObject : Poker has no place on ESPN >
< DeserializedObject : Time to reform copyright >
# Deserializing data with different field values doesn't change anything in the
# database until we call save():
>> > xml = xml . replace ( " Poker has no place on ESPN " , " Poker has no place on television " )
>> > objs = list ( serializers . deserialize ( " xml " , xml ) )
# Even those I deserialized, the database hasn't been touched
>> > Article . objects . all ( )
[ < Article : Poker has no place on ESPN > , < Article : Time to reform copyright > ]
# But when I save, the data changes as you might except.
>> > objs [ 0 ] . save ( )
>> > Article . objects . all ( )
[ < Article : Poker has no place on television > , < Article : Time to reform copyright > ]
2006-06-30 00:42:49 +08:00
# Django also ships with a built-in JSON serializers
>> > json = serializers . serialize ( " json " , Category . objects . filter ( pk = 2 ) )
>> > json
2007-09-15 13:32:29 +08:00
' [ { " pk " : 2, " model " : " serializers.category " , " fields " : { " name " : " Music " }}] '
2006-06-30 00:42:49 +08:00
# You can easily create new objects by deserializing data with an empty PK
# (It's easier to demo this with JSON...)
>> > new_author_json = ' [ { " pk " : null, " model " : " serializers.author " , " fields " : { " name " : " Bill " }}] '
>> > for obj in serializers . deserialize ( " json " , new_author_json ) :
. . . obj . save ( )
>> > Author . objects . all ( )
[ < Author : Bill > , < Author : Jane > , < Author : Joe > ]
# All the serializers work the same
>> > json = serializers . serialize ( " json " , Article . objects . all ( ) )
>> > for obj in serializers . deserialize ( " json " , json ) :
. . . print obj
< DeserializedObject : Poker has no place on television >
< DeserializedObject : Time to reform copyright >
>> > json = json . replace ( " Poker has no place on television " , " Just kidding; I love TV poker " )
>> > for obj in serializers . deserialize ( " json " , json ) :
. . . obj . save ( )
>> > Article . objects . all ( )
[ < Article : Just kidding ; I love TV poker > , < Article : Time to reform copyright > ]
2007-01-27 21:42:51 +08:00
# If you use your own primary key field (such as a OneToOneField),
# it doesn't appear in the serialized field list - it replaces the
# pk identifier.
>> > profile = AuthorProfile ( author = joe , date_of_birth = datetime ( 1970 , 1 , 1 ) )
>> > profile . save ( )
>> > json = serializers . serialize ( " json " , AuthorProfile . objects . all ( ) )
>> > json
2007-09-15 13:32:29 +08:00
' [ { " pk " : 1, " model " : " serializers.authorprofile " , " fields " : { " date_of_birth " : " 1970-01-01 " }}] '
2007-01-27 21:42:51 +08:00
>> > for obj in serializers . deserialize ( " json " , json ) :
. . . print obj
< DeserializedObject : Profile of Joe >
2007-02-27 01:33:27 +08:00
# Objects ids can be referenced before they are defined in the serialization data
# However, the deserialization process will need to be contained within a transaction
2007-09-15 13:32:29 +08:00
>> > json = ' [ { " pk " : 3, " model " : " serializers.article " , " fields " : { " headline " : " Forward references pose no problem " , " pub_date " : " 2006-06-16 15:00:00 " , " categories " : [4, 1], " author " : 4}}, { " pk " : 4, " model " : " serializers.category " , " fields " : { " name " : " Reference " }}, { " pk " : 4, " model " : " serializers.author " , " fields " : { " name " : " Agnes " }}] '
2007-02-27 01:33:27 +08:00
>> > from django . db import transaction
>> > transaction . enter_transaction_management ( )
>> > transaction . managed ( True )
>> > for obj in serializers . deserialize ( " json " , json ) :
. . . obj . save ( )
>> > transaction . commit ( )
>> > transaction . leave_transaction_management ( )
>> > article = Article . objects . get ( pk = 3 )
>> > article
< Article : Forward references pose no problem >
>> > article . categories . all ( )
[ < Category : Reference > , < Category : Sports > ]
>> > article . author
< Author : Agnes >
2007-06-01 21:39:08 +08:00
# Serializer output can be restricted to a subset of fields
>> > print serializers . serialize ( " json " , Article . objects . all ( ) , fields = ( ' headline ' , ' pub_date ' ) )
2007-09-22 21:21:54 +08:00
[ { " pk " : 1 , " model " : " serializers.article " , " fields " : { " headline " : " Just kidding; I love TV poker " , " pub_date " : " 2006-06-16 11:00:00 " } } , { " pk " : 2 , " model " : " serializers.article " , " fields " : { " headline " : " Time to reform copyright " , " pub_date " : " 2006-06-16 13:00:11 " } } , { " pk " : 3 , " model " : " serializers.article " , " fields " : { " headline " : " Forward references pose no problem " , " pub_date " : " 2006-06-16 15:00:00 " } } ]
2007-09-15 13:32:29 +08:00
# Every string is serialized as a unicode object, also primary key
# which is 'varchar'
>> > ac = Actor ( name = " Zażółć " )
>> > mv = Movie ( title = " Gęślą jaźń " , actor = ac )
>> > ac . save ( ) ; mv . save ( )
# Let's serialize our movie
>> > print serializers . serialize ( " json " , [ mv ] )
[ { " pk " : 1 , " model " : " serializers.movie " , " fields " : { " actor " : " Za \u017c \u00f3 \u0142 \u0107 " , " title " : " G \u0119 \u015b l \u0105 ja \u017a \u0144 " } } ]
# Deserialization of movie
>> > list ( serializers . deserialize ( ' json ' , serializers . serialize ( ' json ' , [ mv ] ) ) ) [ 0 ] . object . title
u ' G \u0119 \u015b l \u0105 ja \u017a \u0144 '
# None is null after serialization to json
# Primary key is None in case of not saved model
>> > mv2 = Movie ( title = " Movie 2 " , actor = ac )
>> > print serializers . serialize ( " json " , [ mv2 ] )
[ { " pk " : null , " model " : " serializers.movie " , " fields " : { " actor " : " Za \u017c \u00f3 \u0142 \u0107 " , " title " : " Movie 2 " } } ]
# Deserialization of null returns None for pk
>> > print list ( serializers . deserialize ( ' json ' , serializers . serialize ( ' json ' , [ mv2 ] ) ) ) [ 0 ] . object . id
None
2007-06-01 21:39:08 +08:00
2007-09-22 21:21:54 +08:00
# Serialization and deserialization of floats:
>> > sc = Score ( score = 3.4 )
>> > print serializers . serialize ( " json " , [ sc ] )
[ { " pk " : null , " model " : " serializers.score " , " fields " : { " score " : 3.4 } } ]
>> > print list ( serializers . deserialize ( ' json ' , serializers . serialize ( ' json ' , [ sc ] ) ) ) [ 0 ] . object . score
3.4
2006-08-27 21:59:47 +08:00
""" }