Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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,) 
like image 412
user1544500 Avatar asked Jan 23 '17 10:01

user1544500


2 Answers

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

response = view(request, pk=1)
like image 71
RemcoGerlich Avatar answered Oct 19 '22 17:10

RemcoGerlich


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()
like image 21
7guyo Avatar answered Oct 19 '22 17:10

7guyo