You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -271,97 +271,127 @@ Similarly if a nested representation should be a list of items, you should pass
271
271
content = serializers.CharField(max_length=200)
272
272
created = serializers.DateTimeField()
273
273
274
-
Validation of nested objects will work the same as before. Errors with nested objects will be nested under the field name of the nested object.
274
+
## Writable nested representations
275
+
276
+
When dealing with nested representations that support deserializing the data, an errors with nested objects will be nested under the field name of the nested object.
# {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']}
281
283
282
-
**TODO** Document create and update for nested serializers
284
+
Similarly, the `.validated_data` property will include nested data structures.
283
285
284
-
##Dealing with multiple objects
286
+
#### Writing `.create()` methods for nested representations
285
287
286
-
The `Serializer` class can also handle serializing or deserializing lists of objects.
288
+
If you're supporting writable nested representations you'll need to write `.create()`or `.update()` methods that handle saving multiple objects.
287
289
288
-
#### Serializing multiple objects
290
+
The following example demonstrates how you might handle creating a user with a nested profile object.
289
291
290
-
To serialize a queryset or list of objects instead of a single object instance, you should pass the `many=True` flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.
292
+
class UserSerializer(serializers.ModelSerializer):
293
+
profile = ProfileSerializer()
291
294
292
-
queryset = Book.objects.all()
293
-
serializer = BookSerializer(queryset, many=True)
294
-
serializer.data
295
-
# [
296
-
# {'id': 0, 'title': 'The electric kool-aid acid test', 'author': 'Tom Wolfe'},
297
-
# {'id': 1, 'title': 'If this is a man', 'author': 'Primo Levi'},
#### Writing `.update()` methods for nested representations
304
306
305
-
To deserialize a list of object data, and create multiple object instances in a single pass, you should also set the `many=True` flag, and pass a list of data to be deserialized.
307
+
For updates you'll want to think carefully about how to handle updates to relationships. For example if the data for the relationship is `None`, or not provided, which of the following should occur?
306
308
307
-
This allows you to write views that create multiple items when a `POST` request is made.
309
+
* Set the relationship to `NULL` in the database.
310
+
* Delete the associated instance.
311
+
* Ignore the data and leave the instance as it is.
312
+
* Raise a validation error.
308
313
309
-
For example:
314
+
Here's an example for an `update()` method on our previous `UserSerializer` class.
310
315
311
-
data = [
312
-
{'title': 'The bell jar', 'author': 'Sylvia Plath'},
313
-
{'title': 'For whom the bell tolls', 'author': 'Ernest Hemingway'}
314
-
]
315
-
serializer = BookSerializer(data=data, many=True)
316
-
serializer.is_valid()
317
-
# True
318
-
serializer.save() # `.save()` will be called on each deserialized instance
316
+
def update(self, instance, validated_data):
317
+
profile_data = validated_data.pop('profile')
318
+
# Unless the application properly enforces that this field is
319
+
# always set, the follow could raise a `DoesNotExist`, which
The default implementation for multiple object creation is to simply call `.create()` for each item in the list. If you want to customize this behavior, you'll need to customize the `.create()` method on `ListSerializer` class that is used when `many=True` is passed.
327
+
profile.is_premium_member = profile_data.get(
328
+
'is_premium_member',
329
+
profile.is_premium_member
330
+
)
331
+
profile.has_support_contract = profile_data.get(
332
+
'has_support_contract',
333
+
profile.has_support_contract
334
+
)
335
+
profile.save()
321
336
322
-
For example:
337
+
return user
323
338
324
-
class BookListSerializer(serializers.ListSerializer):
325
-
def create(self, validated_data):
326
-
books = [Book(**item) for item in validated_data]
327
-
return Book.objects.bulk_create(books)
339
+
Because the behavior of nested creates and updates can be ambiguous, and may require complex dependancies between related models, REST framework 3 requires you to always write these methods explicitly. The default `ModelSerializer``.create()` and `.update()` methods do not include support for writable nested representations.
328
340
329
-
class BookSerializer(serializers.Serializer):
330
-
…
331
-
class Meta:
332
-
list_serializer_class = BookListSerializer
341
+
It is possible that a third party package, providing automatic support some kinds of automatic writable nested representations may be released alongside the 3.1 release.
333
342
334
-
#### Deserializing multiple objects for update
343
+
#### Handling saving related instances in model manager classes
335
344
336
-
**TODO**
345
+
An alternative to saving multiple related instances in the serializer is to write custom model manager classes handle creating the correct instances.
337
346
338
-
You can also deserialize a list of objects as part of a bulk update of multiple existing items.
339
-
In this case you need to supply both an existing list or queryset of items, as well as a list of data to update those items with.
347
+
For example, suppose we wanted to ensure that `User` instances and `Profile` instances are always created together as a pair. We might write a custom manager class that looks something like this:
340
348
341
-
This allows you to write views that update or create multiple items when a `PUT` request is made.
349
+
class UserManager(models.Manager):
350
+
...
342
351
343
-
# Capitalizing the titles of the books
344
-
queryset = Book.objects.all()
345
-
data = [
346
-
{'id': 3, 'title': 'The Bell Jar', 'author': 'Sylvia Plath'},
347
-
{'id': 4, 'title': 'For Whom the Bell Tolls', 'author': 'Ernest Hemingway'}
By default bulk updates will be limited to updating instances that already exist in the provided queryset.
363
+
This manager class now more nicely encapsulates that user instances and profile instances are always created at the same time. Our `.create()` method on the serializer class can now be re-written to use the new manager method.
355
364
356
-
When performing a bulk update you may want to allow new items to be created, and missing items to be deleted. To do so, pass `allow_add_remove=True` to the serializer.
serializer.save() # `.save()` will be called on updated or newly created instances.
362
-
# `.delete()` will be called on any other items in the `queryset`.
373
+
For more details on this approach see the Django documentation on [model managers](model-managers), and [this blogpost on using model and manger classes](encapsulation-blogpost).
363
374
364
-
Passing `allow_add_remove=True` ensures that any update operations will completely overwrite the existing queryset, rather than simply updating existing objects.
375
+
## Dealing with multiple objects
376
+
377
+
The `Serializer` class can also handle serializing or deserializing lists of objects.
378
+
379
+
#### Serializing multiple objects
380
+
381
+
To serialize a queryset or list of objects instead of a single object instance, you should pass the `many=True` flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.
382
+
383
+
queryset = Book.objects.all()
384
+
serializer = BookSerializer(queryset, many=True)
385
+
serializer.data
386
+
# [
387
+
# {'id': 0, 'title': 'The electric kool-aid acid test', 'author': 'Tom Wolfe'},
388
+
# {'id': 1, 'title': 'If this is a man', 'author': 'Primo Levi'},
The default behavior for deserializing multiple objects is to support multiple object creation, but not support multiple object updates. For more information on how to support or customize either of these cases, see the [ListSerializer](#ListSerializer) documentation below.
365
395
366
396
## Including extra context
367
397
@@ -399,7 +429,7 @@ By default, all the model fields on the class will be mapped to a corresponding
399
429
400
430
Any relationships such as foreign keys on the model will be mapped to `PrimaryKeyRelatedField`. Reverse relationships are not included by default unless explicitly included as described below.
401
431
402
-
#### Inspecting the generated `ModelSerializer` class.
432
+
#### Inspecting a `ModelSerializer`
403
433
404
434
Serializer classes generate helpful verbose representation strings, that allow you to fully inspect the state of their fields. This is particularly useful when working with `ModelSerializers` where you want to determine what set of fields and validators are being automatically created for you.
405
435
@@ -607,7 +637,7 @@ For example:
607
637
class Meta:
608
638
list_serializer_class = CustomListSerializer
609
639
610
-
#### Customizing `.create()` for multiple objects.
640
+
#### Customizing multiple create
611
641
612
642
The default implementation for multiple object creation is to simply call `.create()` for each item in the list. If you want to customize this behavior, you'll need to customize the `.create()` method on `ListSerializer` class that is used when `many=True` is passed.
613
643
@@ -623,7 +653,7 @@ For example:
623
653
class Meta:
624
654
list_serializer_class = BookListSerializer
625
655
626
-
#### Customizing `.update()` for multiple objects.
656
+
#### Customizing multiple update
627
657
628
658
By default the `ListSerializer` class does not support multiple updates. This is because the behavior that should be expected for insertions and deletions is ambiguous.
629
659
@@ -663,6 +693,8 @@ Here's an example of how you might choose to implement multiple updates:
663
693
class Meta:
664
694
list_serializer_class = BookListSerializer
665
695
696
+
It is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the `allow_add_remove` behavior that was present in REST framework 2.
697
+
666
698
---
667
699
668
700
# BaseSerializer
@@ -687,7 +719,7 @@ Because this class provides the same interface as the `Serializer` class, you ca
687
719
688
720
The only difference you'll notice when doing so is the `BaseSerializer` classes will not generate HTML forms in the browsable API. This is because the data they return does not include all the field information that would allow each field to be rendered into a suitable HTML input.
689
721
690
-
##### Read-only `BaseSerializer` classes.
722
+
##### Read-only `BaseSerializer` classes
691
723
692
724
To implement a read-only serializer using the `BaseSerializer` class, we just need to override the `.to_representation()` method. Let's take a look at an example using a simple Django model:
693
725
@@ -721,7 +753,7 @@ Or use it to serialize multiple instances:
To create a read-write serializer we first need to implement a `.to_internal_value()` method. This method returns the validated values that will be used to construct the object instance, and may raise a `ValidationError` if the supplied data is in an incorrect format.
727
759
@@ -766,7 +798,7 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd
766
798
def create(self, validated_data):
767
799
return HighScore.objects.create(**validated_data)
768
800
769
-
#### Creating new generic serializers with `BaseSerializer`.
801
+
#### Creating new base classes
770
802
771
803
The `BaseSerializer` class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends.
772
804
@@ -905,6 +937,8 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide
0 commit comments