@@ -238,6 +238,160 @@ When set to pluralize:
238
238
Both ` JSON_API_PLURALIZE_RELATION_TYPE ` and ` JSON_API_FORMAT_RELATION_KEYS ` can be combined to
239
239
achieve different results.
240
240
241
+ ### Related fields
242
+
243
+ Because of the additional structure needed to represent relationships in JSON
244
+ API, this package provides the ` ResourceRelatedField ` for serializers, which
245
+ works similarly to ` PrimaryKeyRelatedField ` . By default,
246
+ ` rest_framework_json_api.serializers.ModelSerializer ` will use this for
247
+ related fields automatically. It can be instantiated explicitly as in the
248
+ following example:
249
+
250
+ ``` python
251
+ from rest_framework_json_api import serializers
252
+ from rest_framework_json_api.relations import ResourceRelatedField
253
+
254
+ from myapp.models import Order, LineItem, Customer
255
+
256
+
257
+ class OrderSerializer (serializers .ModelSerializer ):
258
+ class Meta :
259
+ model = Order
260
+
261
+ line_items = ResourceRelatedField(
262
+ queryset = LineItem.objects,
263
+ many = True # necessary for M2M fields & reverse FK fields
264
+ )
265
+
266
+ customer = ResourceRelatedField(
267
+ queryset = Customer.objects # queryset argument is required
268
+ ) # except when read_only=True
269
+
270
+ ```
271
+
272
+ In the [ JSON API spec] ( http://jsonapi.org/format/#document-resource-objects ) ,
273
+ relationship objects contain links to related objects. To make this work
274
+ on a serializer we need to tell the ` ResourceRelatedField ` about the
275
+ corresponding view. Use the ` HyperlinkedModelSerializer ` and instantiate
276
+ the ` ResourceRelatedField ` with the relevant keyword arguments:
277
+
278
+ ``` python
279
+ from rest_framework_json_api import serializers
280
+ from rest_framework_json_api.relations import ResourceRelatedField
281
+
282
+ from myapp.models import Order, LineItem, Customer
283
+
284
+
285
+ class OrderSerializer (serializers .ModelSerializer ):
286
+ class Meta :
287
+ model = Order
288
+
289
+ line_items = ResourceRelatedField(
290
+ queryset = LineItem.objects,
291
+ many = True ,
292
+ related_link_view_name = ' order-lineitems-list' ,
293
+ related_link_url_kwarg = ' order_pk' ,
294
+ self_link_view_name = ' order_relationships'
295
+ )
296
+
297
+ customer = ResourceRelatedField(
298
+ queryset = Customer.objects,
299
+ related_link_view- name = ' order-customer-detail' ,
300
+ related_link_url_kwarg = ' order_pk' ,
301
+ self_link_view_name = ' order-relationships'
302
+ )
303
+ ```
304
+
305
+ * ` related_link_view_name ` is the name of the route for the related
306
+ view.
307
+
308
+ * ` related_link_url_kwarg ` is the keyword argument that will be passed
309
+ to the view that identifies the 'parent' object, so that the results
310
+ can be filtered to show only those objects related to the 'parent'.
311
+
312
+ * ` self_link_view_name ` is the name of the route for the ` RelationshipView `
313
+ (see below).
314
+
315
+ In this example, ` reverse('order-lineitems-list', kwargs={'order_pk': 3} `
316
+ should resolve to something like ` /orders/3/lineitems ` , and that route
317
+ should instantiate a view or viewset for ` LineItem ` objects that accepts
318
+ a keword argument ` order_pk ` . The
319
+ [ drf-nested-routers] ( https://github.com/alanjds/drf-nested-routers ) package
320
+ is useful for defining such nested routes in your urlconf.
321
+
322
+ The corresponding viewset for the ` line-items-list ` route in the above example
323
+ might look like the following. Note that in the typical use case this would be
324
+ the same viewset used for the ` /lineitems ` endpoints; when accessed through
325
+ the nested route ` /orders/<order_pk>/lineitems ` the queryset is filtered using
326
+ the ` order_pk ` keyword argument to include only the lineitems related to the
327
+ specified order.
328
+
329
+ ``` python
330
+ from rest_framework import viewsets
331
+
332
+ from myapp.models import LineItem
333
+ from myapp.serializers import LineItemSerializer
334
+
335
+
336
+ class LineItemViewSet (viewsets .ModelViewSet ):
337
+ queryset = LineItem.objects
338
+ serializer_class = LineItemSerializer
339
+
340
+ def get_queryset (self ):
341
+ queryset = self .queryset
342
+
343
+ # if this viewset is accessed via the 'order-lineitems-list' route,
344
+ # it wll have been passed the `order_pk` kwarg and the queryset
345
+ # needs to be filtered accordingly; if it was accessed via the
346
+ # unnested '/lineitems' route, the queryset should include all LineItems
347
+ if ' order_pk' in self .kwargs:
348
+ order_pk = self .kwargs[' order_pk' ]
349
+ queryset = queryset.filter(order__pk = order_pk])
350
+
351
+ return queryset
352
+ ```
353
+
354
+ ### RelationshipView
355
+ ` rest_framework_json_api.views.RelationshipView ` is used to build
356
+ relationship views (see the
357
+ [ JSON API spec] ( http://jsonapi.org/format/#fetching-relationships ) ).
358
+ The ` self ` link on a relationship object should point to the corresponding
359
+ relationship view.
360
+
361
+ The relationship view is fairly simple because it only serializes
362
+ [ Resource Identifier Objects] ( http://jsonapi.org/format/#document-resource-identifier-objects )
363
+ rather than full resource objects. In most cases the following is sufficient:
364
+
365
+ ``` python
366
+ from rest_framework_json_api.views import RelationshipView
367
+
368
+ from myapp.models import Order
369
+
370
+
371
+ class OrderRelationshipView (RelationshipView ):
372
+ queryset = Order.objects
373
+
374
+ ```
375
+
376
+ The urlconf would need to contain a route like the following:
377
+
378
+ ``` python
379
+ url(
380
+ regex = r ' ^ orders/( ?P<pk> [^ /. ]+ /relationships/( ?P<related_field> [^ /. ]+ ) $ ' ,
381
+ view = OrderRelationshipView.as_view(),
382
+ name = ' order-relationships'
383
+ )
384
+ ```
385
+
386
+ The ` related_field ` kwarg specifies which relationship to use, so
387
+ if we are interested in the relationship represented by the related
388
+ model field ` Order.line_items ` on the Order with pk 3, the url would be
389
+ ` /order/3/relationships/line_items ` . On ` HyperlinkedModelSerializer ` , the
390
+ ` ResourceRelatedField ` will construct the url based on the provided
391
+ ` self_link_view_name ` keyword argument, which should match the ` name= `
392
+ provided in the urlconf, and will use the name of the field for the
393
+ ` related_field ` kwarg.
394
+
241
395
### Meta
242
396
243
397
You may add metadata to the rendered json in two different ways: ` meta_fields ` and ` get_root_meta ` .
0 commit comments