Repository: encode/django-rest-framework

Issue:
Unable to override required argument on a read_only field in extra_kwargs
Fields that are set to `"read_only": True` are not passed to `update()` on a serializer. A work around to this was to add `"read_only": False` to `extra_kwargs` for that field. This would pass the value to update and allow us to use it.

One problem then is with required fields. In `create()`, these fields must be supplied by default. However, for something like an auto-generated UUID or primary key, we cannot provide it. To work around this, we set `"required": False` in the extra_kwargs for that field as well.

In 3.1.2, this behavior allowed creation without that field provided and update was passed it's value. In 3.1.3, this isn't possible because the field is now required and validation fails. This behavior seems to be changed due to #2975.

In #2975, if `read_only` is set to `True` in the model or serializer fields, it drops the `required` value in `extra_kwargs` and defaults to the model or serializer field values. However, we've set the value for `read_only` to `False` in `extra_kwargs`. The problem is that the serializer is still assuming the value is `True` since it is pulling from the model or serializer fields and not `extra_kwargs`, overriding the behavior we want.

Here is an example usage:
#### serializers.py

``` python
class AlbumSerializer(serializers.ModelSerializer):

    class Meta:
        model = Album

        fields = (
            'id', 'artist', 'producer',
            'year', 'price'
        )

        extra_kwargs = {
            "id": {
                "required": False,
                "read_only": False
            }
        }
```



Discussion:
Should [this line](https://github.com/tomchristie/django-rest-framework/pull/2975/files#diff-80f43677c94659fbd60c8687cce68eafR1091) instead be like so?...

```
if extra_kwargs.get('read_only', kwargs.get('read_only', False)):
    extra_kwargs.pop('required', None)  # Read only fields should always omit the 'required' argument.
```

Assume that would resolve your issue?

@tomchristie Yes, that fixes the issue I'm experiencing.


Resolving patch:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -1105,8 +1105,8 @@ def include_extra_kwargs(self, kwargs, extra_kwargs):
         if extra_kwargs.get('default') and kwargs.get('required') is False:
             kwargs.pop('required')
 
-        if kwargs.get('read_only', False):
-            extra_kwargs.pop('required', None)
+        if extra_kwargs.get('read_only', kwargs.get('read_only', False)):
+            extra_kwargs.pop('required', None)  # Read only fields should always omit the 'required' argument.
 
         kwargs.update(extra_kwargs)
 


Test patch:
diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py
--- a/tests/test_model_serializer.py
+++ b/tests/test_model_serializer.py
@@ -235,6 +235,23 @@ class Meta:
         """)
         self.assertEqual(repr(TestSerializer()), expected)
 
+    def test_extra_field_kwargs_required(self):
+        """
+        Ensure `extra_kwargs` are passed to generated fields.
+        """
+        class TestSerializer(serializers.ModelSerializer):
+            class Meta:
+                model = RegularFieldsModel
+                fields = ('auto_field', 'char_field')
+                extra_kwargs = {'auto_field': {'required': False, 'read_only': False}}
+
+        expected = dedent("""
+            TestSerializer():
+                auto_field = IntegerField(read_only=False, required=False)
+                char_field = CharField(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