Repository: carltongibson/django-filter

Issue:
FilterSetMetaclass: look for order_by_field in attrs
`filters[order_by_field]` might come from a parent class, and the
automatic ordering filter needs to take into account the current class
and its filters (for `order_by=True`).

If this is sensible there should be a test for it probably.



Discussion:

Resolving patch:
diff --git a/django_filters/filters.py b/django_filters/filters.py
--- a/django_filters/filters.py
+++ b/django_filters/filters.py
@@ -1,7 +1,6 @@
 from __future__ import absolute_import
 from __future__ import unicode_literals
 
-import warnings
 from collections import OrderedDict
 from datetime import timedelta
 
@@ -19,7 +18,7 @@
     Lookup, LookupTypeField, BaseCSVField, BaseRangeField, RangeField,
     DateRangeField, DateTimeRangeField, TimeRangeField, IsoDateTimeField
 )
-from .utils import deprecate, label_for_filter, pretty_name
+from .utils import label_for_filter, pretty_name
 
 
 __all__ = [
@@ -39,7 +38,6 @@
     'DurationFilter',
     'Filter',
     'IsoDateTimeFilter',
-    'MethodFilter',
     'ModelChoiceFilter',
     'ModelMultipleChoiceFilter',
     'MultipleChoiceFilter',
@@ -60,27 +58,16 @@
 EMPTY_VALUES = ([], (), {}, '', None)
 
 
-def _lookup_type_warning():
-    warnings.warn('lookup_type is deprecated. Use lookup_expr instead.', DeprecationWarning, stacklevel=3)
-
-
 class Filter(object):
     creation_counter = 0
     field_class = forms.Field
 
-    def __init__(self, name=None, label=None, widget=None, action=None, method=None,
-                 lookup_expr='exact', required=False, distinct=False, exclude=False, **kwargs):
+    def __init__(self, name=None, label=None, widget=None, method=None, lookup_expr='exact',
+                 required=False, distinct=False, exclude=False, **kwargs):
         self.name = name
         self.label = label
-        if action:
-            deprecate('Filter.action has been deprecated in favor of Filter.method')
-            self.filter = action
         self.method = method
-
         self.lookup_expr = lookup_expr
-        if 'lookup_type' in kwargs:
-            _lookup_type_warning()
-            self.lookup_expr = kwargs.pop('lookup_type')
 
         self.widget = widget
         self.required = required
@@ -119,18 +106,6 @@ def fset(self, value):
         return locals()
     method = property(**method())
 
-    def lookup_type():
-        def fget(self):
-            _lookup_type_warning()
-            return self.lookup_expr
-
-        def fset(self, value):
-            _lookup_type_warning()
-            self.lookup_expr = value
-
-        return locals()
-    lookup_type = property(**lookup_type())
-
     def label():
         def fget(self):
             if self._label is None and hasattr(self, 'parent'):
@@ -693,49 +668,6 @@ def build_choices(self, fields, labels):
         return [val for pair in zip(ascending, descending) for val in pair]
 
 
-class MethodFilter(Filter):
-    """
-    This filter will allow you to run a method that exists on the filterset class
-    """
-    def __init__(self, *args, **kwargs):
-        deprecate('MethodFilter has been deprecated in favor of Filter.method')
-
-        # Get the action out of the kwargs
-        action = kwargs.get('action', None)
-
-        # If the action is a string store the action and set the action to our own filter method
-        # so it can be backwards compatible and work as expected, the parent will still treat it as
-        # a filter that has an action
-        self.parent_action = ''
-        text_types = (str, six.text_type)
-        if type(action) in text_types:
-            self.parent_action = str(action)
-            kwargs.update({
-                'action': self.filter
-            })
-
-        # Call the parent
-        super(MethodFilter, self).__init__(*args, **kwargs)
-
-    def filter(self, qs, value):
-        """
-        This filter method will act as a proxy for the actual method we want to
-        call.
-
-        It will try to find the method on the parent filterset,
-        if not it attempts to search for the method `field_{{attribute_name}}`.
-        Otherwise it defaults to just returning the queryset.
-        """
-        parent = getattr(self, 'parent', None)
-        parent_filter_method = getattr(parent, self.parent_action, None)
-        if not parent_filter_method:
-            func_str = 'filter_{0}'.format(self.name)
-            parent_filter_method = getattr(parent, func_str, None)
-        if parent_filter_method is not None:
-            return parent_filter_method(qs, value)
-        return qs
-
-
 class FilterMethod(object):
     """
     This helper is used to override Filter.filter() when a 'method' argument
diff --git a/django_filters/filterset.py b/django_filters/filterset.py
--- a/django_filters/filterset.py
+++ b/django_filters/filterset.py
@@ -17,12 +17,8 @@
 from .constants import ALL_FIELDS, STRICTNESS
 from .filters import (Filter, CharFilter, BooleanFilter, BaseInFilter, BaseRangeFilter,
                       ChoiceFilter, DateFilter, DateTimeFilter, TimeFilter, ModelChoiceFilter,
-                      ModelMultipleChoiceFilter, NumberFilter, UUIDFilter,
-                      DurationFilter, OrderingFilter)
-from .utils import try_dbfield, get_all_model_fields, get_model_field, resolve_field, pretty_name, deprecate
-
-
-ORDER_BY_FIELD = 'o'
+                      ModelMultipleChoiceFilter, NumberFilter, UUIDFilter, DurationFilter)
+from .utils import try_dbfield, get_all_model_fields, get_model_field, resolve_field
 
 
 def get_declared_filters(bases, attrs, with_base_filters=True):
@@ -123,34 +119,12 @@ def all_valid(fieldset):
 
 class FilterSetOptions(object):
     def __init__(self, options=None):
-        if getattr(options, 'model', None) is not None:
-            if not hasattr(options, 'fields') and not hasattr(options, 'exclude'):
-                deprecate(
-                    "Not setting Meta.fields with Meta.model is undocumented behavior "
-                    "and may result in unintentionally exposing filter fields. This has "
-                    "been deprecated in favor of setting Meta.fields = '__all__' or by "
-                    "setting the Meta.exclude attribute.", 1)
-
-            elif getattr(options, 'fields', -1) is None:
-                deprecate(
-                    "Setting 'Meta.fields = None' is undocumented behavior and has been "
-                    "deprecated in favor of Meta.fields = '__all__'.", 1)
-
         self.model = getattr(options, 'model', None)
         self.fields = getattr(options, 'fields', None)
         self.exclude = getattr(options, 'exclude', None)
 
         self.filter_overrides = getattr(options, 'filter_overrides', {})
 
-        if hasattr(options, 'order_by'):
-            deprecate('Meta.order_by has been deprecated.', 1)
-
-        if hasattr(options, 'order_by_field'):
-            deprecate('Meta.order_by_field has been deprecated.', 1)
-
-        self.order_by = getattr(options, 'order_by', False)
-        self.order_by_field = getattr(options, 'order_by_field', ORDER_BY_FIELD)
-
         self.strict = getattr(options, 'strict', None)
 
         self.form = getattr(options, 'form', forms.Form)
@@ -175,29 +149,7 @@ def __new__(cls, name, bases, attrs):
         opts = new_class._meta = FilterSetOptions(
             getattr(new_class, 'Meta', None))
 
-        if hasattr(new_class, 'strict'):
-            deprecate('strict has been deprecated. Use Meta.strict instead.')
-            new_class._meta.strict = new_class.strict
-
-        if hasattr(new_class, 'order_by_field'):
-            deprecate('order_by_field has been moved to the Meta class.')
-            new_class._meta.order_by_field = new_class.order_by_field
-
-        if hasattr(new_class, 'filter_overrides'):
-            deprecate('filter_overrides has been moved to the Meta class.')
-            new_class._meta.filter_overrides = new_class.filter_overrides
-
-        assert not hasattr(new_class, 'get_order_by'), \
-            'get_order_by() has been deprecated. Subclass OrderingFilter and override .filter() instead. ' \
-            'See: https://django-filter.readthedocs.io/en/latest/migration.html"'
-
-        assert not hasattr(new_class, 'get_ordering_field'), \
-            'get_ordering_field() has been deprecated. Use OrderingFilter instead. ' \
-            'See: https://django-filter.readthedocs.io/en/latest/migration.html"'
-
-        # TODO: replace with deprecations
-        # if opts.model and opts.fields:
-        if opts.model:
+        if opts.model and (opts.fields is not None or opts.exclude is not None):
             filters = new_class.filters_for_model(opts.model, opts)
             filters.update(declared_filters)
         else:
@@ -208,12 +160,6 @@ def __new__(cls, name, bases, attrs):
             raise TypeError("Meta.fields contains a field that isn't defined "
                             "on this FilterSet: {}".format(not_defined))
 
-        # TODO: remove with deprecations
-        # check key existence instead of setdefault - prevents unnecessary filter construction
-        order_by_field = new_class._meta.order_by_field
-        if opts.order_by and order_by_field not in filters:
-            filters[order_by_field] = new_class.get_ordering_filter(opts, filters)
-
         new_class.declared_filters = declared_filters
         new_class.base_filters = filters
         return new_class
@@ -297,23 +243,6 @@ def __init__(self, data=None, queryset=None, prefix=None, strict=None, request=N
         for filter_key, filter_ in six.iteritems(self.filters):
             filter_.parent = self
 
-    def __iter__(self):
-        deprecate('QuerySet methods are no longer proxied.')
-        for obj in self.qs:
-            yield obj
-
-    def __len__(self):
-        deprecate('QuerySet methods are no longer proxied.')
-        return self.qs.count()
-
-    def __getitem__(self, key):
-        deprecate('QuerySet methods are no longer proxied.')
-        return self.qs[key]
-
-    def count(self):
-        deprecate('QuerySet methods are no longer proxied.')
-        return self.qs.count()
-
     @property
     def qs(self):
         if not hasattr(self, '_qs'):
@@ -358,60 +287,10 @@ def form(self):
                 self._form = Form(prefix=self.form_prefix)
         return self._form
 
-    @classmethod
-    def get_ordering_filter(cls, opts, filters):
-        assert not isinstance(opts.fields, dict), \
-            "'order_by' is not compatible with the 'fields' dict syntax. Use OrderingFilter instead."
-
-        def display_text(name, fltr):
-            """
-            ``name`` is the filter's attribute name on the FilterSet
-            ``text`` is the current display text, which is either the ``name``
-                     or an explicitly assigned label.
-            """
-            # TODO: use `fltr._label` in label-improvements branch
-            text = fltr.label or name.lstrip('-')
-            if name.startswith('-'):
-                text = _('%s (descending)' % text)
-
-            return pretty_name(text)
-
-        if isinstance(opts.order_by, (list, tuple)):
-
-            # e.g. (('field', 'Display name'), ...)
-            if isinstance(opts.order_by[0], (list, tuple)):
-                choices = [(f[0], f[1]) for f in opts.order_by]
-                fields = {filters.get(f[0].lstrip('-')).name: f[0] for f in opts.order_by}
-                return OrderingFilter(choices=choices, fields=fields, empty_label=None)
-
-            # e.g. ('field1', 'field2', ...)
-            else:
-                # (filter name, filter instance)
-                order_by = [(f, filters.get(f.lstrip('-'))) for f in opts.order_by]
-
-                # preference filter label over attribute name
-                choices = [(f, display_text(f, fltr)) for f, fltr in order_by]
-                fields = {fltr.name: f for f, fltr in order_by}
-                return OrderingFilter(choices=choices, fields=fields, empty_label=None)
-
-        # opts.order_by = True
-        order_by = filters.items()
-
-        fields = [(fltr.name, f) for f, fltr in order_by]
-        labels = {f: display_text(f, fltr) for f, fltr in order_by}
-        return OrderingFilter(fields=fields, field_labels=labels, empty_label=None)
-
     @classmethod
     def filters_for_model(cls, model, opts):
-        # TODO: remove with deprecations - this emulates the old behavior
-        fields = opts.fields
-        if fields is None:
-            DEFAULTS = dict(FILTER_FOR_DBFIELD_DEFAULTS)
-            DEFAULTS.update(opts.filter_overrides)
-            fields = get_all_model_fields(model, field_types=DEFAULTS.keys())
-
         return filters_for_model(
-            model, fields, opts.exclude,
+            model, opts.fields, opts.exclude,
             cls.filter_for_field,
             cls.filter_for_reverse_field
         )
diff --git a/django_filters/utils.py b/django_filters/utils.py
--- a/django_filters/utils.py
+++ b/django_filters/utils.py
@@ -46,18 +46,9 @@ def try_dbfield(fn, field_class):
             return data
 
 
-# TODO: remove field_types arg with deprecations
-def get_all_model_fields(model, field_types=None):
+def get_all_model_fields(model):
     opts = model._meta
 
-    if field_types is not None:
-        return [
-            f.name for f in sorted(opts.fields + opts.many_to_many)
-            if not isinstance(f, models.AutoField) and
-            not (getattr(remote_field(f), 'parent_link', False)) and
-            f.__class__ in field_types
-        ]
-
     return [
         f.name for f in sorted(opts.fields + opts.many_to_many)
         if not isinstance(f, models.AutoField) and


Test patch:
diff --git a/tests/test_deprecations.py b/tests/test_deprecations.py
deleted file mode 100644
--- a/tests/test_deprecations.py
+++ /dev/null
@@ -1,717 +0,0 @@
-
-import functools
-import warnings
-import mock
-from django.core.exceptions import ValidationError
-from django.test import TestCase, override_settings
-
-from django_filters import FilterSet
-from django_filters.conf import Settings
-from django_filters.filters import Filter, CharFilter, MethodFilter
-from django_filters.filterset import STRICTNESS
-from .models import User
-from .models import NetworkSetting
-from .models import SubnetMaskField
-
-
-def silence(f):
-    @functools.wraps(f)
-    def wrapped(*args, **kwargs):
-        with warnings.catch_warnings(record=True):
-            warnings.simplefilter("always")
-            f(*args, **kwargs)
-
-    return wrapped
-
-
-class UserFilter(FilterSet):
-    class Meta:
-        model = User
-        fields = '__all__'
-
-
-class FilterSetContainerDeprecationTests(TestCase):
-
-    def test__iter__notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            [obj for obj in UserFilter()]
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test__getitem__notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            with self.assertRaises(IndexError):
-                UserFilter()[0]
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test__len__notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            len(UserFilter())
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test__count__notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            UserFilter().count()
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-
-class MethodFilterDeprecationTests(TestCase):
-
-    def test_notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                username = MethodFilter()
-
-                class Meta:
-                    model = User
-                    fields = []
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    # old tests
-    @silence
-    def test_filtering(self):
-        User.objects.create(username='alex')
-        User.objects.create(username='jacob')
-        User.objects.create(username='aaron')
-
-        class F(FilterSet):
-            username = MethodFilter(action='filter_username')
-
-            class Meta:
-                model = User
-                fields = ['username']
-
-            def filter_username(self, queryset, value):
-                return queryset.filter(
-                    username=value
-                )
-
-        self.assertEqual(list(F().qs), list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'alex'}).qs),
-                         [User.objects.get(username='alex')])
-        self.assertEqual(list(F({'username': 'jose'}).qs),
-                         list())
-
-    @silence
-    def test_filtering_external(self):
-        User.objects.create(username='alex')
-        User.objects.create(username='jacob')
-        User.objects.create(username='aaron')
-
-        def filter_username(queryset, value):
-            return queryset.filter(
-                username=value
-            )
-
-        class F(FilterSet):
-            username = MethodFilter(action=filter_username)
-
-            class Meta:
-                model = User
-                fields = ['username']
-
-        self.assertEqual(list(F().qs), list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'alex'}).qs),
-                         [User.objects.get(username='alex')])
-        self.assertEqual(list(F({'username': 'jose'}).qs),
-                         list())
-
-    @silence
-    def test_filtering_default_attribute_action(self):
-        User.objects.create(username='mike')
-        User.objects.create(username='jake')
-        User.objects.create(username='aaron')
-
-        class F(FilterSet):
-            username = MethodFilter()
-
-            class Meta:
-                model = User
-                fields = ['username']
-
-            def filter_username(self, queryset, value):
-                return queryset.filter(
-                    username__contains='ke'
-                )
-
-        self.assertEqual(list(F().qs), list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'mike'}).qs),
-                         [User.objects.get(username='mike'),
-                          User.objects.get(username='jake')],)
-        self.assertEqual(list(F({'username': 'jake'}).qs),
-                         [User.objects.get(username='mike'),
-                          User.objects.get(username='jake')])
-        self.assertEqual(list(F({'username': 'aaron'}).qs),
-                         [User.objects.get(username='mike'),
-                          User.objects.get(username='jake')])
-
-    @silence
-    def test_filtering_default(self):
-        User.objects.create(username='mike')
-        User.objects.create(username='jake')
-        User.objects.create(username='aaron')
-
-        class F(FilterSet):
-            username = MethodFilter()
-            email = MethodFilter()
-
-            class Meta:
-                model = User
-                fields = ['username']
-
-        self.assertEqual(list(F().qs), list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'mike'}).qs),
-                         list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'jake'}).qs),
-                         list(User.objects.all()))
-        self.assertEqual(list(F({'username': 'aaron'}).qs),
-                         list(User.objects.all()))
-
-
-class FilterActionDeprecationTests(TestCase):
-
-    def test_notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                username = CharFilter(action=lambda x: x)
-
-                class Meta:
-                    model = User
-                    fields = []
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_filter_using_action(self):
-        qs = mock.NonCallableMock(spec=[])
-        action = mock.Mock(spec=['filter'])
-
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            f = Filter(action=action)
-            result = f.filter(qs, 'value')
-            action.assert_called_once_with(qs, 'value')
-            self.assertNotEqual(qs, result)
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_filtering_with_action(self):
-        User.objects.create(username='alex', status=1)
-        User.objects.create(username='jacob', status=2)
-        User.objects.create(username='aaron', status=2)
-        User.objects.create(username='carl', status=0)
-
-        with warnings.catch_warnings(record=True):
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                username = CharFilter(action=lambda qs, value: (
-                    qs.filter(**{'username__startswith': value})
-                ))
-
-                class Meta:
-                    model = User
-                    fields = ['username']
-
-        f = F({'username': 'a'}, queryset=User.objects.all())
-        self.assertQuerysetEqual(
-            f.qs, ['alex', 'aaron'], lambda o: o.username, False)
-
-
-class FilterSetMetaDeprecationTests(TestCase):
-    def test_fields_not_set(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                class Meta:
-                    model = User
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-            self.assertIn("Not setting Meta.fields with Meta.model is undocumented behavior", str(w[-1].message))
-
-    def test_fields_is_none(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                class Meta:
-                    model = User
-                    fields = None
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-            self.assertIn("Setting 'Meta.fields = None' is undocumented behavior", str(w[-1].message))
-
-    def test_fields_not_set_ignore_unknown(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                class Meta:
-                    model = NetworkSetting
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-            self.assertIn("Not setting Meta.fields with Meta.model is undocumented behavior", str(w[-1].message))
-
-        self.assertNotIn('mask', F.base_filters.keys())
-
-    def test_fields_not_set_with_override(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-
-                class Meta:
-                    model = NetworkSetting
-                    filter_overrides = {
-                        SubnetMaskField: {'filter_class': CharFilter},
-                    }
-
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-            self.assertIn("Not setting Meta.fields with Meta.model is undocumented behavior", str(w[-1].message))
-
-        self.assertEqual(list(F.base_filters.keys()), ['ip', 'mask'])
-
-
-class StrictnessDeprecationTests(TestCase):
-    def test_notification(self):
-
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                strict = False
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_passthrough(self):
-        with warnings.catch_warnings(record=True):
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                strict = False
-
-            self.assertEqual(F._meta.strict, False)
-
-
-class FilterOverridesDeprecationTests(TestCase):
-
-    def test_notification(self):
-
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                filter_overrides = {}
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_passthrough(self):
-        with warnings.catch_warnings(record=True):
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                filter_overrides = {
-                    SubnetMaskField: {'filter_class': CharFilter},
-                }
-
-                class Meta:
-                    model = NetworkSetting
-                    fields = '__all__'
-
-        self.assertDictEqual(F._meta.filter_overrides, {
-            SubnetMaskField: {'filter_class': CharFilter},
-        })
-
-        self.assertEqual(list(F.base_filters.keys()), ['ip', 'mask'])
-
-
-class OrderByFieldDeprecationTests(TestCase):
-    def test_notification(self):
-
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                order_by_field = 'field'
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_passthrough(self):
-        with warnings.catch_warnings(record=True):
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                order_by_field = 'field'
-
-            self.assertEqual(F._meta.order_by_field, 'field')
-
-
-class OrderByDeprecationTests(TestCase):
-    def test_order_by_notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                class Meta:
-                    order_by = True
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_order_by_field_notification(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            class F(FilterSet):
-                class Meta:
-                    order_by_field = 'field'
-
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
-    def test_get_order_by_assertion(self):
-        with self.assertRaises(AssertionError):
-            class F(FilterSet):
-                def get_order_by(self):
-                    pass
-
-    def test_get_ordering_field_assertion(self):
-        with self.assertRaises(AssertionError):
-            class F(FilterSet):
-                def get_ordering_field(self):
-                    pass
-
-
-class DeprecatedOrderingFilterSetTests(TestCase):
-    def setUp(self):
-        self.alex = User.objects.create(username='alex', status=1)
-        self.jacob = User.objects.create(username='jacob', status=2)
-        self.aaron = User.objects.create(username='aaron', status=2)
-        self.carl = User.objects.create(username='carl', status=0)
-        self.qs = User.objects.all().order_by('id')
-
-    # old filterset tests
-    @silence
-    def test_ordering(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['username', 'status']
-
-        f = F({'o': 'username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['aaron', 'alex', 'carl', 'jacob'], lambda o: o.username)
-
-        f = F({'o': 'status'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['carl', 'alex', 'jacob', 'aaron'], lambda o: o.username)
-
-    @silence
-    def test_ordering_on_unknown_value(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-
-        f = F({'o': 'username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, [], lambda o: o.username)
-
-    @silence
-    def test_ordering_on_unknown_value_results_in_default_ordering_without_strict(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-                strict = STRICTNESS.IGNORE
-
-        f = F({'o': 'username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['alex', 'jacob', 'aaron', 'carl'], lambda o: o.username)
-
-    @silence
-    def test_ordering_on_unknown_value_results_in_default_ordering_with_strict_raise(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-                strict = STRICTNESS.RAISE_VALIDATION_ERROR
-
-        f = F({'o': 'username'}, queryset=self.qs)
-        with self.assertRaises(ValidationError) as excinfo:
-            f.qs.all()
-        self.assertEqual(excinfo.exception.message_dict,
-                         {'o': ['Select a valid choice. username is not one '
-                                'of the available choices.']})
-
-        # No default order_by should get applied.
-        f = F({}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['alex', 'jacob', 'aaron', 'carl'], lambda o: o.username)
-
-    @silence
-    def test_ordering_on_different_field(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = True
-
-        f = F({'o': 'username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['aaron', 'alex', 'carl', 'jacob'], lambda o: o.username)
-
-        f = F({'o': 'status'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['carl', 'alex', 'jacob', 'aaron'], lambda o: o.username)
-
-    @silence
-    def test_ordering_uses_filter_name(self):
-        class F(FilterSet):
-            account = CharFilter(name='username')
-
-            class Meta:
-                model = User
-                fields = ['account', 'status']
-                order_by = True
-
-        f = F({'o': 'account'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['aaron', 'alex', 'carl', 'jacob'], lambda o: o.username)
-
-    @silence
-    def test_reverted_ordering_uses_filter_name(self):
-        class F(FilterSet):
-            account = CharFilter(name='username')
-
-            class Meta:
-                model = User
-                fields = ['account', 'status']
-                order_by = True
-
-        f = F({'o': '-account'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['jacob', 'carl', 'alex', 'aaron'], lambda o: o.username)
-
-    @silence
-    def test_ordering_with_overridden_field_name(self):
-        """
-        Set the `order_by_field` on the filterset and ensure that the
-        field name is respected.
-        """
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-                order_by_field = 'order'
-
-        f = F({'order': 'status'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['carl', 'alex', 'jacob', 'aaron'], lambda o: o.username)
-
-    @silence
-    def test_ordering_descending_set(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['username', '-username']
-
-        f = F({'o': '-username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['jacob', 'carl', 'alex', 'aaron'], lambda o: o.username)
-
-    @silence
-    def test_ordering_descending_unset(self):
-        """ Test ordering descending works when order_by=True. """
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = True
-
-        f = F({'o': '-username'}, queryset=self.qs)
-        self.assertQuerysetEqual(
-            f.qs, ['jacob', 'carl', 'alex', 'aaron'], lambda o: o.username)
-
-
-class DeprecatedOrderingFormTests(TestCase):
-    @silence
-    def test_ordering(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-
-        f = F().form
-        self.assertEqual(len(f.fields), 3)
-        self.assertIn('o', f.fields)
-        self.assertEqual(f.fields['o'].choices, [('status', 'Status')])
-
-    @silence
-    def test_ordering_uses_all_fields(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = True
-
-        f = F().form
-        self.assertEqual(f.fields['o'].choices, [
-            ('username', 'Username'),
-            ('-username', 'Username (descending)'),
-            ('status', 'Status'),
-            ('-status', 'Status (descending)')])
-
-    @silence
-    def test_ordering_uses_filter_label(self):
-        class F(FilterSet):
-            username = CharFilter(label='Account')
-
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = True
-
-        f = F().form
-        self.assertEqual(f.fields['o'].choices, [
-            ('username', 'Account'),
-            ('-username', 'Account (descending)'),
-            ('status', 'Status'),
-            ('-status', 'Status (descending)')])
-
-    @silence
-    def test_ordering_uses_explicit_filter_name(self):
-        class F(FilterSet):
-            account = CharFilter(name='username')
-
-            class Meta:
-                model = User
-                fields = ['account', 'status']
-                order_by = True
-
-        f = F().form
-        self.assertEqual(f.fields['o'].choices, [
-            ('account', 'Account'),
-            ('-account', 'Account (descending)'),
-            ('status', 'Status'),
-            ('-status', 'Status (descending)')])
-
-    @silence
-    def test_ordering_with_overridden_field_name(self):
-        """
-        Set the `order_by_field` on the filterset and ensure that the
-        field name is respected.
-        """
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status']
-                order_by_field = 'order'
-
-        f = F().form
-        self.assertNotIn('o', f.fields)
-        self.assertIn('order', f.fields)
-        self.assertEqual(f.fields['order'].choices, [('status', 'Status')])
-
-    @silence
-    def test_ordering_with_overridden_field_name_and_descending(self):
-        """
-        Set the `order_by_field` on the filterset and ensure that the
-        field name is respected.
-        """
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = ['status', '-status']
-                order_by_field = 'order'
-
-        f = F().form
-        self.assertNotIn('o', f.fields)
-        self.assertIn('order', f.fields)
-        self.assertEqual(f.fields['order'].choices, [('status', 'Status'), ('-status', 'Status (descending)')])
-
-    @silence
-    def test_ordering_with_overridden_field_name_and_using_all_fields(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = True
-                order_by_field = 'order'
-
-        f = F().form
-        self.assertIn('order', f.fields)
-        self.assertEqual(f.fields['order'].choices, [
-            ('username', 'Username'),
-            ('-username', 'Username (descending)'),
-            ('status', 'Status'),
-            ('-status', 'Status (descending)')])
-
-    @silence
-    def test_ordering_with_custom_display_names(self):
-        class F(FilterSet):
-            class Meta:
-                model = User
-                fields = ['username', 'status']
-                order_by = [('status', 'Current status')]
-
-        f = F().form
-        self.assertEqual(
-            f.fields['o'].choices, [('status', 'Current status')])
-
-
-class DeprecatedSettingsTests(TestCase):
-
-    def test_filter_help_text(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            with override_settings(FILTERS_HELP_TEXT_FILTER=False):
-                Settings()
-
-        self.assertEqual(len(w), 1)
-        self.assertIn("The 'FILTERS_HELP_TEXT_FILTER' setting has been deprecated.", str(w[0].message))
-
-    def test_exclude_help_text(self):
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-
-            with override_settings(FILTERS_HELP_TEXT_EXCLUDE=False):
-                Settings()
-
-        self.assertEqual(len(w), 1)
-        self.assertIn("The 'FILTERS_HELP_TEXT_EXCLUDE' setting has been deprecated.", str(w[0].message))
diff --git a/tests/test_filters.py b/tests/test_filters.py
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -5,7 +5,6 @@
 from datetime import date, time, timedelta, datetime
 import inspect
 import mock
-import warnings
 
 from django import forms
 from django.test import TestCase, override_settings
@@ -213,16 +212,6 @@ def test_filtering_uses_distinct(self):
         result = qs.distinct.assert_called_once_with()
         self.assertNotEqual(qs, result)
 
-    def test_lookup_type_deprecation(self):
-        """
-        Make sure user is alerted when using deprecated ``lookup_type``.
-        """
-        with warnings.catch_warnings(record=True) as w:
-            warnings.simplefilter("always")
-            Filter(lookup_type='exact')
-            self.assertEqual(len(w), 1)
-            self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
-
 
 class CustomFilterWithBooleanCheckTests(TestCase):
 
diff --git a/tests/test_filterset.py b/tests/test_filterset.py
--- a/tests/test_filterset.py
+++ b/tests/test_filterset.py
@@ -321,6 +321,38 @@ class Meta:
         self.assertListEqual(list(F.base_filters),
                              ['title', 'price', 'average_rating'])
 
+    def test_model_no_fields_or_exclude(self):
+        class F(FilterSet):
+            class Meta:
+                model = Book
+
+        self.assertEqual(len(F.declared_filters), 0)
+        self.assertEqual(len(F.base_filters), 0)
+        self.assertListEqual(list(F.base_filters), [])
+
+    def test_model_exclude_is_none(self):
+        # equivalent to unset fields/exclude
+        class F(FilterSet):
+            class Meta:
+                model = Book
+                exclude = None
+
+        self.assertEqual(len(F.declared_filters), 0)
+        self.assertEqual(len(F.base_filters), 0)
+        self.assertListEqual(list(F.base_filters), [])
+
+    def test_model_exclude_empty(self):
+        # equivalent to fields = '__all__'
+        class F(FilterSet):
+            class Meta:
+                model = Book
+                exclude = []
+
+        self.assertEqual(len(F.declared_filters), 0)
+        self.assertEqual(len(F.base_filters), 3)
+        self.assertListEqual(list(F.base_filters),
+                             ['title', 'price', 'average_rating'])
+
     def test_declared_and_model_derived(self):
         class F(FilterSet):
             username = CharFilter()
@@ -785,7 +817,6 @@ class TestFilter(Filter):
         self.assertIs(f.filter, TestFilter.filter)
 
 
-@unittest.skip('TODO: remove when relevant deprecations have been completed')
 class MiscFilterSetTests(TestCase):
 
     def test_no__getitem__(self):