Repository: encode/django-rest-framework

Issue:
More helpful error message when default `.create` fails.
If the default `.create` method on `ModelSerializer` fails with `TypeError` then it'll typically be because it's passed an incorrect parameter to the `MyModel.objects.create()` method. Eg.

```
TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
```

We should highlight this type of issue to users, and make it more obvious & easy to resolve.



Discussion:
Example case where this can happen... user creates a non-model field on the `ModelSerializer` class.


Resolving patch:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -34,6 +34,7 @@
 )
 import copy
 import inspect
+import sys
 import warnings
 
 # Note: We do the following so that users of the framework can use this style:
@@ -593,7 +594,18 @@ def create(self, validated_attrs):
             if relation_info.to_many and (field_name in validated_attrs):
                 many_to_many[field_name] = validated_attrs.pop(field_name)
 
-        instance = ModelClass.objects.create(**validated_attrs)
+        try:
+            instance = ModelClass.objects.create(**validated_attrs)
+        except TypeError as exc:
+            msg = (
+                'The mentioned argument might be a field on the serializer '
+                'that is not part of the model. You need to override the '
+                'create() method in your ModelSerializer subclass to support '
+                'this.')
+            six.reraise(
+                type(exc),
+                type(exc)(str(exc) + '. ' + msg),
+                sys.exc_info()[2])
 
         # Save many-to-many relationships after the instance is created.
         if many_to_many:


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
@@ -10,6 +10,7 @@
 from django.db import models
 from django.test import TestCase
 from rest_framework import serializers
+import pytest
 
 
 def dedent(blocktext):
@@ -26,6 +27,10 @@ class CustomField(models.Field):
     pass
 
 
+class OneFieldModel(models.Model):
+    char_field = models.CharField(max_length=100)
+
+
 class RegularFieldsModel(models.Model):
     """
     A model class for testing regular flat fields.
@@ -68,6 +73,29 @@ class FieldOptionsModel(models.Model):
     choices_field = models.CharField(max_length=100, choices=COLOR_CHOICES)
 
 
+class TestModelSerializer(TestCase):
+    def test_create_method(self):
+        class TestSerializer(serializers.ModelSerializer):
+            non_model_field = serializers.CharField()
+
+            class Meta:
+                model = OneFieldModel
+                fields = ('char_field', 'non_model_field')
+
+        serializer = TestSerializer(data={
+            'char_field': 'foo',
+            'non_model_field': 'bar',
+        })
+        serializer.is_valid()
+        with pytest.raises(TypeError):
+            serializer.save()
+
+        try:
+            serializer.save()
+        except TypeError as exc:
+            assert 'ModelSerializer' in str(exc)
+
+
 class TestRegularFieldMappings(TestCase):
     def test_regular_fields(self):
         """