|
1 """ |
|
2 41. Serialization |
|
3 |
|
4 ``django.core.serializers`` provides interfaces to converting Django querysets |
|
5 to and from "flat" data (i.e. strings). |
|
6 """ |
|
7 |
|
8 from django.db import models |
|
9 |
|
10 class Category(models.Model): |
|
11 name = models.CharField(maxlength=20) |
|
12 |
|
13 class Meta: |
|
14 ordering = ('name',) |
|
15 |
|
16 def __str__(self): |
|
17 return self.name |
|
18 |
|
19 class Author(models.Model): |
|
20 name = models.CharField(maxlength=20) |
|
21 |
|
22 class Meta: |
|
23 ordering = ('name',) |
|
24 |
|
25 def __str__(self): |
|
26 return self.name |
|
27 |
|
28 class Article(models.Model): |
|
29 author = models.ForeignKey(Author) |
|
30 headline = models.CharField(maxlength=50) |
|
31 pub_date = models.DateTimeField() |
|
32 categories = models.ManyToManyField(Category) |
|
33 |
|
34 class Meta: |
|
35 ordering = ('pub_date',) |
|
36 |
|
37 def __str__(self): |
|
38 return self.headline |
|
39 |
|
40 class AuthorProfile(models.Model): |
|
41 author = models.OneToOneField(Author) |
|
42 date_of_birth = models.DateField() |
|
43 |
|
44 def __str__(self): |
|
45 return "Profile of %s" % self.author |
|
46 |
|
47 __test__ = {'API_TESTS':""" |
|
48 # Create some data: |
|
49 >>> from datetime import datetime |
|
50 >>> sports = Category(name="Sports") |
|
51 >>> music = Category(name="Music") |
|
52 >>> op_ed = Category(name="Op-Ed") |
|
53 >>> sports.save(); music.save(); op_ed.save() |
|
54 |
|
55 >>> joe = Author(name="Joe") |
|
56 >>> jane = Author(name="Jane") |
|
57 >>> joe.save(); jane.save() |
|
58 |
|
59 >>> a1 = Article( |
|
60 ... author = jane, |
|
61 ... headline = "Poker has no place on ESPN", |
|
62 ... pub_date = datetime(2006, 6, 16, 11, 00)) |
|
63 >>> a2 = Article( |
|
64 ... author = joe, |
|
65 ... headline = "Time to reform copyright", |
|
66 ... pub_date = datetime(2006, 6, 16, 13, 00)) |
|
67 >>> a1.save(); a2.save() |
|
68 >>> a1.categories = [sports, op_ed] |
|
69 >>> a2.categories = [music, op_ed] |
|
70 |
|
71 # Serialize a queryset to XML |
|
72 >>> from django.core import serializers |
|
73 >>> xml = serializers.serialize("xml", Article.objects.all()) |
|
74 |
|
75 # The output is valid XML |
|
76 >>> from xml.dom import minidom |
|
77 >>> dom = minidom.parseString(xml) |
|
78 |
|
79 # Deserializing has a similar interface, except that special DeserializedObject |
|
80 # instances are returned. This is because data might have changed in the |
|
81 # database since the data was serialized (we'll simulate that below). |
|
82 >>> for obj in serializers.deserialize("xml", xml): |
|
83 ... print obj |
|
84 <DeserializedObject: Poker has no place on ESPN> |
|
85 <DeserializedObject: Time to reform copyright> |
|
86 |
|
87 # Deserializing data with different field values doesn't change anything in the |
|
88 # database until we call save(): |
|
89 >>> xml = xml.replace("Poker has no place on ESPN", "Poker has no place on television") |
|
90 >>> objs = list(serializers.deserialize("xml", xml)) |
|
91 |
|
92 # Even those I deserialized, the database hasn't been touched |
|
93 >>> Article.objects.all() |
|
94 [<Article: Poker has no place on ESPN>, <Article: Time to reform copyright>] |
|
95 |
|
96 # But when I save, the data changes as you might except. |
|
97 >>> objs[0].save() |
|
98 >>> Article.objects.all() |
|
99 [<Article: Poker has no place on television>, <Article: Time to reform copyright>] |
|
100 |
|
101 # Django also ships with a built-in JSON serializers |
|
102 >>> json = serializers.serialize("json", Category.objects.filter(pk=2)) |
|
103 >>> json |
|
104 '[{"pk": "2", "model": "serializers.category", "fields": {"name": "Music"}}]' |
|
105 |
|
106 # You can easily create new objects by deserializing data with an empty PK |
|
107 # (It's easier to demo this with JSON...) |
|
108 >>> new_author_json = '[{"pk": null, "model": "serializers.author", "fields": {"name": "Bill"}}]' |
|
109 >>> for obj in serializers.deserialize("json", new_author_json): |
|
110 ... obj.save() |
|
111 >>> Author.objects.all() |
|
112 [<Author: Bill>, <Author: Jane>, <Author: Joe>] |
|
113 |
|
114 # All the serializers work the same |
|
115 >>> json = serializers.serialize("json", Article.objects.all()) |
|
116 >>> for obj in serializers.deserialize("json", json): |
|
117 ... print obj |
|
118 <DeserializedObject: Poker has no place on television> |
|
119 <DeserializedObject: Time to reform copyright> |
|
120 |
|
121 >>> json = json.replace("Poker has no place on television", "Just kidding; I love TV poker") |
|
122 >>> for obj in serializers.deserialize("json", json): |
|
123 ... obj.save() |
|
124 |
|
125 >>> Article.objects.all() |
|
126 [<Article: Just kidding; I love TV poker>, <Article: Time to reform copyright>] |
|
127 |
|
128 # If you use your own primary key field (such as a OneToOneField), |
|
129 # it doesn't appear in the serialized field list - it replaces the |
|
130 # pk identifier. |
|
131 >>> profile = AuthorProfile(author=joe, date_of_birth=datetime(1970,1,1)) |
|
132 >>> profile.save() |
|
133 |
|
134 >>> json = serializers.serialize("json", AuthorProfile.objects.all()) |
|
135 >>> json |
|
136 '[{"pk": "1", "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]' |
|
137 |
|
138 >>> for obj in serializers.deserialize("json", json): |
|
139 ... print obj |
|
140 <DeserializedObject: Profile of Joe> |
|
141 |
|
142 # Objects ids can be referenced before they are defined in the serialization data |
|
143 # However, the deserialization process will need to be contained within a transaction |
|
144 >>> 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"}}]' |
|
145 >>> from django.db import transaction |
|
146 >>> transaction.enter_transaction_management() |
|
147 >>> transaction.managed(True) |
|
148 >>> for obj in serializers.deserialize("json", json): |
|
149 ... obj.save() |
|
150 |
|
151 >>> transaction.commit() |
|
152 >>> transaction.leave_transaction_management() |
|
153 |
|
154 >>> article = Article.objects.get(pk=3) |
|
155 >>> article |
|
156 <Article: Forward references pose no problem> |
|
157 >>> article.categories.all() |
|
158 [<Category: Reference>, <Category: Sports>] |
|
159 >>> article.author |
|
160 <Author: Agnes> |
|
161 |
|
162 """} |