mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-29 17:39:48 +03:00
Fixed dotted write of non-relational fields, plus the related tests
This commit is contained in:
parent
bc5955f031
commit
2d52a0f180
|
@ -819,9 +819,21 @@ def raise_errors_on_nested_writes(method_name, serializer, validated_data, model
|
||||||
# class UserSerializer(ModelSerializer):
|
# class UserSerializer(ModelSerializer):
|
||||||
# ...
|
# ...
|
||||||
# address = serializer.CharField('profile.address')
|
# address = serializer.CharField('profile.address')
|
||||||
|
#
|
||||||
|
# Though, we can have a dotted field if it is not expressing a model relation.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# class NonRelationalPersonModel(models.Model):
|
||||||
|
# profile = JSONField()
|
||||||
|
#
|
||||||
|
# class UserSerializer(ModelSerializer):
|
||||||
|
# ...
|
||||||
|
# address = serializer.CharField('profile.address')
|
||||||
assert not any(
|
assert not any(
|
||||||
len(field.source_attrs) > 1 and
|
len(field.source_attrs) > 1 and
|
||||||
(field.source_attrs[0] in validated_data) and
|
(field.source_attrs[0] in validated_data) and
|
||||||
|
(field.source_attrs[0] in model_field_info.relations) and
|
||||||
isinstance(validated_data[field.source_attrs[0]], (list, dict))
|
isinstance(validated_data[field.source_attrs[0]], (list, dict))
|
||||||
for field in serializer._writable_fields
|
for field in serializer._writable_fields
|
||||||
), (
|
), (
|
||||||
|
|
|
@ -4,6 +4,9 @@ from django.http import QueryDict
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.compat import postgres_fields
|
||||||
|
from rest_framework.serializers import raise_errors_on_nested_writes
|
||||||
|
from rest_framework.utils import model_meta
|
||||||
|
|
||||||
|
|
||||||
class TestNestedSerializer:
|
class TestNestedSerializer:
|
||||||
|
@ -302,3 +305,55 @@ class TestNestedWriteErrors(TestCase):
|
||||||
'serializer `tests.test_serializer_nested.DottedAddressSerializer`, '
|
'serializer `tests.test_serializer_nested.DottedAddressSerializer`, '
|
||||||
'or set `read_only=True` on dotted-source serializer fields.'
|
'or set `read_only=True` on dotted-source serializer fields.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif('not postgres_fields')
|
||||||
|
class TestNestedNonRelationalFieldWrite:
|
||||||
|
"""
|
||||||
|
Test that raise_errors_on_nested_writes does not raise `AssertionError` when the
|
||||||
|
model field is not a relation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_nested_serializer_create_and_update(self):
|
||||||
|
class NonRelationalPersonModel(models.Model):
|
||||||
|
"""Model declaring a postgres JSONField"""
|
||||||
|
data = postgres_fields.JSONField()
|
||||||
|
|
||||||
|
class NonRelationalPersonDataSerializer(serializers.Serializer):
|
||||||
|
occupation = serializers.CharField()
|
||||||
|
|
||||||
|
class NonRelationalPersonSerializer(serializers.ModelSerializer):
|
||||||
|
data = NonRelationalPersonDataSerializer()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = NonRelationalPersonModel
|
||||||
|
fields = ['data']
|
||||||
|
|
||||||
|
serializer = NonRelationalPersonSerializer(data={'data': {'occupation': 'developer'}})
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {'data': {'occupation': 'developer'}}
|
||||||
|
ModelClass = serializer.Meta.model
|
||||||
|
info = model_meta.get_field_info(ModelClass)
|
||||||
|
raise_errors_on_nested_writes('create', serializer, serializer.validated_data, info)
|
||||||
|
raise_errors_on_nested_writes('update', serializer, serializer.validated_data, info)
|
||||||
|
|
||||||
|
def test_dotted_source_field_create_and_update(self):
|
||||||
|
class NonRelationalPersonModel(models.Model):
|
||||||
|
"""Model declaring a postgres JSONField"""
|
||||||
|
data = postgres_fields.JSONField()
|
||||||
|
|
||||||
|
class DottedNonRelationalPersonSerializer(serializers.ModelSerializer):
|
||||||
|
occupation = serializers.CharField(source='data.occupation')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = NonRelationalPersonModel
|
||||||
|
fields = ['occupation']
|
||||||
|
|
||||||
|
serializer = DottedNonRelationalPersonSerializer(data={'occupation': 'developer'})
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {'data': {'occupation': 'developer'}}
|
||||||
|
ModelClass = serializer.Meta.model
|
||||||
|
info = model_meta.get_field_info(ModelClass)
|
||||||
|
raise_errors_on_nested_writes('create', serializer, serializer.validated_data, info)
|
||||||
|
raise_errors_on_nested_writes('update', serializer, serializer.validated_data, info)
|
||||||
|
assert serializer.data == {'occupation': 'developer'}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user