Repository: encode/django-rest-framework

Issue:
`allow_empty` does not work on serializers with `many=True`.
Is this expected behaviour?

``` python
>>> from rest_framework import serializers
>>>
>>> class ChildSerializer(serializers.Serializer):
...     name = serializers.CharField()
...
>>> class ParentSerializer(serializers.Serializer):
...     children = ChildSerializer(many=True, allow_empty=False)
...
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 2, in ParentSerializer
  File "/Users/pmdarrow/.virtualenvs/api/lib/python3.4/site-packages/rest_framework/serializers.py", line 96, in __new__
    return cls.many_init(*args, **kwargs)
  File "/Users/pmdarrow/.virtualenvs/api/lib/python3.4/site-packages/rest_framework/serializers.py", line 116, in many_init
    child_serializer = cls(*args, **kwargs)
  File "/Users/pmdarrow/.virtualenvs/api/lib/python3.4/site-packages/rest_framework/serializers.py", line 90, in __init__
    super(BaseSerializer, self).__init__(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'allow_empty'
```



Discussion:
`allow_empty` isn't part of the `Field`'s core arguments as listed in the [documentation](http://www.django-rest-framework.org/api-guide/fields/) so I'd expect `allow_empty` will raise an exception.
Do you have a use case where this should be a required argument ?

It's the same use case for `allow_empty` on a `ListField`. In my example I want to disallow an empty list for `children`. To be clear I don't think it should be a required argument, it should be optional.

Alright, looks legit. PR to come.


Resolving patch:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -113,8 +113,13 @@ def many_init(cls, *args, **kwargs):
             kwargs['child'] = cls()
             return CustomListSerializer(*args, **kwargs)
         """
+        allow_empty = kwargs.pop('allow_empty', None)
         child_serializer = cls(*args, **kwargs)
-        list_kwargs = {'child': child_serializer}
+        list_kwargs = {
+            'child': child_serializer,
+        }
+        if allow_empty is not None:
+            list_kwargs['allow_empty'] = allow_empty
         list_kwargs.update(dict([
             (key, value) for key, value in kwargs.items()
             if key in LIST_SERIALIZER_KWARGS


Test patch:
diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py
--- a/tests/test_serializer_nested.py
+++ b/tests/test_serializer_nested.py
@@ -79,17 +79,23 @@ class NestedSerializer(serializers.Serializer):
         class TestSerializer(serializers.Serializer):
             allow_null = NestedSerializer(many=True, allow_null=True)
             not_allow_null = NestedSerializer(many=True)
+            allow_empty = NestedSerializer(many=True, allow_empty=True)
+            not_allow_empty = NestedSerializer(many=True, allow_empty=False)
 
         self.Serializer = TestSerializer
 
     def test_null_allowed_if_allow_null_is_set(self):
         input_data = {
             'allow_null': None,
-            'not_allow_null': [{'example': '2'}, {'example': '3'}]
+            'not_allow_null': [{'example': '2'}, {'example': '3'}],
+            'allow_empty': [{'example': '2'}],
+            'not_allow_empty': [{'example': '2'}],
         }
         expected_data = {
             'allow_null': None,
-            'not_allow_null': [{'example': 2}, {'example': 3}]
+            'not_allow_null': [{'example': 2}, {'example': 3}],
+            'allow_empty': [{'example': 2}],
+            'not_allow_empty': [{'example': 2}],
         }
         serializer = self.Serializer(data=input_data)
 
@@ -99,7 +105,9 @@ def test_null_allowed_if_allow_null_is_set(self):
     def test_null_is_not_allowed_if_allow_null_is_not_set(self):
         input_data = {
             'allow_null': None,
-            'not_allow_null': None
+            'not_allow_null': None,
+            'allow_empty': [{'example': '2'}],
+            'not_allow_empty': [{'example': '2'}],
         }
         serializer = self.Serializer(data=input_data)
 
@@ -118,10 +126,44 @@ def validate_allow_null(self, value):
 
         input_data = {
             'allow_null': None,
-            'not_allow_null': [{'example': 2}]
+            'not_allow_null': [{'example': 2}],
+            'allow_empty': [{'example': 2}],
+            'not_allow_empty': [{'example': 2}],
         }
         serializer = TestSerializer(data=input_data)
 
         assert serializer.is_valid()
         assert serializer.validated_data == input_data
         assert TestSerializer.validation_was_run
+
+    def test_empty_allowed_if_allow_empty_is_set(self):
+        input_data = {
+            'allow_null': [{'example': '2'}],
+            'not_allow_null': [{'example': '2'}],
+            'allow_empty': [],
+            'not_allow_empty': [{'example': '2'}],
+        }
+        expected_data = {
+            'allow_null': [{'example': 2}],
+            'not_allow_null': [{'example': 2}],
+            'allow_empty': [],
+            'not_allow_empty': [{'example': 2}],
+        }
+        serializer = self.Serializer(data=input_data)
+
+        assert serializer.is_valid(), serializer.errors
+        assert serializer.validated_data == expected_data
+
+    def test_empty_not_allowed_if_allow_empty_is_set_to_false(self):
+        input_data = {
+            'allow_null': [{'example': '2'}],
+            'not_allow_null': [{'example': '2'}],
+            'allow_empty': [],
+            'not_allow_empty': [],
+        }
+        serializer = self.Serializer(data=input_data)
+
+        assert not serializer.is_valid()
+
+        expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}}
+        assert serializer.errors == expected_errors