Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UserWarning: X is not compatible with schema generation: due to AnonymousUser #966

Closed
blueyed opened this issue Aug 13, 2018 · 7 comments
Closed

Comments

@blueyed
Copy link
Contributor

blueyed commented Aug 13, 2018

I am looking at the UserWarnings I've tried to enhance in #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
@carltongibson
Copy link
Owner

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.)

@gunthercox
Copy link

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(...)

@aaronstephenson
Copy link

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.

@ruhan
Copy link

ruhan commented Nov 27, 2020

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: axnsan12/drf-yasg#333

ivarnakken added a commit to webkom/lego that referenced this issue Jul 28, 2022
The ViewSets were not compatible with schema generation. django-filter raised UserWarnings. See carltongibson/django-filter#966
ivarnakken added a commit to webkom/lego that referenced this issue Jul 28, 2022
The ViewSets were not compatible with schema generation. django-filter raised UserWarnings. See carltongibson/django-filter#966
@pyaidev
Copy link

pyaidev commented Mar 25, 2023

def get_queryset(self):
    if getattr(self, "swagger_fake_view", False):
        return Event.objects.none()
    return Event.objects.exclude(slug=self.kwargs["slug"])
    
    
    
 Solved 

@KonstantinosPetrakis
Copy link

I wrote a decorator so DRY principle is followed when using this fix:

from django.db.models import QuerySet


def django_filter_warning(get_queryset_func):
    """
    This decorator is used to fix a warning in django-filter.
    See: https://github.com/carltongibson/django-filter/issues/966
    """

    def get_queryset(self):
        if getattr(self, "swagger_fake_view", False):
            return QuerySet()
        return get_queryset_func(self)

    return get_queryset

class MyCoolView:
    ...
    @django_filter_warning
    def get_queryset(self):
        """
        Returns reports that belong to the current user.
        """

        return self.request.user.reports.all()

@pyaidev

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants