2323nested fields.
2424"""
2525
26+ from collections import OrderedDict
27+
2628from rest_framework .serializers import CharField
2729from rest_framework .serializers import SerializerMethodField
30+ from rest_framework .serializers import PrimaryKeyRelatedField
2831
2932from patchwork .api .base import BaseHyperlinkedModelSerializer
3033from patchwork .api .base import CheckHyperlinkedIdentityField
3134from patchwork import models
3235
3336
37+ class SerializedRelatedField (PrimaryKeyRelatedField ):
38+ """
39+ A read-write field that expects a primary key for writes and returns a
40+ serialized version of the underlying field on reads.
41+ """
42+
43+ def use_pk_only_optimization (self ):
44+ # We're using embedded serializers so we want the whole object
45+ return False
46+
47+ def get_queryset (self ):
48+ return self ._Serializer .Meta .model .objects .all ()
49+
50+ def get_choices (self , cutoff = None ):
51+ # Override this so we don't call 'to_representation', which no longer
52+ # returns a flat value
53+ queryset = self .get_queryset ()
54+ if queryset is None :
55+ # Ensure that field.choices returns something sensible
56+ # even when accessed with a read-only field.
57+ return {}
58+
59+ if cutoff is not None :
60+ queryset = queryset [:cutoff ]
61+
62+ return OrderedDict ([
63+ (
64+ item .pk ,
65+ self .display_value (item )
66+ )
67+ for item in queryset
68+ ])
69+
70+ def to_representation (self , data ):
71+ return self ._Serializer (context = self .context ).to_representation (data )
72+
73+
3474class MboxMixin (BaseHyperlinkedModelSerializer ):
3575 """Embed a link to the mbox URL.
3676
@@ -55,132 +95,150 @@ def get_web_url(self, instance):
5595 return request .build_absolute_uri (instance .get_absolute_url ())
5696
5797
58- class BundleSerializer (MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
59-
60- class Meta :
61- model = models .Bundle
62- fields = ('id' , 'url' , 'web_url' , 'name' , 'mbox' )
63- read_only_fields = fields
64- versioned_field = {
65- '1.1' : ('web_url' , ),
66- }
67- extra_kwargs = {
68- 'url' : {'view_name' : 'api-bundle-detail' },
69- }
98+ class BundleSerializer (SerializedRelatedField ):
99+
100+ class _Serializer (MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
101+
102+ class Meta :
103+ model = models .Bundle
104+ fields = ('id' , 'url' , 'web_url' , 'name' , 'mbox' )
105+ read_only_fields = fields
106+ versioned_field = {
107+ '1.1' : ('web_url' , ),
108+ }
109+ extra_kwargs = {
110+ 'url' : {'view_name' : 'api-bundle-detail' },
111+ }
112+
113+
114+ class CheckSerializer (SerializedRelatedField ):
115+
116+ class _Serializer (BaseHyperlinkedModelSerializer ):
117+
118+ url = CheckHyperlinkedIdentityField ('api-check-detail' )
119+
120+ def to_representation (self , instance ):
121+ data = super (CheckSerializer ._Serializer , self ).to_representation (
122+ instance )
123+ data ['state' ] = instance .get_state_display ()
124+ return data
125+
126+ class Meta :
127+ model = models .Check
128+ fields = ('id' , 'url' , 'date' , 'state' , 'target_url' , 'context' )
129+ read_only_fields = fields
130+ extra_kwargs = {
131+ 'url' : {'view_name' : 'api-check-detail' },
132+ }
133+
134+
135+ class CoverLetterSerializer (SerializedRelatedField ):
136+
137+ class _Serializer (MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
138+
139+ class Meta :
140+ model = models .CoverLetter
141+ fields = ('id' , 'url' , 'web_url' , 'msgid' , 'date' , 'name' , 'mbox' )
142+ read_only_fields = fields
143+ versioned_field = {
144+ '1.1' : ('web_url' , 'mbox' , ),
145+ }
146+ extra_kwargs = {
147+ 'url' : {'view_name' : 'api-cover-detail' },
148+ }
149+
150+
151+ class PatchSerializer (SerializedRelatedField ):
152+
153+ class _Serializer (MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
154+
155+ class Meta :
156+ model = models .Patch
157+ fields = ('id' , 'url' , 'web_url' , 'msgid' , 'date' , 'name' , 'mbox' )
158+ read_only_fields = fields
159+ versioned_field = {
160+ '1.1' : ('web_url' , ),
161+ }
162+ extra_kwargs = {
163+ 'url' : {'view_name' : 'api-patch-detail' },
164+ }
70165
71166
72- class CheckSerializer ( BaseHyperlinkedModelSerializer ):
167+ class PersonSerializer ( SerializedRelatedField ):
73168
74- url = CheckHyperlinkedIdentityField ( 'api-check-detail' )
169+ class _Serializer ( BaseHyperlinkedModelSerializer ):
75170
76- def to_representation (self , instance ):
77- data = super (CheckSerializer , self ).to_representation (instance )
78- data ['state' ] = instance .get_state_display ()
79- return data
171+ class Meta :
172+ model = models .Person
173+ fields = ('id' , 'url' , 'name' , 'email' )
174+ read_only_fields = fields
175+ extra_kwargs = {
176+ 'url' : {'view_name' : 'api-person-detail' },
177+ }
80178
81- class Meta :
82- model = models .Check
83- fields = ('id' , 'url' , 'date' , 'state' , 'target_url' , 'context' )
84- read_only_fields = fields
85- extra_kwargs = {
86- 'url' : {'view_name' : 'api-check-detail' },
87179
88- }
180+ class ProjectSerializer ( SerializedRelatedField ):
89181
182+ class _Serializer (BaseHyperlinkedModelSerializer ):
90183
91- class CoverLetterSerializer (MboxMixin , WebURLMixin ,
92- BaseHyperlinkedModelSerializer ):
184+ link_name = CharField (max_length = 255 , source = 'linkname' )
185+ list_id = CharField (max_length = 255 , source = 'listid' )
186+ list_email = CharField (max_length = 200 , source = 'listemail' )
93187
94- class Meta :
95- model = models .CoverLetter
96- fields = ('id' , 'url' , 'web_url' , 'msgid' , 'date' , 'name' , 'mbox' )
97- read_only_fields = fields
98- versioned_field = {
99- '1.1' : ('web_url' , 'mbox' , ),
100- }
101- extra_kwargs = {
102- 'url' : {'view_name' : 'api-cover-detail' },
103- }
188+ class Meta :
189+ model = models .Project
190+ fields = ('id' , 'url' , 'name' , 'link_name' , 'list_id' ,
191+ 'list_email' , 'web_url' , 'scm_url' , 'webscm_url' )
192+ read_only_fields = fields
193+ extra_kwargs = {
194+ 'url' : {'view_name' : 'api-project-detail' },
195+ }
104196
105197
106- class PatchSerializer ( MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
198+ class SeriesSerializer ( SerializedRelatedField ):
107199
108- class Meta :
109- model = models .Patch
110- fields = ('id' , 'url' , 'web_url' , 'msgid' , 'date' , 'name' , 'mbox' )
111- read_only_fields = fields
112- versioned_field = {
113- '1.1' : ('web_url' , ),
114- }
115- extra_kwargs = {
116- 'url' : {'view_name' : 'api-patch-detail' },
117- }
200+ class _Serializer (MboxMixin , WebURLMixin , BaseHyperlinkedModelSerializer ):
118201
202+ class Meta :
203+ model = models .Series
204+ fields = ('id' , 'url' , 'date' , 'name' , 'version' , 'mbox' )
205+ read_only_fields = fields
206+ versioned_field = {
207+ '1.1' : ('web_url' , ),
208+ }
209+ extra_kwargs = {
210+ 'url' : {'view_name' : 'api-series-detail' },
211+ }
119212
120- class PersonSerializer (BaseHyperlinkedModelSerializer ):
121213
122- class Meta :
123- model = models .Person
124- fields = ('id' , 'url' , 'name' , 'email' )
125- read_only_fields = fields
126- extra_kwargs = {
127- 'url' : {'view_name' : 'api-person-detail' },
128- }
214+ class UserSerializer (SerializedRelatedField ):
129215
216+ class _Serializer (BaseHyperlinkedModelSerializer ):
130217
131- class ProjectSerializer (BaseHyperlinkedModelSerializer ):
218+ class Meta :
219+ model = models .User
220+ fields = ('id' , 'url' , 'username' , 'first_name' , 'last_name' ,
221+ 'email' )
222+ read_only_fields = fields
223+ extra_kwargs = {
224+ 'url' : {'view_name' : 'api-user-detail' },
225+ }
132226
133- link_name = CharField (max_length = 255 , source = 'linkname' )
134- list_id = CharField (max_length = 255 , source = 'listid' )
135- list_email = CharField (max_length = 200 , source = 'listemail' )
136227
137- class Meta :
138- model = models .Project
139- fields = ('id' , 'url' , 'name' , 'link_name' , 'list_id' , 'list_email' ,
140- 'web_url' , 'scm_url' , 'webscm_url' )
141- read_only_fields = fields
142- extra_kwargs = {
143- 'url' : {'view_name' : 'api-project-detail' },
144- }
228+ class UserProfileSerializer (SerializedRelatedField ):
145229
230+ class _Serializer (BaseHyperlinkedModelSerializer ):
146231
147- class SeriesSerializer (MboxMixin , WebURLMixin ,
148- BaseHyperlinkedModelSerializer ):
232+ username = CharField (source = 'user.username' )
233+ first_name = CharField (source = 'user.first_name' )
234+ last_name = CharField (source = 'user.last_name' )
235+ email = CharField (source = 'user.email' )
149236
150- class Meta :
151- model = models .Series
152- fields = ('id' , 'url' , 'date' , 'name' , 'version' , 'mbox' )
153- read_only_fields = fields
154- versioned_field = {
155- '1.1' : ('web_url' , ),
156- }
157- extra_kwargs = {
158- 'url' : {'view_name' : 'api-series-detail' },
159- }
160-
161-
162- class UserSerializer (BaseHyperlinkedModelSerializer ):
163-
164- class Meta :
165- model = models .User
166- fields = ('id' , 'url' , 'username' , 'first_name' , 'last_name' , 'email' )
167- read_only_fields = fields
168- extra_kwargs = {
169- 'url' : {'view_name' : 'api-user-detail' },
170- }
171-
172-
173- class UserProfileSerializer (BaseHyperlinkedModelSerializer ):
174-
175- username = CharField (source = 'user.username' )
176- first_name = CharField (source = 'user.first_name' )
177- last_name = CharField (source = 'user.last_name' )
178- email = CharField (source = 'user.email' )
179-
180- class Meta :
181- model = models .UserProfile
182- fields = ('id' , 'url' , 'username' , 'first_name' , 'last_name' , 'email' )
183- read_only_fields = fields
184- extra_kwargs = {
185- 'url' : {'view_name' : 'api-user-detail' },
186- }
237+ class Meta :
238+ model = models .UserProfile
239+ fields = ('id' , 'url' , 'username' , 'first_name' , 'last_name' ,
240+ 'email' )
241+ read_only_fields = fields
242+ extra_kwargs = {
243+ 'url' : {'view_name' : 'api-user-detail' },
244+ }
0 commit comments