Repository: encode/django-rest-framework

Issue:
MultiTable Inherited Model Tests fail with Django 1.11a1
running `tox` on master I get (I don't have Python 3.4 installed):

```
ERROR:   py27-djangomaster: commands failed
...
ERROR:   py35-djangomaster: commands failed
```

For me Django master is at `74a575e`:  https://github.com/django/django/commit/74a575eb7296fb04e1fc2bd4e3f68dee3c66ee0a

SHA256 for the https://github.com/django/django/archive/master.tar.gz I'm seeing: `bc2874ca4e3bce55f528d4cd4fc9b36a5164313675ad534b8b900502ffe9f79d``

The failing tests are:

```
_________________________________ IntegrationTestFiltering.test_filter_with_queryset _________________________________
tests/test_filters.py:179: in test_filter_with_queryset
    self.assertEqual(response.data, expected_data)
E   AssertionError: [OrderedDict([('id', 3), ('text', 'ccc'), [72 chars]3)])] != [{'decimal': '2.25', 'date': '2012-10-04',[20 chars]: 3}]
_____________________________ IntegrationTestFiltering.test_get_filtered_class_root_view _____________________________
tests/test_filters.py:204: in test_get_filtered_class_root_view
    self.assertEqual(response.data, self.data)
E   AssertionError: [OrderedDict([('id', 1), ('text', 'aaa'), [1145 chars]0)])] != [{'decimal': '0.25', 'date': '2012-10-08',[624 chars] 10}]
____________________________ IntegrationTestFiltering.test_get_filtered_fields_root_view _____________________________
tests/test_filters.py:148: in test_get_filtered_fields_root_view
    self.assertEqual(response.data, self.data)
E   AssertionError: [OrderedDict([('id', 1), ('text', 'aaa'), [1145 chars]0)])] != [{'decimal': '0.25', 'date': '2012-10-08',[624 chars] 10}]
____________________________ IntegrationTestDetailFiltering.test_get_filtered_detail_view ____________________________
tests/test_filters.py:298: in test_get_filtered_detail_view
    self.assertEqual(response.data, data)
E   AssertionError: {'dec[26 chars]12-10-08', 'basefilterableitem_ptr': 1, 'text': 'aaa', 'id': 1} != {'dec[26 chars]12-10-08', 'text': 'aaa', 'id': 1}
_______________________ InheritedModelSerializationTests.test_data_is_valid_without_parent_ptr _______________________
tests/test_multitable_inheritance.py:71: in test_data_is_valid_without_parent_ptr
    self.assertEqual(serializer.is_valid(), True)
E   AssertionError: False != True
________________ InheritedModelSerializationTests.test_multitable_inherited_model_fields_as_expected _________________
tests/test_multitable_inheritance.py:48: in test_multitable_inherited_model_fields_as_expected
    set(['name1', 'name2', 'id']))
E   AssertionError: Items in the first set but not the second:
E   'parentmodel_ptr'
```



Discussion:
Indeed. Needs further investigation. We don't necessarily support running against Django master, as some bits of public & private API may change under our feet, but it's worth having these resolved in anticipation of 1.11.

Any further digging from anyone on this is most welcome.

btw, the django-filter backend is migrating to the django-filter package. Any fixes to `IntegrationTestFiltering` here should probably have a corresponding PR in django-filter.

To review as part of 3.5, depending on if we deprecate Django filter as part of that release or not.

As per #4648, this doesn't look like it's anything to do with Django Filter. 

It comes up combining Django master, Model Inheritance, ModelSerializer and `fields = '__all__'`: in this case we get an extra pointer to the the parent model in the serialiser's `data`. 

bd3fe75e introduced a test for this, which is now failing: 

```
______InheritedModelSerializationTests.test_data_is_valid_without_parent_ptr _________
tests/test_multitable_inheritance.py:71: in test_data_is_valid_without_parent_ptr
    self.assertEqual(serializer.is_valid(), True)
E   AssertionError: False != True
```

I think that's the key one. 


Resolving patch:
diff --git a/rest_framework/utils/model_meta.py b/rest_framework/utils/model_meta.py
--- a/rest_framework/utils/model_meta.py
+++ b/rest_framework/utils/model_meta.py
@@ -76,7 +76,12 @@ def _get_forward_relationships(opts):
     Returns an `OrderedDict` of field names to `RelationInfo`.
     """
     forward_relations = OrderedDict()
-    for field in [field for field in opts.fields if field.serialize and get_remote_field(field)]:
+    for field in [
+        field for field in opts.fields
+        if field.serialize and get_remote_field(field) and not (field.primary_key and field.one_to_one)
+        # If the field is a OneToOneField and it's been marked as PK, then this
+        # is a multi-table inheritance auto created PK ('%_ptr').
+    ]:
         forward_relations[field.name] = RelationInfo(
             model_field=field,
             related_model=get_related_model(field),


Test patch: