Ticket #4656: python.py

File python.py, 4.8 KB (added by Matthew Flanagan <mattimustang@…>, 16 years ago)
Line 
1"""
2Full Python serializer for Django.
3"""
4import base
5from django.utils.encoding import smart_unicode
6from django.core.serializers.python import Deserializer as PythonDeserializer
7
8class Serializer(base.Serializer):
9 """
10 Python serializer for Django modelled after Ruby on Rails.
11 Default behaviour is to serialize only model fields with the exception
12 of ForeignKey and ManyToMany fields which must be explicitly added in the
13 ``relations`` argument.
14 """
15
16 def __init__(self, *args, **kwargs):
17 """
18 Initialize instance attributes.
19 """
20 self._fields = None
21 self._extras = None
22 self.objects = []
23 super(Serializer, self).__init__(*args, **kwargs)
24
25 def start_serialization(self):
26 """
27 Called when serializing of the queryset starts.
28 """
29 self._fields = None
30 self._extras = None
31 self.objects = []
32
33 def end_serialization(self):
34 """
35 Called when serializing of the queryset ends.
36 """
37 pass
38
39 def start_object(self, obj):
40 """
41 Called when serializing of an object starts.
42 """
43 self._fields = {}
44 self._extras = {}
45
46 def end_object(self, obj):
47 """
48 Called when serializing of an object ends.
49 """
50 self.objects.append({
51 "model" : smart_unicode(obj._meta),
52 "pk" : smart_unicode(obj._get_pk_val(), strings_only=True),
53 "fields" : self._fields
54 })
55 if self._extras:
56 self.objects[-1]["extras"] = self._extras
57 self._fields = None
58 self._extras = None
59
60 def handle_field(self, obj, field):
61 """
62 Called to handle each individual (non-relational) field on an object.
63 """
64 self._fields[field.name] = smart_unicode(getattr(obj, field.name),
65 strings_only=True)
66
67 def handle_fk_field(self, obj, field):
68 """
69 Called to handle a ForeignKey field.
70 Recursively serializes relations specified in the 'relations' option.
71 """
72 fname = field.name
73 related = getattr(obj, fname)
74 if related is not None:
75 if fname in self.relations:
76 # perform full serialization of FK
77 serializer = Serializer()
78 options = {}
79 if isinstance(self.relations, dict):
80 if isinstance(self.relations[fname], dict):
81 options = self.relations[fname]
82 self._fields[fname] = serializer.serialize([related],
83 **options)[0]
84 else:
85 # emulate the original behaviour and serialize the pk value
86 if field.rel.field_name == related._meta.pk.name:
87 # Related to remote object via primary key
88 related = related._get_pk_val()
89 else:
90 # Related to remote object via other field
91 related = getattr(related, field.rel.field_name)
92 self._fields[fname] = smart_unicode(related, strings_only=True)
93 else:
94 self._fields[fname] = smart_unicode(related, strings_only=True)
95
96 def handle_m2m_field(self, obj, field):
97 """
98 Called to handle a ManyToManyField.
99 Recursively serializes relations specified in the 'relations' option.
100 """
101 fname = field.name
102 if fname in self.relations:
103 # perform full serialization of M2M
104 serializer = Serializer()
105 options = {}
106 if isinstance(self.relations, dict):
107 if isinstance(self.relations[fname], dict):
108 options = self.relations[fname]
109 self._fields[fname] = [
110 serializer.serialize([related], **options)[0]
111 for related in getattr(obj, fname).iterator()]
112 else:
113 # emulate the original behaviour and serialize to a list of
114 # primary key values
115 self._fields[fname] = [
116 smart_unicode(related._get_pk_val(), strings_only=True)
117 for related in getattr(obj, fname).iterator()]
118
119
120 def getvalue(self):
121 """
122 Return the fully serialized queryset (or None if the output stream is
123 not seekable).
124 """
125 return self.objects
126
127 def handle_extra_field(self, obj, field):
128 """
129 Return "extra" fields that the user specifies.
130 Can be a property or callable that takes no arguments.
131 """
132 if hasattr(obj, field):
133 extra = getattr(obj, field)
134 if callable(extra):
135 self._extras[field] = smart_unicode(extra(), strings_only=True)
136 else:
137 self._extras[field] = smart_unicode(extra, strings_only=True)
138
139
140Deserializer = PythonDeserializer
Back to Top