mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #3160 -- Added the ability to control the content type in a test client POST request. This is to allow easier testing of json-rpc/xml-rpc/soap etc interfaces. Thanks to Mikeal Rogers for the suggestion, and Ben <afternoon@uk2.net> for the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4529 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -9,6 +9,9 @@ from django.http import urlencode, SimpleCookie | ||||
| from django.test import signals | ||||
| from django.utils.functional import curry | ||||
|  | ||||
| BOUNDARY = 'BoUnDaRyStRiNg' | ||||
| MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY | ||||
|  | ||||
| class ClientHandler(BaseHandler): | ||||
|     """ | ||||
|     A HTTP Handler that can be used for testing purposes. | ||||
| @@ -184,19 +187,20 @@ class Client: | ||||
|  | ||||
|         return self.request(**r) | ||||
|  | ||||
|     def post(self, path, data={}, **extra): | ||||
|     def post(self, path, data={}, content_type=MULTIPART_CONTENT, **extra): | ||||
|         "Request a response from the server using POST." | ||||
|  | ||||
|         BOUNDARY = 'BoUnDaRyStRiNg' | ||||
|         if content_type is MULTIPART_CONTENT: | ||||
|             post_data = encode_multipart(BOUNDARY, data) | ||||
|         else: | ||||
|             post_data = data | ||||
|  | ||||
|         encoded = encode_multipart(BOUNDARY, data) | ||||
|         stream = StringIO(encoded) | ||||
|         r = { | ||||
|             'CONTENT_LENGTH': len(encoded), | ||||
|             'CONTENT_TYPE':   'multipart/form-data; boundary=%s' % BOUNDARY, | ||||
|             'CONTENT_LENGTH': len(post_data), | ||||
|             'CONTENT_TYPE':   content_type, | ||||
|             'PATH_INFO':      path, | ||||
|             'REQUEST_METHOD': 'POST', | ||||
|             'wsgi.input':     stream, | ||||
|             'wsgi.input':     StringIO(post_data), | ||||
|         } | ||||
|         r.update(extra) | ||||
|  | ||||
|   | ||||
| @@ -217,15 +217,21 @@ can be invoked on the ``Client`` instance. | ||||
|  | ||||
|         http://yoursite.com/customers/details/?name=fred&age=7 | ||||
|  | ||||
| ``post(path, data={})`` | ||||
|     Make a POST request on the provided ``path``. The key-value pairs in the | ||||
|     data dictionary will be used to create the POST data payload. This payload | ||||
|     will be transmitted with the mimetype ``multipart/form-data``. | ||||
|  | ||||
|     However submitting files is a special case. To POST a file, you need only | ||||
| ``post(path, data={}, content_type=MULTIPART_CONTENT)`` | ||||
|     Make a POST request on the provided ``path``. If you provide a content type | ||||
|     (e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be  | ||||
|     sent as-is in the POST request, using the content type in the HTTP  | ||||
|     ``Content-Type`` header. | ||||
|      | ||||
|     If you do not provide a value for ``content_type``, the values in  | ||||
|     ``data`` will be transmitted with a content type of ``multipart/form-data``. | ||||
|     The key-value pairs in the data dictionary will be encoded as a multipart | ||||
|     message and used to create the POST data payload. | ||||
|      | ||||
|     Submitting files is a special case. To POST a file, you need only | ||||
|     provide the file field name as a key, and a file handle to the file you wish to | ||||
|     upload as a value. The Test Client will populate the two POST fields (i.e., | ||||
|     ``field`` and ``field_file``) required by FileField. For example:: | ||||
|     ``field`` and ``field_file``) required by Django's FileField. For example:: | ||||
|  | ||||
|         c = Client() | ||||
|         f = open('wishlist.doc') | ||||
|   | ||||
| @@ -43,7 +43,7 @@ class ClientTest(unittest.TestCase): | ||||
|          | ||||
|         # Check some response details | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertEqual(response.template.name, 'Empty POST Template') | ||||
|         self.assertEqual(response.template.name, 'Empty GET Template') | ||||
|          | ||||
|     def test_empty_post(self): | ||||
|         "POST an empty dictionary to a view" | ||||
| @@ -53,7 +53,7 @@ class ClientTest(unittest.TestCase): | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertEqual(response.template.name, 'Empty POST Template') | ||||
|          | ||||
|     def test_post_view(self): | ||||
|     def test_post(self): | ||||
|         "POST some data to a view" | ||||
|         post_data = { | ||||
|             'value': 37 | ||||
| @@ -66,6 +66,14 @@ class ClientTest(unittest.TestCase): | ||||
|         self.assertEqual(response.template.name, 'POST Template') | ||||
|         self.failUnless('Data received' in response.content) | ||||
|          | ||||
|     def test_raw_post(self): | ||||
|         test_doc = """<?xml version="1.0" encoding="utf-8"?><library><book><title>Blink</title><author>Malcolm Gladwell</author></book></library>""" | ||||
|         response = self.client.post("/test_client/raw_post_view/", test_doc, | ||||
|                                     content_type="text/xml") | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertEqual(response.template.name, "Book template") | ||||
|         self.assertEqual(response.content, "Blink - Malcolm Gladwell") | ||||
|  | ||||
|     def test_redirect(self): | ||||
|         "GET a URL that redirects elsewhere" | ||||
|         response = self.client.get('/test_client/redirect_view/') | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import views | ||||
| urlpatterns = patterns('', | ||||
|     (r'^get_view/$', views.get_view), | ||||
|     (r'^post_view/$', views.post_view), | ||||
|     (r'^raw_post_view/$', views.raw_post_view), | ||||
|     (r'^redirect_view/$', views.redirect_view), | ||||
|     (r'^login_protected_view/$', views.login_protected_view), | ||||
|     (r'^session_view/$', views.session_view), | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| from xml.dom.minidom import parseString | ||||
| from django.template import Context, Template | ||||
| from django.http import HttpResponse, HttpResponseRedirect | ||||
| from django.contrib.auth.decorators import login_required | ||||
| @@ -13,15 +14,34 @@ def post_view(request): | ||||
|     """A view that expects a POST, and returns a different template depending | ||||
|     on whether any POST data is available | ||||
|     """ | ||||
|     if request.POST: | ||||
|         t = Template('Data received: {{ data }} is the value.', name='POST Template') | ||||
|         c = Context({'data': request.POST['value']}) | ||||
|     if request.method == 'POST': | ||||
|         if request.POST: | ||||
|             t = Template('Data received: {{ data }} is the value.', name='POST Template') | ||||
|             c = Context({'data': request.POST['value']}) | ||||
|         else: | ||||
|             t = Template('Viewing POST page.', name='Empty POST Template') | ||||
|             c = Context() | ||||
|     else: | ||||
|         t = Template('Viewing POST page.', name='Empty POST Template') | ||||
|         t = Template('Viewing GET page.', name='Empty GET Template') | ||||
|         c = Context() | ||||
|          | ||||
|      | ||||
|     return HttpResponse(t.render(c)) | ||||
|      | ||||
| def raw_post_view(request): | ||||
|     """A view which expects raw XML to be posted and returns content extracted | ||||
|     from the XML""" | ||||
|     if request.method == 'POST': | ||||
|         root = parseString(request.raw_post_data) | ||||
|         first_book = root.firstChild.firstChild | ||||
|         title, author = [n.firstChild.nodeValue for n in first_book.childNodes] | ||||
|         t = Template("{{ title }} - {{ author }}", name="Book template") | ||||
|         c = Context({"title": title, "author": author}) | ||||
|     else: | ||||
|         t = Template("GET request.", name="Book GET template") | ||||
|         c = Context() | ||||
|  | ||||
|     return HttpResponse(t.render(c)) | ||||
|  | ||||
| def redirect_view(request): | ||||
|     "A view that redirects all requests to the GET view" | ||||
|     return HttpResponseRedirect('/test_client/get_view/') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user