Repository: encode/django-rest-framework

Issue:
DRF doesn't set allow_empty=False for ArrayField with blank=False
Recently I came across an issue where invalid data was being created through our API, it turns out there's a subtle difference between the validation on an `ArrayField` and the resulting `ListField` in a `ModelSerializer`.

Given the following `models.py`:

```python
from django.db import models
from django.contrib.postgres.fields import ArrayField

class Example(models.Model):
    data = ArrayField(models.IntegerField())  # blank=False by default
```

and this `serializers.py`

```python
from rest_framework import serializers
from .models import Example

class ExampleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Example
        fields = ['data']

class ExampleSerializer2(serializers.ModelSerializer):
    data = serializers.ListField(child=serializers.IntegerField(), allow_empty=False)

    class Meta:
        model = Example
        fields = ['data']
```

The `TestExampleSerializer.test_empty_list` test fails:

```python
from unittest import TestCase

from django.core.exceptions import ValidationError

from .models import Example
from .serializers import ExampleSerializer, ExampleSerializer2

class TestExampleModel(TestCase):
    def test_empty_list(self):
        # This works, Django doesn't allow an empty list if blank=False
        obj = Example(data=[])
        with self.assertRaises(ValidationError) as cm:
            obj.full_clean()
        error_dict = cm.exception.error_dict
        self.assertIn('data', error_dict)
        self.assertEqual('blank', error_dict['data'][0].code)

class TestExampleSerializer(TestCase):
    def test_empty_list(self):
        # This fails, DRF allows empty lists
        serializer = ExampleSerializer(data={'data': []})
        self.assertFalse(serializer.is_valid(), 'Expected validation error for empty list')

class TestExampleSerializer2(TestCase):
    def test_empty_list(self):
        # Setting allow_empty=False manually works
        serializer = ExampleSerializer2(data={'data': []})
        self.assertFalse(serializer.is_valid(), 'Expected validation error for empty list')
        self.assertIn('data', serializer.errors)
        self.assertEqual('empty', serializer.errors['data'][0].code)
```

I expected `ExampleSerializer` and `ExampleSerializer2` to behave the same. 

When creating the `ListField` from the `ArrayField` DRF should set `allow_empty` on the `ListField` to the same value as `blank` on the `ArrayField`.


Discussion:

Resolving patch:
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
@@ -109,6 +109,9 @@ def get_field_kwargs(field_name, model_field):
     if model_field.blank and (isinstance(model_field, (models.CharField, models.TextField))):
         kwargs['allow_blank'] = True
 
+    if not model_field.blank and (postgres_fields and isinstance(model_field, postgres_fields.ArrayField)):
+        kwargs['allow_empty'] = False
+
     if isinstance(model_field, models.FilePathField):
         kwargs['path'] = model_field.path
 


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
@@ -440,15 +440,17 @@ class Meta:
     def test_array_field(self):
         class ArrayFieldModel(models.Model):
             array_field = postgres_fields.ArrayField(base_field=models.CharField())
+            array_field_with_blank = postgres_fields.ArrayField(blank=True, base_field=models.CharField())
 
         class TestSerializer(serializers.ModelSerializer):
             class Meta:
                 model = ArrayFieldModel
-                fields = ['array_field']
+                fields = ['array_field', 'array_field_with_blank']
 
         expected = dedent("""
             TestSerializer():
-                array_field = ListField(child=CharField(label='Array field', validators=[<django.core.validators.MaxLengthValidator object>]))
+                array_field = ListField(allow_empty=False, child=CharField(label='Array field', validators=[<django.core.validators.MaxLengthValidator object>]))
+                array_field_with_blank = ListField(child=CharField(label='Array field with blank', validators=[<django.core.validators.MaxLengthValidator object>]), required=False)
         """)
         self.assertEqual(repr(TestSerializer()), expected)