mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-14 10:12:36 +03:00
Add MODEL_SERIALIZER_FIELD_MAPPING settings
This commit is contained in:
parent
f113ab6b68
commit
760921a9bb
|
@ -143,6 +143,17 @@ Default: `ordering`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Serializer settings
|
||||||
|
|
||||||
|
#### MODEL_SERIALIZER_FIELD_MAPPING
|
||||||
|
|
||||||
|
Extra field mapping used to extend or override mapping of django db fields to serializer fields which is used by
|
||||||
|
ModelSerializer to set up fields for serializer.
|
||||||
|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Versioning settings
|
## Versioning settings
|
||||||
|
|
||||||
#### DEFAULT_VERSION
|
#### DEFAULT_VERSION
|
||||||
|
|
|
@ -894,13 +894,35 @@ class ModelSerializer(Serializer):
|
||||||
* A set of default validators are automatically populated.
|
* A set of default validators are automatically populated.
|
||||||
* Default `.create()` and `.update()` implementations are provided.
|
* Default `.create()` and `.update()` implementations are provided.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
serializer_related_field = PrimaryKeyRelatedField
|
||||||
|
serializer_related_to_field = SlugRelatedField
|
||||||
|
serializer_url_field = HyperlinkedIdentityField
|
||||||
|
serializer_choice_field = ChoiceField
|
||||||
|
|
||||||
|
# The field name for hyperlinked identity fields. Defaults to 'url'.
|
||||||
|
# You can modify this using the API setting.
|
||||||
|
#
|
||||||
|
# Note that if you instead need modify this on a per-serializer basis,
|
||||||
|
# you'll also need to ensure you update the `create` method on any generic
|
||||||
|
# views, to correctly handle the 'Location' response header for
|
||||||
|
# "HTTP 201 Created" responses.
|
||||||
|
url_field_name = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serializer_field_mapping(self):
|
||||||
|
"""Get mapping of django model field to serializer field.
|
||||||
|
|
||||||
The process of automatically determining a set of serializer fields
|
The process of automatically determining a set of serializer fields
|
||||||
based on the model fields is reasonably complex, but you almost certainly
|
based on the model fields is reasonably complex, but you almost certainly
|
||||||
don't need to dig into the implementation.
|
don't need to dig into the implementation.
|
||||||
|
|
||||||
If the `ModelSerializer` class *doesn't* generate the set of fields that
|
If the `ModelSerializer` class *doesn't* generate the set of fields that
|
||||||
you need you should either declare the extra/differing fields explicitly on
|
you need you should either extend serializer_field_mapping with
|
||||||
the serializer class, or simply use a `Serializer` class.
|
the extra/differing fields explicitly, or simply use a `Serializer`
|
||||||
|
class.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
serializer_field_mapping = {
|
serializer_field_mapping = {
|
||||||
models.AutoField: IntegerField,
|
models.AutoField: IntegerField,
|
||||||
|
@ -936,19 +958,12 @@ class ModelSerializer(Serializer):
|
||||||
serializer_field_mapping[postgres_fields.HStoreField] = HStoreField
|
serializer_field_mapping[postgres_fields.HStoreField] = HStoreField
|
||||||
serializer_field_mapping[postgres_fields.ArrayField] = ListField
|
serializer_field_mapping[postgres_fields.ArrayField] = ListField
|
||||||
serializer_field_mapping[postgres_fields.JSONField] = JSONField
|
serializer_field_mapping[postgres_fields.JSONField] = JSONField
|
||||||
serializer_related_field = PrimaryKeyRelatedField
|
for (
|
||||||
serializer_related_to_field = SlugRelatedField
|
model_field,
|
||||||
serializer_url_field = HyperlinkedIdentityField
|
serializer_field,
|
||||||
serializer_choice_field = ChoiceField
|
) in api_settings.MODEL_SERIALIZER_FIELD_MAPPING.items():
|
||||||
|
serializer_field_mapping[model_field] = serializer_field
|
||||||
# The field name for hyperlinked identity fields. Defaults to 'url'.
|
return serializer_field_mapping
|
||||||
# You can modify this using the API setting.
|
|
||||||
#
|
|
||||||
# Note that if you instead need modify this on a per-serializer basis,
|
|
||||||
# you'll also need to ensure you update the `create` method on any generic
|
|
||||||
# views, to correctly handle the 'Location' response header for
|
|
||||||
# "HTTP 201 Created" responses.
|
|
||||||
url_field_name = None
|
|
||||||
|
|
||||||
# Default `create` and `update` behavior...
|
# Default `create` and `update` behavior...
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
|
|
@ -126,6 +126,9 @@ DEFAULTS = {
|
||||||
'retrieve': 'read',
|
'retrieve': 'read',
|
||||||
'destroy': 'delete'
|
'destroy': 'delete'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# Serializers
|
||||||
|
'MODEL_SERIALIZER_FIELD_MAPPING': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,7 +150,8 @@ IMPORT_STRINGS = [
|
||||||
'UNAUTHENTICATED_USER',
|
'UNAUTHENTICATED_USER',
|
||||||
'UNAUTHENTICATED_TOKEN',
|
'UNAUTHENTICATED_TOKEN',
|
||||||
'VIEW_NAME_FUNCTION',
|
'VIEW_NAME_FUNCTION',
|
||||||
'VIEW_DESCRIPTION_FUNCTION'
|
'VIEW_DESCRIPTION_FUNCTION',
|
||||||
|
'MODEL_SERIALIZER_FIELD_MAPPING',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,6 +172,16 @@ def perform_import(val, setting_name):
|
||||||
return import_from_string(val, setting_name)
|
return import_from_string(val, setting_name)
|
||||||
elif isinstance(val, (list, tuple)):
|
elif isinstance(val, (list, tuple)):
|
||||||
return [import_from_string(item, setting_name) for item in val]
|
return [import_from_string(item, setting_name) for item in val]
|
||||||
|
elif isinstance(val, (dict)):
|
||||||
|
return {
|
||||||
|
import_from_string(
|
||||||
|
key,
|
||||||
|
setting_name,
|
||||||
|
): import_from_string(
|
||||||
|
value,
|
||||||
|
setting_name,
|
||||||
|
) for key, value in val.items()
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ from django.core.validators import (
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import m2m_changed
|
from django.db.models.signals import m2m_changed
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.test import TestCase
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.compat import postgres_fields
|
from rest_framework.compat import postgres_fields
|
||||||
|
@ -43,6 +43,12 @@ class CustomField(models.Field):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CustomCharFieldField(serializers.CharField):
|
||||||
|
"""
|
||||||
|
A custom serializer field simply for testing purposes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class OneFieldModel(models.Model):
|
class OneFieldModel(models.Model):
|
||||||
char_field = models.CharField(max_length=100)
|
char_field = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
@ -194,6 +200,32 @@ class TestRegularFieldMappings(TestCase):
|
||||||
custom_field = ModelField\(model_field=<tests.test_model_serializer.CustomField: custom_field>\)
|
custom_field = ModelField\(model_field=<tests.test_model_serializer.CustomField: custom_field>\)
|
||||||
file_path_field = FilePathField\(path=%r\)
|
file_path_field = FilePathField\(path=%r\)
|
||||||
""" % tempfile.gettempdir())
|
""" % tempfile.gettempdir())
|
||||||
|
print(expected)
|
||||||
|
assert re.search(expected, repr(TestSerializer())) is not None
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
REST_FRAMEWORK={
|
||||||
|
'MODEL_SERIALIZER_FIELD_MAPPING': {
|
||||||
|
'django.db.models.CharField': 'tests.test_model_serializer.CustomCharFieldField',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def test_custom_fields(self):
|
||||||
|
"""
|
||||||
|
If MODEL_SERIALIZER_FIELD_MAPPING is set than model fields should map
|
||||||
|
to their equivalent serializer fields.
|
||||||
|
"""
|
||||||
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RegularFieldsModel
|
||||||
|
fields = (
|
||||||
|
"char_field",
|
||||||
|
)
|
||||||
|
|
||||||
|
expected = dedent(r"""
|
||||||
|
TestSerializer\(\):
|
||||||
|
char_field = CustomCharFieldField\(max_length=100\)
|
||||||
|
""")
|
||||||
assert re.search(expected, repr(TestSerializer())) is not None
|
assert re.search(expected, repr(TestSerializer())) is not None
|
||||||
|
|
||||||
def test_field_options(self):
|
def test_field_options(self):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user