mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-10 19:56:59 +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
|
||||
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.utils import six
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
@ -358,6 +358,7 @@ class ModelSerializer(Serializer):
|
|||
model = getattr(self.Meta, 'model')
|
||||
fields = getattr(self.Meta, 'fields', None)
|
||||
depth = getattr(self.Meta, 'depth', 0)
|
||||
extra_kwargs = getattr(self.Meta, 'extra_kwargs', {})
|
||||
|
||||
# Retrieve metadata about fields & relationships on the model class.
|
||||
info = model_meta.get_field_info(model)
|
||||
|
@ -405,9 +406,32 @@ class ModelSerializer(Serializer):
|
|||
if not issubclass(field_cls, HyperlinkedRelatedField):
|
||||
kwargs.pop('view_name', None)
|
||||
|
||||
else:
|
||||
assert False, 'Field name `%s` is not valid.' % field_name
|
||||
elif hasattr(model, 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)
|
||||
|
||||
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
|
||||
an appropriate set of serializer fields for each case.
|
||||
"""
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
from rest_framework import serializers
|
||||
|
@ -37,6 +38,9 @@ class RegularFieldsModel(models.Model):
|
|||
time_field = models.TimeField()
|
||||
url_field = models.URLField(max_length=100)
|
||||
|
||||
def method(self):
|
||||
return 'method'
|
||||
|
||||
|
||||
class TestRegularFieldMappings(TestCase):
|
||||
def test_regular_fields(self):
|
||||
|
@ -69,6 +73,87 @@ class TestRegularFieldMappings(TestCase):
|
|||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user