Repository: encode/django-rest-framework

Issue:
No friendly message about removal of filtersets emitted.
I'm getting the following backtrace since  3.5.2 was released.

 
```
mod_wsgi (pid=107917): Exception occurred processing WSGI script '/my_project/my_app/deploy/my_app.wsgi'.
Traceback (most recent call last):
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/Django-1.8-py2.7.egg/django/core/handlers/wsgi.py", line 170, in __call__
    self.load_middleware()
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/Django-1.8-py2.7.egg/django/core/handlers/base.py", line 52, in load_middleware
    mw_instance = mw_class()
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/Django-1.8-py2.7.egg/django/middleware/locale.py", line 24, in __init__
    for url_pattern in get_resolver(None).url_patterns:
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/Django-1.8-py2.7.egg/django/core/urlresolvers.py", line 402, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/Django-1.8-py2.7.egg/django/core/urlresolvers.py", line 396, in urlconf_module
    self._urlconf_module = import_module(self.urlconf_name)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "my_project/my_app/deploy/cgi/my_app/urls.py", line 7, in <module>
    from rest_framework import routers, serializers, viewsets
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/viewsets.py", line 26, in <module>
    from rest_framework import generics, mixins, views
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/generics.py", line 25, in <module>
    class GenericAPIView(views.APIView):
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/generics.py", line 44, in GenericAPIView
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/settings.py", line 220, in __getattr__
    val = perform_import(val, attr)
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/settings.py", line 165, in perform_import
    return [import_from_string(item, setting_name) for item in val]
  File "my_project/my_app/deploy/python-env/lib/python2.7/site-packages/djangorestframework-3.5.2-py2.7.egg/rest_framework/settings.py", line 181, in import_from_string
    raise ImportError(msg)
ImportError: Could not import 'rest_framework.filters.DjangoFilterBackend' for API setting 'DEFAULT_FILTER_BACKENDS'. ImportError: No module named rest_framework.filterset.
```
with 
```
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    ),
    'DEFAULT_RENDERER_CLASSES' : [
        'rest_framework.renderers.JSONRenderer',
    ],
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    )

}
```

My reading of #4620 is that this should be a friendly warning pointing be to the direct issue. Instead I had to dig through the diff of pip freeze outputs to trace it down. No worries it's done now. BVUt it might help other later if your warning appears . ;-).



Discussion:
:-/

Related: #4643

As is, 3.5.1+ are not compatible with code written for 3.5.0. I get that this was a bugfix (or did I understand something wrong ?) but 3.5.1 should really be called 4.0.0, and so on. Getting an ImportError because you depend on "djangorestframework>=3.5,<3.6" is really bad semver practice :(

It's not intentional. It's a bugfix causing a bug. We'll resolve it and issue a new release ASAP.


Resolving patch:
diff --git a/rest_framework/filters.py b/rest_framework/filters.py
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -38,31 +38,19 @@ def get_schema_fields(self, view):
 
 
 if django_filters:
-    from django_filters.filterset import FilterSetMetaclass as DFFilterSetMetaclass
     from django_filters.rest_framework.filterset import FilterSet as DFFilterSet
 
-    class FilterSetMetaclass(DFFilterSetMetaclass):
-        def __new__(cls, name, bases, attrs):
+    class FilterSet(DFFilterSet):
+        def __init__(self, *args, **kwargs):
             warnings.warn(
                 "The built in 'rest_framework.filters.FilterSet' is pending deprecation. "
                 "You should use 'django_filters.rest_framework.FilterSet' instead.",
                 PendingDeprecationWarning
             )
-            return super(FilterSetMetaclass, cls).__new__(cls, name, bases, attrs)
-    _BaseFilterSet = DFFilterSet
+            return super(FilterSet, self).__init__(*args, **kwargs)
 else:
-    # Dummy metaclass just so we can give a user-friendly error message.
-    class FilterSetMetaclass(type):
-        def __init__(self, name, bases, attrs):
-            # Assert only on subclasses, so we can define FilterSet below.
-            if bases != (object,):
-                assert False, 'django-filter must be installed to use the `FilterSet` class'
-            super(FilterSetMetaclass, self).__init__(name, bases, attrs)
-    _BaseFilterSet = object
-
-
-class FilterSet(six.with_metaclass(FilterSetMetaclass, _BaseFilterSet)):
-    pass
+    def FilterSet():
+        assert False, 'django-filter must be installed to use the `FilterSet` class'
 
 
 class DjangoFilterBackend(BaseFilterBackend):


Test patch: