mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-06-25 07:53:17 +03:00
Merge pull request #3345 from jpadilla/fields
Update ModelSerializer 'fields'/'exclude'/'__all__' behavior
This commit is contained in:
commit
f87573ffa3
|
@ -432,6 +432,7 @@ Declaring a `ModelSerializer` looks like this:
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
|
fields = ('id', 'account_name', 'users', 'created')
|
||||||
|
|
||||||
By default, all the model fields on the class will be mapped to a corresponding serializer fields.
|
By default, all the model fields on the class will be mapped to a corresponding serializer fields.
|
||||||
|
|
||||||
|
@ -453,7 +454,7 @@ To do so, open the Django shell, using `python manage.py shell`, then import the
|
||||||
|
|
||||||
## Specifying which fields to include
|
## Specifying which fields to include
|
||||||
|
|
||||||
If you only want a subset of the default fields to be used in a model serializer, you can do so using `fields` or `exclude` options, just as you would with a `ModelForm`.
|
If you only want a subset of the default fields to be used in a model serializer, you can do so using `fields` or `exclude` options, just as you would with a `ModelForm`. It is strongly recommended that you explicitly set all fields that should be serialized using the `fields` attribute. This will make it less likely to result in unintentionally exposing data when your models change.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -462,7 +463,27 @@ For example:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'users', 'created')
|
fields = ('id', 'account_name', 'users', 'created')
|
||||||
|
|
||||||
The names in the `fields` option will normally map to model fields on the model class.
|
You can also set the `fields` attribute to the special value `'__all__'` to indicate that all fields in the model should be used.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
You can set the `exclude` attribute of the to a list of fields to be excluded from the serializer.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
exclude = ('users',)
|
||||||
|
|
||||||
|
In the example above, if the `Account` model had 3 fields `account_name`, `users`, and `created`, this will result in the fields `account_name` and `created` to be serialized.
|
||||||
|
|
||||||
|
The names in the `fields` and `exclude` attributes will normally map to model fields on the model class.
|
||||||
|
|
||||||
Alternatively names in the `fields` options can map to properties or methods which take no arguments that exist on the model class.
|
Alternatively names in the `fields` options can map to properties or methods which take no arguments that exist on the model class.
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ response content is handled by parsers and renderers.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.fields import Field as DjangoModelField
|
from django.db.models.fields import Field as DjangoModelField
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
from django.db.models.fields import FieldDoesNotExist
|
||||||
|
@ -51,6 +53,8 @@ LIST_SERIALIZER_KWARGS = (
|
||||||
'instance', 'data', 'partial', 'context', 'allow_null'
|
'instance', 'data', 'partial', 'context', 'allow_null'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ALL_FIELDS = '__all__'
|
||||||
|
|
||||||
|
|
||||||
# BaseSerializer
|
# BaseSerializer
|
||||||
# --------------
|
# --------------
|
||||||
|
@ -943,13 +947,13 @@ class ModelSerializer(Serializer):
|
||||||
fields = getattr(self.Meta, 'fields', None)
|
fields = getattr(self.Meta, 'fields', None)
|
||||||
exclude = getattr(self.Meta, 'exclude', None)
|
exclude = getattr(self.Meta, 'exclude', None)
|
||||||
|
|
||||||
if fields and not isinstance(fields, (list, tuple)):
|
if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
'The `fields` option must be a list or tuple. Got %s.' %
|
'The `fields` option must be a list or tuple. Got %s.' %
|
||||||
type(fields).__name__
|
type(fields).__name__
|
||||||
)
|
)
|
||||||
|
|
||||||
if exclude and not isinstance(exclude, (list, tuple)):
|
if exclude and exclude != ALL_FIELDS and not isinstance(exclude, (list, tuple)):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
'The `exclude` option must be a list or tuple. Got %s.' %
|
'The `exclude` option must be a list or tuple. Got %s.' %
|
||||||
type(exclude).__name__
|
type(exclude).__name__
|
||||||
|
@ -962,6 +966,19 @@ class ModelSerializer(Serializer):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if fields is None and exclude is None:
|
||||||
|
warnings.warn(
|
||||||
|
"Creating a ModelSerializer without either the 'fields' attribute "
|
||||||
|
"or the 'exclude' attribute will be prohibited. "
|
||||||
|
"The {serializer_class} serializer needs updating.".format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
),
|
||||||
|
PendingDeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
if fields == ALL_FIELDS:
|
||||||
|
fields = None
|
||||||
|
|
||||||
if fields is not None:
|
if fields is not None:
|
||||||
# Ensure that all declared fields have also been included in the
|
# Ensure that all declared fields have also been included in the
|
||||||
# `Meta.fields` option.
|
# `Meta.fields` option.
|
||||||
|
|
|
@ -321,6 +321,21 @@ class TestRegularFieldMappings(TestCase):
|
||||||
|
|
||||||
ExampleSerializer()
|
ExampleSerializer()
|
||||||
|
|
||||||
|
def test_fields_and_exclude_behavior(self):
|
||||||
|
class ImplicitFieldsSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
|
||||||
|
class ExplicitFieldsSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
implicit = ImplicitFieldsSerializer()
|
||||||
|
explicit = ExplicitFieldsSerializer()
|
||||||
|
|
||||||
|
assert implicit.data == explicit.data
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(django.VERSION < (1, 8),
|
@pytest.mark.skipif(django.VERSION < (1, 8),
|
||||||
reason='DurationField is only available for django1.8+')
|
reason='DurationField is only available for django1.8+')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user