mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-31 15:24:31 +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 Meta:
|
||||
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.
|
||||
|
||||
|
@ -453,7 +454,7 @@ To do so, open the Django shell, using `python manage.py shell`, then import the
|
|||
|
||||
## 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:
|
||||
|
||||
|
@ -462,7 +463,27 @@ For example:
|
|||
model = Account
|
||||
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.
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ response content is handled by parsers and renderers.
|
|||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import warnings
|
||||
|
||||
from django.db import models
|
||||
from django.db.models.fields import Field as DjangoModelField
|
||||
from django.db.models.fields import FieldDoesNotExist
|
||||
|
@ -51,6 +53,8 @@ LIST_SERIALIZER_KWARGS = (
|
|||
'instance', 'data', 'partial', 'context', 'allow_null'
|
||||
)
|
||||
|
||||
ALL_FIELDS = '__all__'
|
||||
|
||||
|
||||
# BaseSerializer
|
||||
# --------------
|
||||
|
@ -943,13 +947,13 @@ class ModelSerializer(Serializer):
|
|||
fields = getattr(self.Meta, 'fields', 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(
|
||||
'The `fields` option must be a list or tuple. Got %s.' %
|
||||
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(
|
||||
'The `exclude` option must be a list or tuple. Got %s.' %
|
||||
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:
|
||||
# Ensure that all declared fields have also been included in the
|
||||
# `Meta.fields` option.
|
||||
|
|
|
@ -321,6 +321,21 @@ class TestRegularFieldMappings(TestCase):
|
|||
|
||||
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),
|
||||
reason='DurationField is only available for django1.8+')
|
||||
|
|
Loading…
Reference in New Issue
Block a user