mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 00:19:53 +03:00
refactored the use of update_fields as a meta attribute
This commit is contained in:
parent
5f7348102f
commit
572ed7c3d4
|
@ -256,11 +256,23 @@ When passing data to a serializer instance, the unmodified data will be made ava
|
|||
## Partial updates
|
||||
|
||||
By default, serializers must be passed values for all required fields or they will raise validation errors. You can use the `partial` argument in order to allow partial updates. Note that `STRICT_PARTIAL_UPDATE` must be set to `True` to enable field specific updates using `.save(update_fields=[...])` for `ModelSerializer`
|
||||
with `partial=True`. `PARTIAL_UPDATE_EXTRA_FIELDS` lets you specify the fields you will like to update everytime like `mod_date` or `modified_at`.
|
||||
with `partial=True`.
|
||||
|
||||
# Update `comment` with partial data
|
||||
serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)
|
||||
|
||||
The current implementation of `ModelSerializer` performs `instance.save()` which [saves all fields](https://docs.djangoproject.com/en/4.0/ref/models/instances/#specifying-which-fields-to-save) in a model which may lead to a race condition given a high frequency of partial
|
||||
update requests on a single resource. Specifying `partial_update_extra_fields = []` in a `ModelSerializer`'s `Meta` will save only the fields specified in a partial update by enforcing the use of
|
||||
[update_fields](https://docs.djangoproject.com/en/4.0/ref/models/instances/#specifying-which-fields-to-save) when saving an instance during a `ModelSerializer` update with `partial=True`.
|
||||
|
||||
# define the ModelSerializer with partial_update_extra_fields
|
||||
class EventSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
fields = "__all__"
|
||||
model = Event
|
||||
partial_update_extra_fields = []
|
||||
|
||||
For cases where there are fields like `modified_at` that need to be updated during a partial update even when not provided during a partial update, those field names should be specified in `partial_update_extra_fields` like so: `partial_update_extra_fields = ['modified_at']` or `partial_update_extra_fields = ['mod_date']`
|
||||
## Dealing with nested objects
|
||||
|
||||
The previous examples are fine for dealing with objects that only have simple datatypes, but sometimes we also need to be able to represent more complex objects, where some of the attributes of an object might not be simple datatypes such as strings, dates or integers.
|
||||
|
|
|
@ -143,25 +143,6 @@ Default: `ordering`
|
|||
|
||||
---
|
||||
|
||||
## Model serializer settings
|
||||
|
||||
*The following settings control the behavior of the model serializer.*
|
||||
|
||||
#### STRICT_PARTIAL_UPDATE
|
||||
|
||||
Enforce the use of [update_fields](https://docs.djangoproject.com/en/4.0/ref/models/instances/#specifying-which-fields-to-save)
|
||||
when saving an instance during a model serializer update with `partial=True`.
|
||||
|
||||
Default: `False`
|
||||
|
||||
#### PARTIAL_UPDATE_EXTRA_FIELDS
|
||||
|
||||
Lets you specify the fields you will like to update everytime like `mod_date` or `modified_at`.
|
||||
|
||||
Default: `[]`
|
||||
|
||||
---
|
||||
|
||||
## Versioning settings
|
||||
|
||||
#### DEFAULT_VERSION
|
||||
|
|
|
@ -997,7 +997,8 @@ class ModelSerializer(Serializer):
|
|||
# relationships as being a special case. During updates we already
|
||||
# have an instance pk for the relationships to be associated with.
|
||||
m2m_fields = []
|
||||
update_fields = [*api_settings.PARTIAL_UPDATE_EXTRA_FIELDS]
|
||||
partial_update_extra_fields = self.get_partial_update_extra_fields()
|
||||
update_fields = [*(partial_update_extra_fields or [])]
|
||||
for attr, value in validated_data.items():
|
||||
if attr in info.relations and info.relations[attr].to_many:
|
||||
m2m_fields.append((attr, value))
|
||||
|
@ -1005,7 +1006,7 @@ class ModelSerializer(Serializer):
|
|||
setattr(instance, attr, value)
|
||||
update_fields.append(attr)
|
||||
|
||||
if self.partial and api_settings.STRICT_PARTIAL_UPDATE:
|
||||
if self.partial and partial_update_extra_fields is not None:
|
||||
instance.save(update_fields=update_fields)
|
||||
else:
|
||||
instance.save()
|
||||
|
@ -1632,6 +1633,29 @@ class ModelSerializer(Serializer):
|
|||
|
||||
return validators
|
||||
|
||||
def get_partial_update_extra_fields(self):
|
||||
partial_update_extra_fields = getattr(self.Meta, 'partial_update_extra_fields', None)
|
||||
|
||||
if partial_update_extra_fields is not None and not isinstance(partial_update_extra_fields, (list, tuple)):
|
||||
raise TypeError(
|
||||
'The `partial_update_extra_fields` option must be a NoneType or list or tuple. Got %s.' %
|
||||
type(partial_update_extra_fields).__name__
|
||||
)
|
||||
|
||||
fields = self.get_fields()
|
||||
if partial_update_extra_fields is not None:
|
||||
for field_name in partial_update_extra_fields:
|
||||
assert field_name in fields, (
|
||||
"The field '{field_name}' was included on serializer "
|
||||
"{serializer_class} in the 'partial_update_extra_fields' option, but does "
|
||||
"not match any model field.".format(
|
||||
field_name=field_name,
|
||||
serializer_class=self.__class__.__name__
|
||||
)
|
||||
)
|
||||
|
||||
return partial_update_extra_fields
|
||||
|
||||
|
||||
class HyperlinkedModelSerializer(ModelSerializer):
|
||||
"""
|
||||
|
|
|
@ -50,10 +50,6 @@ DEFAULTS = {
|
|||
# Generic view behavior
|
||||
'DEFAULT_PAGINATION_CLASS': None,
|
||||
'DEFAULT_FILTER_BACKENDS': [],
|
||||
|
||||
# Model serializer behavior
|
||||
'STRICT_PARTIAL_UPDATE': False,
|
||||
'PARTIAL_UPDATE_EXTRA_FIELDS': [],
|
||||
|
||||
# Schema
|
||||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema',
|
||||
|
|
Loading…
Reference in New Issue
Block a user