I'm testing a CreateAPIView with an APITestCase class. Things are working as expected as an anonymous user, but when I login() as a user, I get a 405 HttpResponseNotAllowed exception. I'm able to successfully create an object while authed as a user through the django-rest-framework web frontend. I'm using djangorestframework version 3.9.4 and Django 1.11.29.
Here are the main parts of the code, for a general idea of what I'm doing:
class SherdNoteCreate(CreateAPIView): serializer_class = SherdNoteSerializer def post(self, request, *args, **kwargs): data = request.data.copy() data['asset'] = kwargs.get('asset_id') serializer = SherdNoteSerializer(data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class SherdNoteTests(APITestCase): def test_create_sherdnote_on_own_asset(self): # Removing this auth block allows the test to pass self.u = UserFactory(username='test_user') self.u.set_password('test') self.u.save() login = self.client.login(username='test_user', password='test') assert(login is True) asset = AssetFactory(primary_source='image', author=self.u) url = reverse('sherdnote-create', kwargs={'asset_id': asset.pk}) data = { 'title': 'note title', 'body': 'note body' } response = self.client.post(url, data, format='json') # This fails with a 405! self.assertEqual(response.status_code, status.HTTP_201_CREATED) The route in urls.py:
url(r'^(?P<asset_id>\d+)/sherdnote/create/$', SherdNoteCreate.as_view(), name='sherdnote-create'), Here's the response and response.__dict__ printed out, from the test above:
<HttpResponseNotAllowed [GET, HEAD, OPTIONS] status_code=405, "text/html; charset=utf-8"> {'_headers': {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'allow': ('Allow', 'GET, HEAD, OPTIONS'), 'vary': ('Va ry', 'Origin, Cookie'), 'x-frame-options': ('X-Frame-Options', 'SAMEORIGIN'), 'content-length': ('Content-Length', '0')}, '_closab le_objects': [<WSGIRequest: POST '/asset/1/sherdnote/create/'>], '_handler_class': None, 'cookies': <SimpleCookie: >, 'closed': Tr ue, '_reason_phrase': None, '_charset': None, '_container': [b''], 'wsgi_request': <WSGIRequest: POST '/asset/1/sherdnote/create/' >, 'client': <rest_framework.test.APIClient object at 0x7f9880902f10>, 'request': {'PATH_INFO': '/asset/1/sherdnote/create/', 'REQ UEST_METHOD': 'POST', 'SERVER_PORT': '80', 'wsgi.url_scheme': 'http', 'CONTENT_LENGTH': 41, 'CONTENT_TYPE': 'application/json; cha rset=None', 'wsgi.input': <django.test.client.FakePayload object at 0x7f987e834790>, 'QUERY_STRING': ''}, 'templates': [], 'contex t': None, 'json': <function curry.<locals>._curried at 0x7f988018e440>, 'resolver_match': <SimpleLazyObject: <function Client.requ est.<locals>.<lambda> at 0x7f988018eef0>>, '_dont_enforce_csrf_checks': True} I've been having trouble tracking down why this is happening. Does anyone have any ideas?
url = reverse('sherdnote-create', kwargs={'asset_id': asset.pk})can you debug this line and see if your post request is sent to correct url./asset/1/sherdnote/create/postusing postman or curl successfully? 405 HTTP response status code indicates that the request method is known by the server but is not supported by the target resource.postmethod in your view to becreate, they should be the same.