~ubuntu-branches/ubuntu/maverick/python-django/maverick

« back to all changes in this revision

Viewing changes to tests/modeltests/serializers/models.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.1.8 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090729112628-pg09ino8sz0sj21t
Tags: 1.1-1
* New upstream release.
* Merge from experimental:
  - Ship FastCGI initscript and /etc/default file in python-django's examples
    directory (Closes: #538863)
  - Drop "05_10539-sphinx06-compatibility.diff"; it has been applied
    upstream.
  - Bump Standards-Version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
"""
 
3
42. Serialization
 
4
 
 
5
``django.core.serializers`` provides interfaces to converting Django
 
6
``QuerySet`` objects to and from "flat" data (i.e. strings).
 
7
"""
 
8
 
 
9
try:
 
10
    from decimal import Decimal
 
11
except ImportError:
 
12
    from django.utils._decimal import Decimal # Python 2.3 fallback
 
13
 
 
14
from django.db import models
 
15
 
 
16
class Category(models.Model):
 
17
    name = models.CharField(max_length=20)
 
18
 
 
19
    class Meta:
 
20
       ordering = ('name',)
 
21
 
 
22
    def __unicode__(self):
 
23
        return self.name
 
24
 
 
25
class Author(models.Model):
 
26
    name = models.CharField(max_length=20)
 
27
 
 
28
    class Meta:
 
29
        ordering = ('name',)
 
30
 
 
31
    def __unicode__(self):
 
32
        return self.name
 
33
 
 
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)
 
39
 
 
40
    class Meta:
 
41
       ordering = ('pub_date',)
 
42
 
 
43
    def __unicode__(self):
 
44
        return self.headline
 
45
 
 
46
class AuthorProfile(models.Model):
 
47
    author = models.OneToOneField(Author, primary_key=True)
 
48
    date_of_birth = models.DateField()
 
49
 
 
50
    def __unicode__(self):
 
51
        return u"Profile of %s" % self.author
 
52
 
 
53
class Actor(models.Model):
 
54
    name = models.CharField(max_length=20, primary_key=True)
 
55
 
 
56
    class Meta:
 
57
        ordering = ('name',)
 
58
 
 
59
    def __unicode__(self):
 
60
        return self.name
 
61
 
 
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'))
 
66
 
 
67
    class Meta:
 
68
       ordering = ('title',)
 
69
 
 
70
    def __unicode__(self):
 
71
        return self.title
 
72
 
 
73
class Score(models.Model):
 
74
    score = models.FloatField()
 
75
 
 
76
 
 
77
class Team(object):
 
78
    def __init__(self, title):
 
79
        self.title = title
 
80
 
 
81
    def __unicode__(self):
 
82
        raise NotImplementedError("Not so simple")
 
83
 
 
84
    def __str__(self):
 
85
        raise NotImplementedError("Not so simple")
 
86
 
 
87
    def to_string(self):
 
88
        return "%s" % self.title
 
89
 
 
90
class TeamField(models.CharField):
 
91
    __metaclass__ = models.SubfieldBase
 
92
 
 
93
    def __init__(self):
 
94
        super(TeamField, self).__init__(max_length=100)
 
95
 
 
96
    def get_db_prep_save(self, value):
 
97
        return unicode(value.title)
 
98
 
 
99
    def to_python(self, value):
 
100
        if isinstance(value, Team):
 
101
            return value
 
102
        return Team(value)
 
103
 
 
104
    def value_to_string(self, obj):
 
105
        return self._get_val_from_obj(obj).to_string()
 
106
 
 
107
class Player(models.Model):
 
108
    name = models.CharField(max_length=50)
 
109
    rank = models.IntegerField()
 
110
    team = TeamField()
 
111
 
 
112
    def __unicode__(self):
 
113
        return u'%s (%d) playing for %s' % (self.name, self.rank, self.team.to_string())
 
114
 
 
115
__test__ = {'API_TESTS':"""
 
116
# Create some data:
 
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()
 
122
 
 
123
>>> joe = Author(name="Joe")
 
124
>>> jane = Author(name="Jane")
 
125
>>> joe.save(); jane.save()
 
126
 
 
127
>>> a1 = Article(
 
128
...     author = jane,
 
129
...     headline = "Poker has no place on ESPN",
 
130
...     pub_date = datetime(2006, 6, 16, 11, 00))
 
131
>>> a2 = Article(
 
132
...     author = joe,
 
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]
 
138
 
 
139
# Serialize a queryset to XML
 
140
>>> from django.core import serializers
 
141
>>> xml = serializers.serialize("xml", Article.objects.all())
 
142
 
 
143
# The output is valid XML
 
144
>>> from xml.dom import minidom
 
145
>>> dom = minidom.parseString(xml)
 
146
 
 
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):
 
151
...     print obj
 
152
<DeserializedObject: Poker has no place on ESPN>
 
153
<DeserializedObject: Time to reform copyright>
 
154
 
 
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))
 
159
 
 
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>]
 
163
 
 
164
# But when I save, the data changes as you might except.
 
165
>>> objs[0].save()
 
166
>>> Article.objects.all()
 
167
[<Article: Poker has no place on television>, <Article: Time to reform copyright>]
 
168
 
 
169
# Django also ships with a built-in JSON serializers
 
170
>>> json = serializers.serialize("json", Category.objects.filter(pk=2))
 
171
>>> json
 
172
'[{"pk": 2, "model": "serializers.category", "fields": {"name": "Music"}}]'
 
173
 
 
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):
 
178
...     obj.save()
 
179
>>> Author.objects.all()
 
180
[<Author: Bill>, <Author: Jane>, <Author: Joe>]
 
181
 
 
182
# All the serializers work the same
 
183
>>> json = serializers.serialize("json", Article.objects.all())
 
184
>>> for obj in serializers.deserialize("json", json):
 
185
...     print obj
 
186
<DeserializedObject: Poker has no place on television>
 
187
<DeserializedObject: Time to reform copyright>
 
188
 
 
189
>>> json = json.replace("Poker has no place on television", "Just kidding; I love TV poker")
 
190
>>> for obj in serializers.deserialize("json", json):
 
191
...     obj.save()
 
192
 
 
193
>>> Article.objects.all()
 
194
[<Article: Just kidding; I love TV poker>, <Article: Time to reform copyright>]
 
195
 
 
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
 
198
# pk identifier.
 
199
>>> profile = AuthorProfile(author=joe, date_of_birth=datetime(1970,1,1))
 
200
>>> profile.save()
 
201
 
 
202
>>> json = serializers.serialize("json", AuthorProfile.objects.all())
 
203
>>> json
 
204
'[{"pk": 1, "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
 
205
 
 
206
>>> for obj in serializers.deserialize("json", json):
 
207
...     print obj
 
208
<DeserializedObject: Profile of Joe>
 
209
 
 
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):
 
217
...     obj.save()
 
218
 
 
219
>>> transaction.commit()
 
220
>>> transaction.leave_transaction_management()
 
221
 
 
222
>>> article = Article.objects.get(pk=3)
 
223
>>> article
 
224
<Article: Forward references pose no problem>
 
225
>>> article.categories.all()
 
226
[<Category: Reference>, <Category: Sports>]
 
227
>>> article.author
 
228
<Author: Agnes>
 
229
 
 
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"}}]
 
233
 
 
234
# Every string is serialized as a unicode object, also primary key
 
235
# which is 'varchar'
 
236
>>> ac = Actor(name="Zażółć")
 
237
>>> mv = Movie(title="Gęślą jaźń", actor=ac)
 
238
>>> ac.save(); mv.save()
 
239
 
 
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"}}]
 
243
 
 
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'
 
247
 
 
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"}}]
 
253
 
 
254
# Deserialization of null returns None for pk
 
255
>>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id
 
256
None
 
257
 
 
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
 
263
3.4
 
264
 
 
265
# Custom field with non trivial to string convertion value
 
266
>>> player = Player()
 
267
>>> player.name = "Soslan Djanaev"
 
268
>>> player.rank = 1
 
269
>>> player.team = Team("Spartak Moskva")
 
270
>>> player.save()
 
271
 
 
272
>>> serialized = serializers.serialize("json", Player.objects.all())
 
273
>>> print serialized
 
274
[{"pk": 1, "model": "serializers.player", "fields": {"name": "Soslan Djanaev", "rank": 1, "team": "Spartak Moskva"}}]
 
275
 
 
276
>>> obj = list(serializers.deserialize("json", serialized))[0]
 
277
>>> print obj
 
278
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>
 
279
 
 
280
"""}
 
281
 
 
282
try:
 
283
    import yaml
 
284
    __test__['YAML'] = """
 
285
# Create some data:
 
286
 
 
287
>>> articles = Article.objects.all().order_by("id")[:2]
 
288
>>> from django.core import serializers
 
289
 
 
290
# test if serial
 
291
 
 
292
>>> serialized = serializers.serialize("yaml", articles)
 
293
>>> print serialized
 
294
- fields:
 
295
    author: 2
 
296
    categories: [3, 1]
 
297
    headline: Just kidding; I love TV poker
 
298
    pub_date: 2006-06-16 11:00:00
 
299
  model: serializers.article
 
300
  pk: 1
 
301
- fields:
 
302
    author: 1
 
303
    categories: [2, 3]
 
304
    headline: Time to reform copyright
 
305
    pub_date: 2006-06-16 13:00:11
 
306
  model: serializers.article
 
307
  pk: 2
 
308
<BLANKLINE>
 
309
 
 
310
>>> obs = list(serializers.deserialize("yaml", serialized))
 
311
>>> for i in obs:
 
312
...     print i
 
313
<DeserializedObject: Just kidding; I love TV poker>
 
314
<DeserializedObject: Time to reform copyright>
 
315
 
 
316
# Custom field with non trivial to string convertion value with YAML serializer
 
317
 
 
318
>>> print serializers.serialize("yaml", Player.objects.all())
 
319
- fields: {name: Soslan Djanaev, rank: 1, team: Spartak Moskva}
 
320
  model: serializers.player
 
321
  pk: 1
 
322
<BLANKLINE>
 
323
 
 
324
>>> serialized = serializers.serialize("yaml", Player.objects.all())
 
325
>>> obj = list(serializers.deserialize("yaml", serialized))[0]
 
326
>>> print obj
 
327
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>
 
328
 
 
329
 
 
330
"""
 
331
except ImportError:
 
332
    pass
 
333