Expected view to be called with a URL keyword argument named "pk"

23,278

Solution 1

View functions are called with the request and the arguments from the URL. So pass them:

response = view(request, pk=1)

Solution 2

I encountered similar error when I made a mistake of using get_object method in perform_create. Read why this wrong from documentation

perform_create(self,instance):
      instance = self.get_object()
Share:
23,278

Related videos on Youtube

user1544500
Author by

user1544500

Learning Python/Django and Angular.

Updated on July 09, 2022

Comments

  • user1544500
    user1544500 almost 2 years

    I'm writing a test for a Django Rest Framework view following closely the testing documentation

    Here's my simple test:

    def test_patient_detail_api_opens(self):
        factory = APIRequestFactory()
        view =PatientDetailApi.as_view()
        request = factory.get(reverse('api_pacjent', kwargs={'pk' :1}))
        force_authenticate(request, user=self.user)
        response = view(request)
        self.assertEqual(response.status_code, 200)
    

    This test fails with the following message:

    AssertionError: Expected view PatientDetailApi to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.
    

    I fail to understand why this is happening and how to fix this.

    • The pk kwargs is there in the URL,
    • according to the docs there's no need to add the lookup-field value explicitly if it defaults to pk,
    • the view opens correctly and yet this test fails...

    Can somebody please explain why this error occurs?

    Here's the relevant code:

    the 'main' url.py:

    urlpatterns = [
        url(r'^pacjent/', include('pacjent.urls')),
    ] 
    

    pacjent.urls looks like this:

    url(r'^api/szczegoly/(?P<pk>\d+)/$', PatientDetailApi.as_view(), name="api_pacjent"),
    

    And PatientDetailApi is this:

    class PatientDetailApi(generics.RetrieveUpdateAPIView):
        model = Patient
        serializer_class = PatientDetailsSerializer
        queryset = Patient.objects.all()
    
        authentication_classes = (SessionAuthentication, BasicAuthentication)
        permission_classes = (IsAuthenticated,) 
    
    • Daniel Roseman
      Daniel Roseman over 7 years
      Does it work when you actually request the api outside of your test, eg via Postman? Or if you use the APIClient?
    • user1544500
      user1544500 over 7 years
      It does. It was the missing part mentioned by RemcoGerlich. Thanks for your suggestion!
    • Asad Manzoor
      Asad Manzoor over 4 years
      @user1544500 what will be the API endpoint if you call your API from postman with named argument?
  • Csaba Toth
    Csaba Toth about 5 years
    OMG, I tried to add it to the as_view and then the factory.get, then trying to fiddle with the request itself...