Django-filter: UserWarning: X is not compatible with schema generation: due to AnonymousUser

Created on 13 Aug 2018  ·  4Comments  ·  Source: carltongibson/django-filter

I am looking at the UserWarnings I've tried to enhance in https://github.com/carltongibson/django-filter/pull/903 again:

…/django-filter/django_filters/rest_framework/backends.py:131: UserWarning: <class 'project.app.views.TermsOfServiceViewSet'> is not compatible with schema generation
  "{} is not compatible with schema generation".format(view.__class__)

Those happen mostly because an AnonymousUser is used, which is not compatible with most of our view's get_queryset() methods, which assume that the user is authenticated (and has certain methods in particular).

I am using drf_yasg here.

I wonder if there is a way to improve this, e.g. by using an authenticated user for it (would be a drf-yasg issue then probably).

Traceback:

../../../Vcs/django-rest-framework/rest_framework/views.py:480: in dispatch
    response = handler(request, *args, **kwargs)
.venv/lib/python3.6/site-packages/drf_yasg/views.py:85: in get
    schema = generator.get_schema(request, self.public)
.venv/lib/python3.6/site-packages/drf_yasg/generators.py:215: in get_schema
    paths, prefix = self.get_paths(endpoints, components, request, public)
.venv/lib/python3.6/site-packages/drf_yasg/generators.py:337: in get_paths
    operation = self.get_operation(view, path, prefix, method, components, request)
.venv/lib/python3.6/site-packages/drf_yasg/generators.py:379: in get_operation
    operation = view_inspector.get_operation(operation_keys)
.venv/lib/python3.6/site-packages/drf_yasg/inspectors/view.py:30: in get_operation
    query = self.get_query_parameters()
.venv/lib/python3.6/site-packages/drf_yasg/inspectors/view.py:293: in get_query_parameters
    natural_parameters = self.get_filter_parameters() + self.get_pagination_parameters()
.venv/lib/python3.6/site-packages/drf_yasg/inspectors/base.py:336: in get_filter_parameters
    fields += self.probe_inspectors(self.filter_inspectors, 'get_filter_parameters', filter_backend()) or []
.venv/lib/python3.6/site-packages/drf_yasg/inspectors/base.py:71: in probe_inspectors
    result = method(obj, **kwargs)
.venv/lib/python3.6/site-packages/drf_yasg/inspectors/query.py:27: in get_filter_parameters
    fields = filter_backend.get_schema_fields(self.view)
../../../Vcs/django-filter/django_filters/rest_framework/backends.py:131: in get_schema_fields
    "{} is not compatible with schema generation".format(view.__class__)
E   UserWarning: <class 'project.app.views.AffiliationViewSet'> is not compatible with schema generation

Most helpful comment

One possible workaround might be to define something like this in the get_queryset method of your viewset. Handling the case where self.request is None seems to do the trick.

def get_queryset(self):
    if self.request is None:
        return SomeModel.objects.none()

    return SomeModel.objects.filter(...)

All 4 comments

Not much we can do here. Any method needing to call get_queryset() is going to run into this. You basically need to allow that to handle the anonymous case.

Either way the issue is better addressed as part of DRF's introspection logic. (But there's not a simple answer there yet either.)

One possible workaround might be to define something like this in the get_queryset method of your viewset. Handling the case where self.request is None seems to do the trick.

def get_queryset(self):
    if self.request is None:
        return SomeModel.objects.none()

    return SomeModel.objects.filter(...)

Thanks @gunthercox your comment really helped me out. It put me on the path to the solution, but ultimately what worked for me was this:

queryset = MyModel.objects.all()

def get_queryset(self):
    if not self.request:
        return MyModel.objects.none()

    if self.request.query_params:
        queryset = self.filter_queryset(self.queryset)
    else:
        queryset = self.queryset

    # ... the rest of the method code ...

    return queryset

Hope this helps someone else in a similar situation.

I think that the suggested approach is this one:

def get_queryset(self):
    if getattr(self, "swagger_fake_view", False):
        return MyModel.objects.none()

    # ... the rest of the method code ...

I've seen that in this thread: https://github.com/axnsan12/drf-yasg/issues/333

Was this page helpful?
0 / 5 - 0 ratings

Related issues

csarcom picture csarcom  ·  3Comments

xtrinch picture xtrinch  ·  4Comments

madelyneriksen picture madelyneriksen  ·  4Comments

Alexx-G picture Alexx-G  ·  4Comments

lalzada picture lalzada  ·  3Comments