Test RequestFactory and Client don't have query_params

Hey everyone, I’ve been using Django DRF and I’m facing some issues creating unit tests to make sure my pagination is working properly.

I tried using the RequestFactory and the Client to generate a request to pass to the pagination function but the requests created don’t come with a query_params making the unit-tests fail.

from django.test import TestCase
from django.test.client import Client
from django.contrib.sessions.middleware import SessionMiddleware
from rest_framework.test import APIRequestFactory, APIClient
from rest_framework.authtoken.models import Token


from trends.common.pagination import StandardPagination

class StandardPaginationTestCase(TestCase):
    def setUp(self):
        self.pagination = StandardPagination()
        self.factory = APIRequestFactory()

    def test_pagination(self):
        # Create a request

        request = self.factory.get("/query", query_params={"page": 1, "page_size": 10})

        # Create a dummy queryset
        queryset = [
            "item1",
            "item2",
            "item3",
            "item4",
            "item5",
            "item6",
            "item7",
            "item8",
            "item9",
            "item10",
        ]

        # Paginate the queryset
        paginated_queryset = self.pagination.paginate_queryset(queryset, request)

        # Check if pagination is working correctly
        self.assertEqual(len(paginated_queryset), 10)
        self.assertEqual(paginated_queryset[0], "item1")

Error:

Traceback (most recent call last):
  File "/var/lib/trends_backend/tests/common/test_pagination.py", line 37, in test_pagination
    paginated_queryset = self.pagination.paginate_queryset(queryset, request)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rest_framework/pagination.py", line 204, in paginate_queryset
    page_size = self.get_page_size(request)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rest_framework/pagination.py", line 270, in get_page_size
    request.query_params[self.page_size_query_param],
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'WSGIRequest' object has no attribute 'query_params'
from rest_framework.pagination import PageNumberPagination


class StandardPagination(PageNumberPagination):
    page_size_query_param = "page_size"
    max_page_size = 100
    page_size = 10

I tried a bunch of different things adding a Session Middleware, using the default Client and RequestFactory functions instead of DRF ones but nothing worked

Yeah, it’s a bit weird, it’s named data. The same name that you use on a POST request.

So this…

can be replaced with…
request = self.factory.get("/query", data={"page": 1, "page_size": 10})

I forgot to mention that I tested that as well and it didn’t work

Well, looking into the source code from the 5.0 release it should be working.
(I don’t know which version of django you’re using)

Yup, version 5.0.4 here. I don’t know why I’m getting this error

Django==5.0.4
django-cors-headers==4.3.1
djangorestframework==3.15.1

I added some extra pieces of code to the topic, imports and Pagination class

I see that you’re using APIRequestFactory, it would be good to take a look into this piece of the DRF’s source code then

Yup, I tried using both APIRequestFactory and RequestFactory, as well as APIClient and Client.
I also tried using QUERY_STRING, query_params and data but none worked. :smiling_face_with_tear:

So I got no idea what to do now

Maybe try to put the query string directly into the url?
Like:
request = self.factory.get("/query?page=1&page_size=10")

Tried that as well, still getting the error

Well, in this case, i would triple check my (yours) setup and if that persists open an issue to the DRF repo.

1 Like

What DRF pagination classes expect as the request argument is a rest_framework.request.Request instance (django-rest-framework/rest_framework/request.py at 9d4ed054bf8acfac6209b7e7f837fc97517affcc · encode/django-rest-framework · GitHub) not a WSGIRequest.

Such DRF request is instanciated by the DRF APIView class (see django-rest-framework/rest_framework/views.py at 9d4ed054bf8acfac6209b7e7f837fc97517affcc · encode/django-rest-framework · GitHub) . So, if you do not want to test the pagination through a real APIView, using API client, then wrap the request you built with APIRequestFactory in a DRF Request.

from rest_framework.request import Request


request = Request(self.factory(...))
1 Like