Repository: encode/django-rest-framework

Issue:
Not calling function with source= anymore
Here the serializer:

``` python
class IndividuSerializer(ModelSerializer):
    # ...
    sexe_display = CharField(source='get_sexe_display', label='sexe', read_only=True)
```

The API doesn't display the choice values from Django models anymore.

``` json
{
    "url": "http://localhost:8000/api/dsn/individu/1/",
    "id": 1,
    "metadatas": null,
    "sexe_display": "<bound method curry.<locals>._curried of <Individu: XXX XXX>>",
    "...": "..."
}
```

In the previous release it worked just fine. ;)



Discussion:
I'm not able to replicate this.

For example...

```
class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(source='get_username', read_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'email')
```

Results in this...

![screen shot 2016-10-21 at 15 40 44](https://cloud.githubusercontent.com/assets/647359/19602352/d6d9e040-97a4-11e6-9fe7-7abe22c5e826.png)

Could you try to reduce this to a reproducible test case, or similar?

``` python
class IndividuSerializer(ModelSerializer):
    # ...
    sexe_display = CharField(source='get_sexe_display', label='sexe', read_only=True)
```

The field `sexe` is defined in django model. And The method `get_sexe_display` is django's `_get_FIELD_display`. It's returned `<bound method curry.<locals>._curried of <Individu: XXX XXX>>`. 

`_curried(*moreargs, **morekwargs)` is defined in django.utils.functional

But In drf 'fields.py' line 62, method `is_simple_callable`, `param.default` is always `param.empty`.
[https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L62](url)


Resolving patch:
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -54,12 +54,17 @@ def is_simple_callable(obj):
         """
         True if the object is a callable that takes no arguments.
         """
-        if not callable(obj):
+        if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
             return False
 
         sig = inspect.signature(obj)
         params = sig.parameters.values()
-        return all(param.default != param.empty for param in params)
+        return all(
+            param.kind == param.VAR_POSITIONAL or
+            param.kind == param.VAR_KEYWORD or
+            param.default != param.empty
+            for param in params
+        )
 
 else:
     def is_simple_callable(obj):


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -37,6 +37,9 @@ def valid(self):
             def valid_kwargs(self, param='value'):
                 pass
 
+            def valid_vargs_kwargs(self, *args, **kwargs):
+                pass
+
             def invalid(self, param):
                 pass
 
@@ -45,11 +48,13 @@ def invalid(self, param):
         # unbound methods
         assert not is_simple_callable(Foo.valid)
         assert not is_simple_callable(Foo.valid_kwargs)
+        assert not is_simple_callable(Foo.valid_vargs_kwargs)
         assert not is_simple_callable(Foo.invalid)
 
         # bound methods
         assert is_simple_callable(Foo().valid)
         assert is_simple_callable(Foo().valid_kwargs)
+        assert is_simple_callable(Foo().valid_vargs_kwargs)
         assert not is_simple_callable(Foo().invalid)
 
     def test_function(self):
@@ -59,13 +64,31 @@ def simple():
         def valid(param='value', param2='value'):
             pass
 
+        def valid_vargs_kwargs(*args, **kwargs):
+            pass
+
         def invalid(param, param2='value'):
             pass
 
         assert is_simple_callable(simple)
         assert is_simple_callable(valid)
+        assert is_simple_callable(valid_vargs_kwargs)
         assert not is_simple_callable(invalid)
 
+    def test_4602_regression(self):
+        from django.db import models
+
+        class ChoiceModel(models.Model):
+            choice_field = models.CharField(
+                max_length=1, default='a',
+                choices=(('a', 'A'), ('b', 'B')),
+            )
+
+            class Meta:
+                app_label = 'tests'
+
+        assert is_simple_callable(ChoiceModel().get_choice_field_display)
+
     @unittest.skipUnless(typings, 'requires python 3.5')
     def test_type_annotation(self):
         # The annotation will otherwise raise a syntax error in python < 3.5