mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 05:04:31 +03:00
Configuration correctness tests on ModelSerializer
This commit is contained in:
parent
5b7e4af0d6
commit
87734be5f4
|
@ -10,7 +10,7 @@ python primitives.
|
||||||
2. The process of marshalling between python primitives and request and
|
2. The process of marshalling between python primitives and request and
|
||||||
response content is handled by parsers and renderers.
|
response content is handled by parsers and renderers.
|
||||||
"""
|
"""
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
|
@ -358,6 +358,7 @@ class ModelSerializer(Serializer):
|
||||||
model = getattr(self.Meta, 'model')
|
model = getattr(self.Meta, 'model')
|
||||||
fields = getattr(self.Meta, 'fields', None)
|
fields = getattr(self.Meta, 'fields', None)
|
||||||
depth = getattr(self.Meta, 'depth', 0)
|
depth = getattr(self.Meta, 'depth', 0)
|
||||||
|
extra_kwargs = getattr(self.Meta, 'extra_kwargs', {})
|
||||||
|
|
||||||
# Retrieve metadata about fields & relationships on the model class.
|
# Retrieve metadata about fields & relationships on the model class.
|
||||||
info = model_meta.get_field_info(model)
|
info = model_meta.get_field_info(model)
|
||||||
|
@ -405,9 +406,32 @@ class ModelSerializer(Serializer):
|
||||||
if not issubclass(field_cls, HyperlinkedRelatedField):
|
if not issubclass(field_cls, HyperlinkedRelatedField):
|
||||||
kwargs.pop('view_name', None)
|
kwargs.pop('view_name', None)
|
||||||
|
|
||||||
else:
|
elif hasattr(model, field_name):
|
||||||
assert False, 'Field name `%s` is not valid.' % field_name
|
# Create a read only field for model methods and properties.
|
||||||
|
field_cls = ReadOnlyField
|
||||||
|
kwargs = {}
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
'Field name `%s` is not valid for model `%s`.' %
|
||||||
|
(field_name, model.__class__.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that any fields declared on the class are
|
||||||
|
# also explicity included in `Meta.fields`.
|
||||||
|
missing_fields = set(declared_fields.keys()) - set(fields)
|
||||||
|
if missing_fields:
|
||||||
|
missing_field = list(missing_fields)[0]
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
'Field `%s` has been declared on serializer `%s`, but '
|
||||||
|
'is missing from `Meta.fields`.' %
|
||||||
|
(missing_field, self.__class__.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Populate any kwargs defined in `Meta.extra_kwargs`
|
||||||
|
kwargs.update(extra_kwargs.get(field_name, {}))
|
||||||
|
|
||||||
|
# Create the serializer field.
|
||||||
ret[field_name] = field_cls(**kwargs)
|
ret[field_name] = field_cls(**kwargs)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -5,6 +5,7 @@ shortcuts for automatically creating serializers based on a given model class.
|
||||||
These tests deal with ensuring that we correctly map the model fields onto
|
These tests deal with ensuring that we correctly map the model fields onto
|
||||||
an appropriate set of serializer fields for each case.
|
an appropriate set of serializer fields for each case.
|
||||||
"""
|
"""
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
@ -37,6 +38,9 @@ class RegularFieldsModel(models.Model):
|
||||||
time_field = models.TimeField()
|
time_field = models.TimeField()
|
||||||
url_field = models.URLField(max_length=100)
|
url_field = models.URLField(max_length=100)
|
||||||
|
|
||||||
|
def method(self):
|
||||||
|
return 'method'
|
||||||
|
|
||||||
|
|
||||||
class TestRegularFieldMappings(TestCase):
|
class TestRegularFieldMappings(TestCase):
|
||||||
def test_regular_fields(self):
|
def test_regular_fields(self):
|
||||||
|
@ -69,6 +73,87 @@ class TestRegularFieldMappings(TestCase):
|
||||||
|
|
||||||
self.assertEqual(repr(TestSerializer()), expected)
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
|
def test_method_field(self):
|
||||||
|
"""
|
||||||
|
Properties and methods on the model should be allowed as `Meta.fields`
|
||||||
|
values, and should map to `ReadOnlyField`.
|
||||||
|
"""
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = ('auto_field', 'method')
|
||||||
|
|
||||||
|
expected = dedent("""
|
||||||
|
TestSerializer():
|
||||||
|
auto_field = IntegerField(read_only=True)
|
||||||
|
method = ReadOnlyField()
|
||||||
|
""")
|
||||||
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
|
def test_pk_fields(self):
|
||||||
|
"""
|
||||||
|
Both `pk` and the actual primary key name are valid in `Meta.fields`.
|
||||||
|
"""
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = ('pk', 'auto_field')
|
||||||
|
|
||||||
|
expected = dedent("""
|
||||||
|
TestSerializer():
|
||||||
|
pk = IntegerField(label='Auto field', read_only=True)
|
||||||
|
auto_field = IntegerField(read_only=True)
|
||||||
|
""")
|
||||||
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
|
def test_extra_field_kwargs(self):
|
||||||
|
"""
|
||||||
|
Ensure `extra_kwargs` are passed to generated fields.
|
||||||
|
"""
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = ('pk', 'char_field')
|
||||||
|
extra_kwargs = {'char_field': {'default': 'extra'}}
|
||||||
|
|
||||||
|
expected = dedent("""
|
||||||
|
TestSerializer():
|
||||||
|
pk = IntegerField(label='Auto field', read_only=True)
|
||||||
|
char_field = CharField(default='extra', max_length=100)
|
||||||
|
""")
|
||||||
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
|
def test_invalid_field(self):
|
||||||
|
"""
|
||||||
|
Field names that do not map to a model field or relationship should
|
||||||
|
raise a configuration errror.
|
||||||
|
"""
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = ('auto_field', 'invalid')
|
||||||
|
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as excinfo:
|
||||||
|
TestSerializer()
|
||||||
|
expected = 'Field name `invalid` is not valid for model `ModelBase`.'
|
||||||
|
assert str(excinfo.exception) == expected
|
||||||
|
|
||||||
|
def test_missing_field(self):
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
missing = serializers.ReadOnlyField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = ('auto_field',)
|
||||||
|
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as excinfo:
|
||||||
|
TestSerializer()
|
||||||
|
expected = (
|
||||||
|
'Field `missing` has been declared on serializer '
|
||||||
|
'`TestSerializer`, but is missing from `Meta.fields`.'
|
||||||
|
)
|
||||||
|
assert str(excinfo.exception) == expected
|
||||||
|
|
||||||
|
|
||||||
# Testing relational field mappings
|
# Testing relational field mappings
|
||||||
|
|
Loading…
Reference in New Issue
Block a user