#28218: KeyError 'content-type' http/response.py when printing response
------------------------------------------+------------------------
               Reporter:  Denise Mauldin  |          Owner:  nobody
                   Type:  Bug             |         Status:  new
              Component:  HTTP handling   |        Version:  1.10
               Severity:  Normal          |       Keywords:
           Triage Stage:  Unreviewed      |      Has patch:  0
    Needs documentation:  0               |    Needs tests:  0
Patch needs improvement:  0               |  Easy pickings:  0
                  UI/UX:  0               |
------------------------------------------+------------------------
 Hi all,

 I'm using Django Rest Framework for my API.  I'm testing account creation
 using my API.


 {{{
 from django.urls import reverse
 from django.contrib.auth import get_user_model
 from rest_framework import status
 from rest_framework.request import Request
 from rest_framework.test import APITestCase, APIClient, APIRequestFactory
 from rest_framework.authtoken.models import Token

 class AccountCreationTests(APITestCase):
     """
     This is the account creation tests for the /api/users endpoint on
 angular
     """
     fixtures = ['user_dev', 'order_dev']

     def setUp(self):
         self.client = APIClient()
         self.factory = APIRequestFactory()

     def test_create_account_fails(self):
         """
         Ensure we can't create a new account object without required keys
 on angular
         """
         url = reverse('user-list')
         data = {'email': '[email protected]'}
         # fails because of required fields
         response = self.client.post(url, data, format='json')
         print("\n\ntest_create_account_fails response
 {}\n\n".format(response.__dict__))
         self.assertEqual(response.status_code,
 status.HTTP_400_BAD_REQUEST,
                          "Creating a user without required fields is a bad
 request")

     def test_create_account(self):
         """ Creating an account only works if there is no request.user and
 all required fields provided """
         starting_user_count = get_user_model().objects.count()
         url = reverse('user-list')
         data = {'email': '[email protected]', 'first_name': 'John',
 'last_name': 'Doe',
                 'phone': '2065551234', 'institution': 'Test', 'groupLead':
 'John',
                 'password': 'testpassword'}
         response = self.client.post(url, data, format='json')
         print("\n\ntest_create_account response
 {}\n\n".format(response.__dict__))
         self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                          "User API POST unsuccessful
 {}".format(response.data))
         self.assertEqual(get_user_model().objects.count(),
 starting_user_count + 1,
                          "One user was created")
 self.assertEqual(get_user_model().objects.get(email=data['email']).email,
 '[email protected]',
                          "Email exists in database {}".format(
 get_user_model().objects.filter(email=data['email']).__dict__)

 }}}

 The test_create_account_fails method works and returns an expected
 failure.  The test_create_account fails because http/response.py line 152
 can't find the 'headers' key.  I'm not sure why....


 {{{
 Traceback (most recent call last):
   File "/var/www/ann/ann/users/tests/test_account_creation.py", line 41,
 in test_create_account
     print("\n\ntest_create_account response {}\n\n".format(response))
   File "/home/vagrant/.virtualenvs/ann/lib/python3.5/site-
 packages/django/http/response.py", line 299, in __repr__
     'content_type': self['Content-Type'],
   File "/home/vagrant/.virtualenvs/ann/lib/python3.5/site-
 packages/django/http/response.py", line 152, in __getitem__
     return self._headers[header.lower()][1]
 KeyError: 'content-type'
 }}}

 If I patch the code to:

 {{{
     def __getitem__(self, header):
         if self._headers.get(header.lower()):
             return self._headers[header.lower()][1]
         return self._headers.get(header.lower())
 }}}

 then test_create_account returns the following object during a print:

 {{{
 test_create_account response {'resolver_match': <SimpleLazyObject:
 <function Client.request.<locals>.<lambda> at 0x7f8399ed4400>>, 'using':
 None, 'template_name': None, 'context': [[{'False': False, 'None': None,
 'True': True}, {'activate_url': 'http://testserver/accounts/confirm-
 email/MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ/', 'key':
 'MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ', 'user': <User: John Doe>,
 'current_site': <Site: ann.test.org>}], [{'False': False, 'None': None,
 'True': True}, {'activate_url': 'http://testserver/accounts/confirm-
 email/MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ/', 'key':
 'MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ', 'user': <User: John Doe>,
 'current_site': <Site: ann.test.org>}, {}], [{'False': False, 'None':
 None, 'True': True}, {'activate_url': 'http://testserver/accounts/confirm-
 email/MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ/', 'key':
 'MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ', 'user': <User: John Doe>,
 'current_site': <Site: ann.test.org>}], [{'False': False, 'None': None,
 'True': True}, {'activate_url': 'http://testserver/accounts/confirm-
 email/MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ/', 'key':
 'MTU:1dB3Lm:43Wje1L2IirjhfKIBf_uzsUclZQ', 'user': <User: John Doe>,
 'current_site': <Site: ann.test.org>}, {'user_display': 'John Doe'}]],
 '_dont_enforce_csrf_checks': True, '_post_render_callbacks': [],
 '_is_rendered': True, 'client': <rest_framework.test.APIClient object at
 0x7f83997a2470>, 'cookies': <SimpleCookie:
 csrftoken='HPkblAYrdPfbJs5c2OAc7vH0k89wuj1n7elaPP8VZhvaB7CcouQxjy6bV47s3jgR'
 sessionid='f0ukkwdn00jyt1tx52r86c9fax1ut2yv'>, 'context_data': None,
 'templates': [<django.template.base.Template object at 0x7f8399a57e10>,
 <django.template.base.Template object at 0x7f8399adef98>,
 <django.template.base.Template object at 0x7f8399ade748>,
 <django.template.base.Template object at 0x7f8399adef28>], 'json
 }}}

 test_create_account_fails returns this object:

 {{{
 test_create_account_fails response {'context_data': None, 'template_name':
 None, 'templates': [], 'resolver_match': <SimpleLazyObject: <function
 Client.request.<locals>.<lambda> at 0x7fd5038941e0>>, 'closed': True,
 '_is_rendered': True, 'status_code': 400, '_post_render_callbacks': [],
 '_charset': None, '_reason_phrase': None, '_request': None, '_headers':
 {'content-type': ('Content-Type', 'application/json'), 'allow': ('Allow',
 'GET, POST, OPTIONS'), 'vary': ('Vary', 'Cookie'), 'x-frame-options': ('X
 -Frame-Options', 'SAMEORIGIN')}, '_handler_class': None, 'using': None,
 'exception': True, 'data': {'institution': ['This field is required.'],
 'phone': ['This field is required.'], 'group_lead': ['This field is
 required.'], 'password': ['This field is required.'], 'first_name': ['This
 field is required.'], 'last_name': ['This field is required.']},
 'accepted_renderer':
 <djangorestframework_camel_case.render.CamelCaseJSONRenderer object at
 0x7fd50356cb00>, 'content_type': None, 'accepted_media_type':
 'application/json', 'client': <rest_framework.test.APIClient object at
 0x7fd50356c630>, 'wsgi_request': <WSGIRequest: POST '/api/users'>,
 'context': None, '_closable_objects': [<WSGIRequest: POST '/api/users'>],
 'renderer_context': {'view': <ann.users.apiviews.UserViewSet object at
 0x7fd50356c978>, 'args': (), 'response': <Response status_code=400,
 "application/json">, 'request': <rest_framework.request.Request object at
 0x7fd50356ca20>, 'kwargs': {}}, '_container': [b'{"institution":["This
 field is required."],"phone":["This field is
 required."],"groupLead":["This field is required."],"password":["This
 field is required."],"firstName":["This field is
 required."],"lastName":["This field is required."]}'], 'cookies':
 <SimpleCookie: >, 'json': <function curry.<locals>._curried at
 0x7fd503894510>, 'request': {'REQUEST_METHOD': 'POST', 'CONTENT_LENGTH':
 28, 'wsgi.url_scheme': 'http', 'QUERY_STRING': '', 'wsgi.input':
 <django.test.client.FakePayload object at 0x7fd5034d9908>, 'SERVER_PORT':
 '80', 'CONTENT_TYPE': 'application/json; charset=None', 'PATH_INFO':
 '/api/users'}, '_dont_enforce_csrf_checks': True}
 }}}

 Maybe this is a bug with Django Rest Framework or CamelCaseJSONParser, but
 I'd expect http/response to have a more robust getter?

--
Ticket URL: <https://code.djangoproject.com/ticket/28218>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/056.1d5fecd13bbc0f94b3d0348b346307db%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to