django rest model-view-set list action raise 404 if pass query parameter

Viewed 301

if I pass any query parameter get 404

views.py

class BusinessViewSet(ModelViewSet):
    queryset = Business.objects.all()
    permission_classes = [IsAuthenticated, HasUsernamePermission]
    filter_backends = [SearchFilter, DjangoFilterBackend, DistanceFilterBackend]
    search_fields = ['username']
    ordering_fields = ['name']
    pagination_class = LimitOffsetPagination
    filterset_fields = ['name', 'category']

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return BusinessCreateSerializer
        return BusinessSerializer

urls.py

from rest_framework.routers import DefaultRouter

from businesses.api.views import BusinessViewSet

app_name = "businesses"
router = DefaultRouter()
router.register(r'', BusinessViewSet,basename="business")
urlpatterns = []
urlpatterns += router.urls

for example if i request

  • /api/businesses/ - response code is 200
  • /api/businesses/?search=a - response code is 404
3 Answers

Use the show_urls command for further checks if you have django_extensions.

It seems that you are using DjangoRestFramework default SearchFilter backend, hence you must add search_fields to the BusinessViewSet class.

Also, check the route from your browser to see if the form and its button (Filter button) are available and working or not.

DjangoRestFramework Search and Filter Form

The docs mention

The SearchFilter class will only be applied if the view has a search_fields attribute set.

As you don't have search_fields, SearchFilter is not used.

I debug my code and found my problem

HasUsernamePermission code

from rest_framework.permissions import BasePermission
from django.utils.translation import gettext_lazy as _
from django.urls import resolve


class HasUsernamePermission(BasePermission):
    """
    User must has username
    """
    message = _('User must has username')

    def has_permission(self, request, view):
        # Instance must have an attribute named `owner`.
        if resolve(request.get_full_path()).url_name == 'user-detail' \
                and request.method == 'PATCH':  # user probably set username
            return True
        return bool(request.user.username)

when you query params passed resolve method raise 404 exception I change my code to down blow and my problem has solved

class HasUsernamePermission(BasePermission):
"""
User must has username
"""
message = _('User must has username')

def has_permission(self, request, view):
    # Instance must have an attribute named `owner`.
    if view.__class__.__name__ == 'UserViewSet' and view.action == 'detail' and request.method == 'PATCH':  # user probably set username
        return True
    return bool(request.user.username)

thank you friends for your feedback on my question

Related