1
# -*- coding: utf-8 -*-
5
``django.core.serializers`` provides interfaces to converting Django
6
``QuerySet`` objects to and from "flat" data (i.e. strings).
10
from decimal import Decimal
12
from django.utils._decimal import Decimal # Python 2.3 fallback
14
from django.db import models
16
class Category(models.Model):
17
name = models.CharField(max_length=20)
22
def __unicode__(self):
25
class Author(models.Model):
26
name = models.CharField(max_length=20)
31
def __unicode__(self):
34
class Article(models.Model):
35
author = models.ForeignKey(Author)
36
headline = models.CharField(max_length=50)
37
pub_date = models.DateTimeField()
38
categories = models.ManyToManyField(Category)
41
ordering = ('pub_date',)
43
def __unicode__(self):
46
class AuthorProfile(models.Model):
47
author = models.OneToOneField(Author, primary_key=True)
48
date_of_birth = models.DateField()
50
def __unicode__(self):
51
return u"Profile of %s" % self.author
53
class Actor(models.Model):
54
name = models.CharField(max_length=20, primary_key=True)
59
def __unicode__(self):
62
class Movie(models.Model):
63
actor = models.ForeignKey(Actor)
64
title = models.CharField(max_length=50)
65
price = models.DecimalField(max_digits=6, decimal_places=2, default=Decimal('0.00'))
70
def __unicode__(self):
73
class Score(models.Model):
74
score = models.FloatField()
78
def __init__(self, title):
81
def __unicode__(self):
82
raise NotImplementedError("Not so simple")
85
raise NotImplementedError("Not so simple")
88
return "%s" % self.title
90
class TeamField(models.CharField):
91
__metaclass__ = models.SubfieldBase
94
super(TeamField, self).__init__(max_length=100)
96
def get_db_prep_save(self, value):
97
return unicode(value.title)
99
def to_python(self, value):
100
if isinstance(value, Team):
104
def value_to_string(self, obj):
105
return self._get_val_from_obj(obj).to_string()
107
class Player(models.Model):
108
name = models.CharField(max_length=50)
109
rank = models.IntegerField()
112
def __unicode__(self):
113
return u'%s (%d) playing for %s' % (self.name, self.rank, self.team.to_string())
115
__test__ = {'API_TESTS':"""
117
>>> from datetime import datetime
118
>>> sports = Category(name="Sports")
119
>>> music = Category(name="Music")
120
>>> op_ed = Category(name="Op-Ed")
121
>>> sports.save(); music.save(); op_ed.save()
123
>>> joe = Author(name="Joe")
124
>>> jane = Author(name="Jane")
125
>>> joe.save(); jane.save()
129
... headline = "Poker has no place on ESPN",
130
... pub_date = datetime(2006, 6, 16, 11, 00))
133
... headline = "Time to reform copyright",
134
... pub_date = datetime(2006, 6, 16, 13, 00, 11, 345))
135
>>> a1.save(); a2.save()
136
>>> a1.categories = [sports, op_ed]
137
>>> a2.categories = [music, op_ed]
139
# Serialize a queryset to XML
140
>>> from django.core import serializers
141
>>> xml = serializers.serialize("xml", Article.objects.all())
143
# The output is valid XML
144
>>> from xml.dom import minidom
145
>>> dom = minidom.parseString(xml)
147
# Deserializing has a similar interface, except that special DeserializedObject
148
# instances are returned. This is because data might have changed in the
149
# database since the data was serialized (we'll simulate that below).
150
>>> for obj in serializers.deserialize("xml", xml):
152
<DeserializedObject: Poker has no place on ESPN>
153
<DeserializedObject: Time to reform copyright>
155
# Deserializing data with different field values doesn't change anything in the
156
# database until we call save():
157
>>> xml = xml.replace("Poker has no place on ESPN", "Poker has no place on television")
158
>>> objs = list(serializers.deserialize("xml", xml))
160
# Even those I deserialized, the database hasn't been touched
161
>>> Article.objects.all()
162
[<Article: Poker has no place on ESPN>, <Article: Time to reform copyright>]
164
# But when I save, the data changes as you might except.
166
>>> Article.objects.all()
167
[<Article: Poker has no place on television>, <Article: Time to reform copyright>]
169
# Django also ships with a built-in JSON serializers
170
>>> json = serializers.serialize("json", Category.objects.filter(pk=2))
172
'[{"pk": 2, "model": "serializers.category", "fields": {"name": "Music"}}]'
174
# You can easily create new objects by deserializing data with an empty PK
175
# (It's easier to demo this with JSON...)
176
>>> new_author_json = '[{"pk": null, "model": "serializers.author", "fields": {"name": "Bill"}}]'
177
>>> for obj in serializers.deserialize("json", new_author_json):
179
>>> Author.objects.all()
180
[<Author: Bill>, <Author: Jane>, <Author: Joe>]
182
# All the serializers work the same
183
>>> json = serializers.serialize("json", Article.objects.all())
184
>>> for obj in serializers.deserialize("json", json):
186
<DeserializedObject: Poker has no place on television>
187
<DeserializedObject: Time to reform copyright>
189
>>> json = json.replace("Poker has no place on television", "Just kidding; I love TV poker")
190
>>> for obj in serializers.deserialize("json", json):
193
>>> Article.objects.all()
194
[<Article: Just kidding; I love TV poker>, <Article: Time to reform copyright>]
196
# If you use your own primary key field (such as a OneToOneField),
197
# it doesn't appear in the serialized field list - it replaces the
199
>>> profile = AuthorProfile(author=joe, date_of_birth=datetime(1970,1,1))
202
>>> json = serializers.serialize("json", AuthorProfile.objects.all())
204
'[{"pk": 1, "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
206
>>> for obj in serializers.deserialize("json", json):
208
<DeserializedObject: Profile of Joe>
210
# Objects ids can be referenced before they are defined in the serialization data
211
# However, the deserialization process will need to be contained within a transaction
212
>>> 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"}}]'
213
>>> from django.db import transaction
214
>>> transaction.enter_transaction_management()
215
>>> transaction.managed(True)
216
>>> for obj in serializers.deserialize("json", json):
219
>>> transaction.commit()
220
>>> transaction.leave_transaction_management()
222
>>> article = Article.objects.get(pk=3)
224
<Article: Forward references pose no problem>
225
>>> article.categories.all()
226
[<Category: Reference>, <Category: Sports>]
230
# Serializer output can be restricted to a subset of fields
231
>>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date'))
232
[{"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"}}]
234
# Every string is serialized as a unicode object, also primary key
236
>>> ac = Actor(name="Zażółć")
237
>>> mv = Movie(title="Gęślą jaźń", actor=ac)
238
>>> ac.save(); mv.save()
240
# Let's serialize our movie
241
>>> print serializers.serialize("json", [mv])
242
[{"pk": 1, "model": "serializers.movie", "fields": {"price": "0.00", "actor": "Za\u017c\u00f3\u0142\u0107", "title": "G\u0119\u015bl\u0105 ja\u017a\u0144"}}]
244
# Deserialization of movie
245
>>> list(serializers.deserialize('json', serializers.serialize('json', [mv])))[0].object.title
246
u'G\u0119\u015bl\u0105 ja\u017a\u0144'
248
# None is null after serialization to json
249
# Primary key is None in case of not saved model
250
>>> mv2 = Movie(title="Movie 2", actor=ac)
251
>>> print serializers.serialize("json", [mv2])
252
[{"pk": null, "model": "serializers.movie", "fields": {"price": "0.00", "actor": "Za\u017c\u00f3\u0142\u0107", "title": "Movie 2"}}]
254
# Deserialization of null returns None for pk
255
>>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id
258
# Serialization and deserialization of floats:
259
>>> sc = Score(score=3.4)
260
>>> print serializers.serialize("json", [sc])
261
[{"pk": null, "model": "serializers.score", "fields": {"score": 3.4}}]
262
>>> print list(serializers.deserialize('json', serializers.serialize('json', [sc])))[0].object.score
265
# Custom field with non trivial to string convertion value
266
>>> player = Player()
267
>>> player.name = "Soslan Djanaev"
269
>>> player.team = Team("Spartak Moskva")
272
>>> serialized = serializers.serialize("json", Player.objects.all())
274
[{"pk": 1, "model": "serializers.player", "fields": {"name": "Soslan Djanaev", "rank": 1, "team": "Spartak Moskva"}}]
276
>>> obj = list(serializers.deserialize("json", serialized))[0]
278
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>
284
__test__['YAML'] = """
287
>>> articles = Article.objects.all().order_by("id")[:2]
288
>>> from django.core import serializers
292
>>> serialized = serializers.serialize("yaml", articles)
297
headline: Just kidding; I love TV poker
298
pub_date: 2006-06-16 11:00:00
299
model: serializers.article
304
headline: Time to reform copyright
305
pub_date: 2006-06-16 13:00:11
306
model: serializers.article
310
>>> obs = list(serializers.deserialize("yaml", serialized))
313
<DeserializedObject: Just kidding; I love TV poker>
314
<DeserializedObject: Time to reform copyright>
316
# Custom field with non trivial to string convertion value with YAML serializer
318
>>> print serializers.serialize("yaml", Player.objects.all())
319
- fields: {name: Soslan Djanaev, rank: 1, team: Spartak Moskva}
320
model: serializers.player
324
>>> serialized = serializers.serialize("yaml", Player.objects.all())
325
>>> obj = list(serializers.deserialize("yaml", serialized))[0]
327
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>