5

I am using djangorestframework==3.3.3 and Django==1.9.4

I have a test where I want to check that query parameters processed correctly.

class TestResourceView(APITestCase):

    def test_view_process_query_params_correctly(self):
        client = APIClient()
        client.login(username='<username>', password='password')
        response = client.get('/api/v2/resource/1/users/?fields=first_name;last_name')
        self.assertEqual(response.status_code, 200)
        # .... rest of the test .... 

In my view I put print statement just to see if query parameters are parsed properly, but I get empty query dictionary:

class Resource(APIView):
    def get(self, request):
        query_params = request.query_params
        print('Printing query params')
        print(query_params)
        # .... rest of the code ....

    def post(self, request):
        query_params = request.query_params
        print('Printing query params')
        print(query_params)
        # .... rest of the code ....

Result in terminal when running tests:

Printing query params
<QueryDict: {}>

In the same time if I test post request like this:

response = client.post('/api/v2/resource/1/users/?fields=first_name;last_name')

i get params incorrectly parsed:

Printing query params
<QueryDict: {'last_name': [''], 'fields': ['first_name']}>

What is the correct way of using APIClient? Or is this still a bug? Because there was already similar issue

3 Answers 3

1

For me, the issue was that DRF wants the params in data not args like the Django test client.

This answer helped me: https://stackoverflow.com/a/45183972/9512437

class AccountTests(APITestCase):

    def setUp(self):
        self.user = CustomUser.objects.create_user(email="[email protected]", password="password1", is_staff=True)
        self.client = APIClient()

    def test_add_name(self):
        self.client.force_authenticate(self.user)

        url = reverse('customuser-detail', args=(self.user.id,))
        data = {'first_name': 'test', 'last_name': 'user'}
        response = self.client.put(url, data, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
Sign up to request clarification or add additional context in comments.

1 Comment

I believe you might have misunderstood the question; it's asking about query_params not request data
0

The format of your query parameters is incorrect.

If you want the result to be {'fields': ['last_name', 'first_name']}, then your POST url should be .../users/?fields=first_name&fields=last_name'. You'll probably want to access the params using getlist().

1 Comment

The idea is to get query params, and parse them the way I need. For example, there might be params like this /api/v2/resource/1/users/?fields=first_name;last_name, which will be parsed into the set {'first_name', 'last_name'}. One more option /api/v2/resource/1/users/?fields=1-4, which under the hood will be parsed into the set {'first_name', 'last_name', 'phone', 'skype'}. And still, another problem remains client.get('/api/v2/resource/1/users/?fields=first_name;last_name') results in empty query_params
0

1) Regarding empty <QueryDict: {}> in client.get('/api/v2/resource/1/users/?fields=first_name;last_name') - there was my mistake in my code. I had two tests with the same name, one of which indeed has empty <QueryDict: {}>. So, when running tests, django ran the test with <QueryDict: {}>

2) Regarding incorrect parsing of query params in client.post('/api/v2/resource/1/users/?fields=first_name;last_name'), I found the following discussion. So, django basically follows HTTP standards, where it is said that ; semicolon is reserved character and if using, than the correct way to comprehend it same as &. Here more details

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.