Skip to content

Fix #4198 #4199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/api-guide/serializers.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ This option should be a list or tuple of field names, and is declared as follows
fields = ('id', 'account_name', 'users', 'created')
read_only_fields = ('account_name',)

Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option.
Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option. Having a field listed in `read_only_fields` and declared on the class will raise an exception.

---

Expand Down Expand Up @@ -570,6 +570,8 @@ This option is a dictionary, mapping field names to a dictionary of keyword argu
user.save()
return user

Having arguments for a field in `extra_kwargs` for a field declared on the class will raise an exception.

## Relational fields

When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for `ModelSerializer` is to use the primary keys of the related instances.
Expand Down
12 changes: 8 additions & 4 deletions rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,11 @@ def get_fields(self):
# Determine any extra field arguments and hidden fields that
# should be included
extra_kwargs = self.get_extra_kwargs()
for field in extra_kwargs:
assert field not in declared_fields, (
"Field {} is declared on the class and also present in "
"extra_kwargs or read_only_fields".format(field)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On thinking about this: we might need to be a bit clever about this - some folks may want to use subclassing to override a declared field. Unclear.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Jun 15, 2016 at 5:56 PM, Tom Christie notifications@github.com
wrote:

In rest_framework/serializers.py
#4199 (comment)
:

@@ -947,6 +947,11 @@ def get_fields(self):
# Determine any extra field arguments and hidden fields that
# should be included
extra_kwargs = self.get_extra_kwargs()

  •    for field in extra_kwargs:
    
  •        assert field not in declared_fields, (
    
  •            "Field {} is declared on the class and also present in "
    
  •            "extra_kwargs or read_only_fields".format(field)
    
  •        )
    

On thinking about this: we might need to be a bit clever about this -
some folks may want to use subclassing to override a declared field.
Unclear.

Can you give me an example, and what you think the correct behaviour
should be?

George-Cristian Bîrzan

On Wed, Jun 15, 2016 at 5:56 PM, Tom Christie notifications@github.com
wrote:

In rest_framework/serializers.py
#4199 (comment)
:

@@ -947,6 +947,11 @@ def get_fields(self):
# Determine any extra field arguments and hidden fields that
# should be included
extra_kwargs = self.get_extra_kwargs()

  •    for field in extra_kwargs:
    
  •        assert field not in declared_fields, (
    
  •            "Field {} is declared on the class and also present in "
    
  •            "extra_kwargs or read_only_fields".format(field)
    
  •        )
    

On thinking about this: we might need to be a bit clever about this -
some folks may want to use subclassing to override a declared field.
Unclear.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/tomchristie/django-rest-framework/pull/4199/files/5dd336ec6ca80dbcabaa1be054ac5a7f2f6c2a7d#r67177845,
or mute the thread
https://github.com/notifications/unsubscribe/AAv3ZReOQoFmXw-gCmRa6DrrjKdDisEhks5qMBKigaJpZM4I2QWM
.

George-Cristian Bîrzan

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this functionality all the time, to override field attributes on inherited serializers.

I would even argue to leave the current behavior to allow providing extra kwargs, that is handy for providing common kwargs to multiple fields by a simple loop, (though, it can be done by overriding init, I had preferred this one).

extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(
field_names, declared_fields, extra_kwargs
)
Expand Down Expand Up @@ -1321,12 +1326,11 @@ def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs
# add in a hidden field that populates it.
hidden_fields[unique_constraint_name] = HiddenField(default=default)

# Update `extra_kwargs` with any new options.
# Update `extra_kwargs` with any new options but don't overwrite old values.
for key, value in uniqueness_extra_kwargs.items():
if key in extra_kwargs:
extra_kwargs[key].update(value)
else:
extra_kwargs[key] = value
value.update(extra_kwargs[key])
extra_kwargs[key] = value

return extra_kwargs, hidden_fields

Expand Down
45 changes: 43 additions & 2 deletions tests/test_model_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,8 +933,8 @@ class TestSerializer(serializers.ModelSerializer):

class Meta:
model = OneFieldModel
read_only_fields = ('char_field', 'non_model_field')
fields = read_only_fields
read_only_fields = ('char_field',)
fields = read_only_fields + ('non_model_field', )
Copy link
Member

@kevin-brown kevin-brown Jun 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this make a test or two fail because non_model_field isn't actually defined as read-only anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That particular test is TestMetaInheritance which doesn't try to set the
field, just checks whether it's set as read only. While the logic of the
test is not totally preserved, that's because the functionality changed.

On Wed, Jun 15, 2016 at 5:35 PM, Kevin Brown notifications@github.com
wrote:

In tests/test_model_serializer.py
#4199 (comment)
:

@@ -933,8 +933,8 @@ class TestSerializer(serializers.ModelSerializer):

         class Meta:
             model = OneFieldModel
  •            read_only_fields = ('char_field', 'non_model_field')
    
  •            fields = read_only_fields
    
  •            read_only_fields = ('char_field',)
    
  •            fields = read_only_fields + ('non_model_field', )
    

Shouldn't this make a test or two fail because non_model_field isn't
actually specified as read-only anymore?


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/tomchristie/django-rest-framework/pull/4199/files/5dd336ec6ca80dbcabaa1be054ac5a7f2f6c2a7d#r67173621,
or mute the thread
https://github.com/notifications/unsubscribe/AAv3ZSrABzE7kkWUp_UjAk2VfX6UOQVjks5qMA2ogaJpZM4I2QWM
.

George-Cristian Bîrzan

extra_kwargs = {}

class ChildSerializer(TestSerializer):
Expand All @@ -955,3 +955,44 @@ class Meta(TestSerializer.Meta):
self.assertEqual(unicode_repr(ChildSerializer()), child_expected)
self.assertEqual(unicode_repr(TestSerializer()), test_expected)
self.assertEqual(unicode_repr(ChildSerializer()), child_expected)


class TestDeclaredFieldsConflict(TestCase):
def test_extra_kwargs_conflict(self):
class TestSerializer(serializers.ModelSerializer):
some_field = serializers.CharField()

class Meta:
model = OneFieldModel
extra_kwargs = {'some_field': {'read_only': True}}
with self.assertRaises(AssertionError):
TestSerializer().get_fields()

def test_read_only_fields_conflict(self):
class TestSerializer(serializers.ModelSerializer):
some_field = serializers.CharField()

class Meta:
model = OneFieldModel
read_only_fields = ('some_field', )
with self.assertRaises(AssertionError):
TestSerializer().get_fields()


class TestUniquenessOverride(TestCase):
def test_required_not_overwritten(self):
class TestModel(models.Model):
field_1 = models.IntegerField(null=True)
field_2 = models.IntegerField()

class Meta:
unique_together = (('field_1', 'field_2'),)

class TestSerializer(serializers.ModelSerializer):
class Meta:
model = TestModel
extra_kwargs = {'field_1': {'required': False}}

fields = TestSerializer().fields
self.assertFalse(fields['field_1'].required)
self.assertTrue(fields['field_2'].required)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy