Repository: encode/django-rest-framework

Issue:
ModelSerializer generate ChoicesField will discard default parameter
model

```python
class Brand(models.Model):
    name = models.CharField(_("名称"), max_length=50, unique=True)
    status = models.SmallIntegerField(
        verbose_name=_("状态"),
        choices=BrandStatus.choices,
        default=BrandStatus.ENABLE.value,
        help_text=make_markdown_table(BrandStatus.choices)
    )
    description = models.CharField(
        _("描述"), max_length=300, null=True, blank=True
    )
    creator = models.ForeignKey(
        "users.User", on_delete=models.CASCADE, verbose_name=_("拥有者")
    )
    created = models.DateTimeField(_("创建时间"), auto_now_add=True)
    updated = models.DateTimeField(_("更新时间"), auto_now=True)
```

Serializer

```python
class BrandSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=50, validators=[special_character])
    created = serializers.DateTimeField(read_only=True)
    updated = serializers.DateTimeField(read_only=True)
    creator = serializers.ReadOnlyField(source="creator.username")

    class Meta:
        model = Brand
        fields = "__all__"
```



swagger
![swagger](https://user-images.githubusercontent.com/32224841/89626069-69033500-d8cb-11ea-8a71-5650385d7826.png)

So i find

> Serializers.ModelSerializer

```python
if 'choices' in field_kwargs:
  # Fields with choices get coerced into `ChoiceField`
  # instead of using their regular typed field.
  field_class = self.serializer_choice_field
  # Some model fields may introduce kwargs that would not be valid
  # for the choice field. We need to strip these out.
  # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES)
  valid_kwargs = {
    'read_only', 'write_only',
    'required', 'default', 'initial', 'source',
    'label', 'help_text', 'style',
    'error_messages', 'validators', 'allow_null', 'allow_blank',
    'choices'
  }
  for key in list(field_kwargs):
    if key not in valid_kwargs:
      field_kwargs.pop(key)
```

default parameter not in valid_kwargs and will pop, but default in field_kwargs['field_kwargs']

I rewrite 

```python
class ModelSerializer(serializers.ModelSerializer):
    def build_standard_field(self, field_name, model_field):
        field_kwargs = get_field_kwargs(field_name, model_field)
        if 'choices' in field_kwargs:
            # Fields with choices get coerced into `ChoiceField`
            # instead of using their regular typed field.
            field_class = self.serializer_choice_field
            # Some model fields may introduce kwargs that would not be valid
            # for the choice field. We need to strip these out.
            # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES)
            valid_kwargs = {
                'read_only', 'write_only',
                'required', 'default', 'initial', 'source',
                'label', 'help_text', 'style',
                'error_messages', 'validators', 'allow_null', 'allow_blank',
                'choices'
            }
            field_kwargs["default"] = field_kwargs["model_field"].default  # add this
            for key in list(field_kwargs):
                if key not in valid_kwargs:
                    field_kwargs.pop(key)
        else:
            field_class, field_kwargs = super(ModelSerializer, self).build_standard_field(field_name, model_field)
        return field_class, field_kwargs
```

swagger
![swager2](https://user-images.githubusercontent.com/32224841/89626432-0199b500-d8cc-11ea-985a-b6d1494b0e29.png)



Discussion:
you can use the `extra_kwargs`, follow the link https://www.django-rest-framework.org/community/3.0-announcement/#the-extra_kwargs-option. Alternatively, specify the field explicitly on the serializer class.

Resolving patch:
diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py
--- a/rest_framework/metadata.py
+++ b/rest_framework/metadata.py
@@ -11,6 +11,7 @@
 from django.utils.encoding import force_str
 
 from rest_framework import exceptions, serializers
+from rest_framework.fields import empty
 from rest_framework.request import clone_request
 from rest_framework.utils.field_mapping import ClassLookupDict
 
@@ -149,4 +150,7 @@ def get_field_info(self, field):
                 for choice_value, choice_name in field.choices.items()
             ]
 
+        if getattr(field, 'default', None) and field.default != empty and not callable(field.default):
+            field_info['default'] = field.default
+
         return field_info
diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py
--- a/rest_framework/utils/field_mapping.py
+++ b/rest_framework/utils/field_mapping.py
@@ -9,6 +9,7 @@
 from django.utils.text import capfirst
 
 from rest_framework.compat import postgres_fields
+from rest_framework.fields import empty
 from rest_framework.validators import UniqueValidator
 
 NUMERIC_FIELD_TYPES = (
@@ -127,6 +128,9 @@ def get_field_kwargs(field_name, model_field):
         kwargs['read_only'] = True
         return kwargs
 
+    if model_field.default is not None and model_field.default != empty and not callable(model_field.default):
+        kwargs['default'] = model_field.default
+
     if model_field.has_default() or model_field.blank or model_field.null:
         kwargs['required'] = False
 


Test patch:
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -184,6 +184,135 @@ def get_serializer(self):
         assert response.status_code == status.HTTP_200_OK
         assert response.data == expected
 
+    def test_actions_with_default(self):
+        """
+        On generic views OPTIONS should return an 'actions' key with metadata
+        on the fields with default that may be supplied to PUT and POST requests.
+        """
+        class NestedField(serializers.Serializer):
+            a = serializers.IntegerField(default=2)
+            b = serializers.IntegerField()
+
+        class ExampleSerializer(serializers.Serializer):
+            choice_field = serializers.ChoiceField(['red', 'green', 'blue'], default='red')
+            integer_field = serializers.IntegerField(
+                min_value=1, max_value=1000, default=1
+            )
+            char_field = serializers.CharField(
+                min_length=3, max_length=40, default="example"
+            )
+            list_field = serializers.ListField(
+                child=serializers.ListField(
+                    child=serializers.IntegerField(default=1)
+                )
+            )
+            nested_field = NestedField()
+            uuid_field = serializers.UUIDField(label="UUID field")
+
+        class ExampleView(views.APIView):
+            """Example view."""
+            def post(self, request):
+                pass
+
+            def get_serializer(self):
+                return ExampleSerializer()
+
+        view = ExampleView.as_view()
+        response = view(request=request)
+        expected = {
+            'name': 'Example',
+            'description': 'Example view.',
+            'renders': [
+                'application/json',
+                'text/html'
+            ],
+            'parses': [
+                'application/json',
+                'application/x-www-form-urlencoded',
+                'multipart/form-data'
+            ],
+            'actions': {
+                'POST': {
+                    'choice_field': {
+                        'type': 'choice',
+                        'required': False,
+                        'read_only': False,
+                        'label': 'Choice field',
+                        "choices": [
+                            {'value': 'red', 'display_name': 'red'},
+                            {'value': 'green', 'display_name': 'green'},
+                            {'value': 'blue', 'display_name': 'blue'}
+                        ],
+                        'default': 'red'
+                    },
+                    'integer_field': {
+                        'type': 'integer',
+                        'required': False,
+                        'read_only': False,
+                        'label': 'Integer field',
+                        'min_value': 1,
+                        'max_value': 1000,
+                        'default': 1
+                    },
+                    'char_field': {
+                        'type': 'string',
+                        'required': False,
+                        'read_only': False,
+                        'label': 'Char field',
+                        'min_length': 3,
+                        'max_length': 40,
+                        'default': 'example'
+                    },
+                    'list_field': {
+                        'type': 'list',
+                        'required': True,
+                        'read_only': False,
+                        'label': 'List field',
+                        'child': {
+                            'type': 'list',
+                            'required': True,
+                            'read_only': False,
+                            'child': {
+                                'type': 'integer',
+                                'required': False,
+                                'read_only': False,
+                                'default': 1
+                            }
+                        }
+                    },
+                    'nested_field': {
+                        'type': 'nested object',
+                        'required': True,
+                        'read_only': False,
+                        'label': 'Nested field',
+                        'children': {
+                            'a': {
+                                'type': 'integer',
+                                'required': False,
+                                'read_only': False,
+                                'label': 'A',
+                                'default': 2
+                            },
+                            'b': {
+                                'type': 'integer',
+                                'required': True,
+                                'read_only': False,
+                                'label': 'B'
+                            }
+                        }
+                    },
+                    'uuid_field': {
+                        'type': 'string',
+                        'required': True,
+                        'read_only': False,
+                        'label': 'UUID field'
+                    }
+                }
+            }
+        }
+        assert response.status_code == status.HTTP_200_OK
+        assert response.data == expected
+
     def test_global_permissions(self):
         """
         If a user does not have global permissions on an action, then any
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
@@ -173,7 +173,7 @@ class Meta:
             TestSerializer():
                 auto_field = IntegerField(read_only=True)
                 big_integer_field = IntegerField()
-                boolean_field = BooleanField(required=False)
+                boolean_field = BooleanField(default=False, required=False)
                 char_field = CharField(max_length=100)
                 comma_separated_integer_field = CharField(max_length=100, validators=[<django.core.validators.RegexValidator object>])
                 date_field = DateField()
@@ -182,7 +182,7 @@ class Meta:
                 email_field = EmailField(max_length=100)
                 float_field = FloatField()
                 integer_field = IntegerField()
-                null_boolean_field = BooleanField(allow_null=True, required=False)
+                null_boolean_field = BooleanField(allow_null=True, default=False, required=False)
                 positive_integer_field = IntegerField()
                 positive_small_integer_field = IntegerField()
                 slug_field = SlugField(allow_unicode=False, max_length=100)
@@ -210,7 +210,7 @@ class Meta:
                 length_limit_field = CharField(max_length=12, min_length=3)
                 blank_field = CharField(allow_blank=True, max_length=10, required=False)
                 null_field = IntegerField(allow_null=True, required=False)
-                default_field = IntegerField(required=False)
+                default_field = IntegerField(default=0, required=False)
                 descriptive_field = IntegerField(help_text='Some help text', label='A label')
                 choices_field = ChoiceField(choices=(('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')))
                 text_choices_field = ChoiceField(choices=(('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')))