Fonnae
Fonnae

Reputation: 523

Django REST: Exception Value: .filter_queryset() must be overridden

I tried to create a new installation of my codebase and am running into this issue. As best as possible, I have tried to verify that both installations have the same exact versions of all dependencies.

The issue only seems to strike on endpoints that access the database, although maybe that is just a coincidence and the issue is not at all DB related. (The DB is definitely functioning because the old install can still access it.)

Let me know if there is any other helpful info I can gather to help debug.

Traceback:
File "venv/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "venv/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)
File "venv/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
  87.             return self.dispatch(request, *args, **kwargs)
File "venv/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  466.             response = self.handle_exception(exc)
File "venv/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)
File "venv/lib/python2.7/site-packages/rest_framework/mixins.py" in retrieve
  56.         instance = self.get_object()
File "venv/lib/python2.7/site-packages/rest_framework/generics.py" in get_object
  84.         queryset = self.filter_queryset(self.get_queryset())
File "venv/lib/python2.7/site-packages/rest_framework/generics.py" in filter_queryset
  151.             queryset = backend().filter_queryset(self.request, queryset, self)
File "venv/lib/python2.7/site-packages/rest_framework/filters.py" in filter_queryset
  31.         raise NotImplementedError(".filter_queryset() must be overridden.")

Exception Type: NotImplementedError at /my/endpoint
Exception Value: .filter_queryset() must be overridden.

Here is my package list from pip list:

Package                            Version
---------------------------------- ----------
argcomplete                        0.8.1
asn1crypto                         0.24.0
backports.shutil-get-terminal-size 1.0.0
beautifulsoup4                     4.3.2
cffi                               1.11.5
cryptography                       2.3.1
Cython                             0.28.5
decorator                          4.3.0
Django                             1.8.4
django-cors-headers                1.1.0
django-filter                      0.11.0
djangorestframework                3.2.3
djangorestframework-jwt            1.7.1
dxpy                               0.161.0
enum34                             1.0.4
fusepy                             2.0.2
futures                            3.0.3
gunicorn                           19.3.0
idna                               2.0
impyla                             0.10.0
ipaddress                          1.0.14
ipdb                               0.11
ipython                            5.8.0
ipython-genutils                   0.2.0
kazoo                              2.2.1
Markdown                           2.6.2
MySQL-python                       1.2.5
ndg-httpsclient                    0.4.0
pathlib2                           2.3.2
pexpect                            4.6.0
pickleshare                        0.7.4
pip                                18.0
prompt-toolkit                     1.0.15
psutil                             2.1.3
ptyprocess                         0.6.0
pyasn1                             0.1.8
pycparser                          2.14
Pygments                           2.2.0
PyJWT                              1.4.0
pymssql                            2.2.0.dev0
pyodbc                             4.0.24
pyOpenSSL                          17.5.0
python-dateutil                    2.3
python-magic                       0.4.6
requests                           2.7.0
scandir                            1.9.0
setuptools                         40.0.0
simplegeneric                      0.8.1
six                                1.9.0
SQLAlchemy                         1.2.11
thrift                             0.9.2
traitlets                          4.3.2
wcwidth                            0.1.7
WebHDFS                            0.2.0
wheel                              0.24.0
ws4py                              0.3.2
xattr                              0.6.4

Here are my rest framework settings. I'm starting to think that the use of the BaseFilterBackend is the start of the issue. Seems like that class contains the filter_queryset() method that is not being overwritten:

REST_FRAMEWORK = {
     'DEFAULT_PERMISSION_CLASSES': (
         'rest_framework.permissions.IsAuthenticated',
     ),
     'DEFAULT_AUTHENTICATION_CLASSES': (
         'rest_framework.authentication.SessionAuthentication',
         'rest_framework.authentication.BasicAuthentication',
         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
     ),
     'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.BaseFilterBackend',),
     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
  }

EDIT: Here is the view causing the error:

 from rest_framework import permissions
 from rest_framework import renderers
 from rest_framework import viewsets, mixins
 from models import MyModel

 from rest_framework.response import Response

 from rest_framework.renderers import JSONRenderer
 from rest_framework.parsers import JSONParser

 from rest_framework import generics
 from rest_framework import filters

 import six

 class MyViewSet(viewsets.ModelViewSet):

     queryset = MyModel.objects.all()
     serializer_class = MyModelSerializer

     #Allows to filter using URL params and sorting
     filter_backends = (filters.BaseFilterBackend, filters.OrderingFilter)
     ordering = ('CreatedAt',)
     filter_fields = ('Modelfield1', 'Modelfield2',)

Upvotes: 3

Views: 1898

Answers (1)

Dmitry M
Dmitry M

Reputation: 440

In your settings, you've set DEFAULT_FILTER_BACKENDS' to ('rest_framework.filters.BaseFilterBackend',). Thus, BaseFilterBackend is being applied to most your views* and is throwing the NotImplementedError because BaseFilterBackend is a baseclass that is not actually intended to be applied directly -- only to be overridden by you or inherited by other filters. You should remove it from your defaults and anywhere else you're using it.

*Except the ones that manually specify their filters via filter_backends like you did in your sample view.

For example, the error can be resolved by replacing BaseFilterBackend with DjangoFilterBackend in the settings and in the view.

Upvotes: 1

Related Questions