This commit is contained in:
Mattias Lindvall 2024-01-05 05:40:27 +01:00 committed by GitHub
commit 6911b89cca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 0 deletions

View File

@ -528,6 +528,21 @@ You can add extra fields to a `ModelSerializer` or override the default fields b
Extra fields can correspond to any property or callable on the model.
## Specifying field classes
In order to override the field class only, and still get the field kwargs set dynamically, you may use the `field_classes`
Meta option.
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['account_name']
field_classes = {'account_name': AccountNameField}
Note that the field class that you use needs to support whatever kwargs the serializer determines to use for this field.
Typically, you want your custom field class to inherit from the appropriate built in field class.
For example, the custom `AccountNameField` could inherit from the built in `CharField`.
## Specifying read only fields
You may wish to specify multiple fields as read-only. Instead of adding each field explicitly with the `read_only=True` attribute, you may use the shortcut Meta option, `read_only_fields`.

View File

@ -1122,6 +1122,11 @@ class ModelSerializer(Serializer):
source, info, model, depth
)
# Override field_class by classes defined in `Meta.field_classes`.
field_class = self.get_field_class(
source, info, model, field_class
)
# Include any kwargs defined in `Meta.extra_kwargs`
field_kwargs = self.include_extra_kwargs(
field_kwargs, extra_field_kwargs
@ -1387,6 +1392,17 @@ class ModelSerializer(Serializer):
(field_name, model_class.__name__, self.__class__.__module__, self.__class__.__name__)
)
def get_field_class(self, field_name, info, model_class, field_class):
"""
Get field class from 'field_classes', or use the default.
"""
field_classes = getattr(self.Meta, 'field_classes', {})
if field_name in field_classes:
return field_classes[field_name]
return field_class
def include_extra_kwargs(self, kwargs, extra_kwargs):
"""
Include any 'extra_kwargs' that have been included for this field,

View File

@ -271,6 +271,26 @@ class TestRegularFieldMappings(TestCase):
""")
self.assertEqual(repr(TestSerializer()), expected)
def test_field_classes(self):
"""
Ensure `field_classes` do override the field class.
"""
class CustomCharField(serializers.CharField):
pass
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = RegularFieldsModel
fields = ('auto_field', 'char_field')
field_classes = {'char_field': CustomCharField}
expected = dedent("""
TestSerializer():
auto_field = IntegerField(read_only=True)
char_field = CustomCharField(max_length=100)
""")
self.assertEqual(repr(TestSerializer()), expected)
def test_extra_field_kwargs(self):
"""
Ensure `extra_kwargs` are passed to generated fields.