Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #3160 -- Added the ability to control the content type in a tes…

…t 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
  • Loading branch information...
commit d6d51c9546a8734683c75bddc2cab93e05247f1e 1 parent 4a85a75
Russell Keith-Magee authored February 17, 2007
18  django/test/client.py
@@ -9,6 +9,9 @@
9 9
 from django.test import signals
10 10
 from django.utils.functional import curry
11 11
 
  12
+BOUNDARY = 'BoUnDaRyStRiNg'
  13
+MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
  14
+
12 15
 class ClientHandler(BaseHandler):
13 16
     """
14 17
     A HTTP Handler that can be used for testing purposes.
@@ -184,19 +187,20 @@ def get(self, path, data={}, **extra):
184 187
 
185 188
         return self.request(**r)
186 189
 
187  
-    def post(self, path, data={}, **extra):
  190
+    def post(self, path, data={}, content_type=MULTIPART_CONTENT, **extra):
188 191
         "Request a response from the server using POST."
189 192
 
190  
-        BOUNDARY = 'BoUnDaRyStRiNg'
  193
+        if content_type is MULTIPART_CONTENT:
  194
+            post_data = encode_multipart(BOUNDARY, data)
  195
+        else:
  196
+            post_data = data
191 197
 
192  
-        encoded = encode_multipart(BOUNDARY, data)
193  
-        stream = StringIO(encoded)
194 198
         r = {
195  
-            'CONTENT_LENGTH': len(encoded),
196  
-            'CONTENT_TYPE':   'multipart/form-data; boundary=%s' % BOUNDARY,
  199
+            'CONTENT_LENGTH': len(post_data),
  200
+            'CONTENT_TYPE':   content_type,
197 201
             'PATH_INFO':      path,
198 202
             'REQUEST_METHOD': 'POST',
199  
-            'wsgi.input':     stream,
  203
+            'wsgi.input':     StringIO(post_data),
200 204
         }
201 205
         r.update(extra)
202 206
 
20  docs/testing.txt
@@ -217,15 +217,21 @@ can be invoked on the ``Client`` instance.
217 217
 
218 218
         http://yoursite.com/customers/details/?name=fred&age=7
219 219
 
220  
-``post(path, data={})``
221  
-    Make a POST request on the provided ``path``. The key-value pairs in the
222  
-    data dictionary will be used to create the POST data payload. This payload
223  
-    will be transmitted with the mimetype ``multipart/form-data``.
224  
-
225  
-    However submitting files is a special case. To POST a file, you need only
  220
+``post(path, data={}, content_type=MULTIPART_CONTENT)``
  221
+    Make a POST request on the provided ``path``. If you provide a content type
  222
+    (e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be 
  223
+    sent as-is in the POST request, using the content type in the HTTP 
  224
+    ``Content-Type`` header.
  225
+    
  226
+    If you do not provide a value for ``content_type``, the values in 
  227
+    ``data`` will be transmitted with a content type of ``multipart/form-data``.
  228
+    The key-value pairs in the data dictionary will be encoded as a multipart
  229
+    message and used to create the POST data payload.
  230
+    
  231
+    Submitting files is a special case. To POST a file, you need only
226 232
     provide the file field name as a key, and a file handle to the file you wish to
227 233
     upload as a value. The Test Client will populate the two POST fields (i.e.,
228  
-    ``field`` and ``field_file``) required by FileField. For example::
  234
+    ``field`` and ``field_file``) required by Django's FileField. For example::
229 235
 
230 236
         c = Client()
231 237
         f = open('wishlist.doc')
12  tests/modeltests/test_client/models.py
@@ -43,7 +43,7 @@ def test_get_post_view(self):
43 43
         
44 44
         # Check some response details
45 45
         self.assertEqual(response.status_code, 200)
46  
-        self.assertEqual(response.template.name, 'Empty POST Template')
  46
+        self.assertEqual(response.template.name, 'Empty GET Template')
47 47
         
48 48
     def test_empty_post(self):
49 49
         "POST an empty dictionary to a view"
@@ -53,7 +53,7 @@ def test_empty_post(self):
53 53
         self.assertEqual(response.status_code, 200)
54 54
         self.assertEqual(response.template.name, 'Empty POST Template')
55 55
         
56  
-    def test_post_view(self):
  56
+    def test_post(self):
57 57
         "POST some data to a view"
58 58
         post_data = {
59 59
             'value': 37
@@ -66,6 +66,14 @@ def test_post_view(self):
66 66
         self.assertEqual(response.template.name, 'POST Template')
67 67
         self.failUnless('Data received' in response.content)
68 68
         
  69
+    def test_raw_post(self):
  70
+        test_doc = """<?xml version="1.0" encoding="utf-8"?><library><book><title>Blink</title><author>Malcolm Gladwell</author></book></library>"""
  71
+        response = self.client.post("/test_client/raw_post_view/", test_doc,
  72
+                                    content_type="text/xml")
  73
+        self.assertEqual(response.status_code, 200)
  74
+        self.assertEqual(response.template.name, "Book template")
  75
+        self.assertEqual(response.content, "Blink - Malcolm Gladwell")
  76
+
69 77
     def test_redirect(self):
70 78
         "GET a URL that redirects elsewhere"
71 79
         response = self.client.get('/test_client/redirect_view/')
1  tests/modeltests/test_client/urls.py
@@ -4,6 +4,7 @@
4 4
 urlpatterns = patterns('',
5 5
     (r'^get_view/$', views.get_view),
6 6
     (r'^post_view/$', views.post_view),
  7
+    (r'^raw_post_view/$', views.raw_post_view),
7 8
     (r'^redirect_view/$', views.redirect_view),
8 9
     (r'^login_protected_view/$', views.login_protected_view),
9 10
     (r'^session_view/$', views.session_view),
30  tests/modeltests/test_client/views.py
... ...
@@ -1,3 +1,4 @@
  1
+from xml.dom.minidom import parseString
1 2
 from django.template import Context, Template
2 3
 from django.http import HttpResponse, HttpResponseRedirect
3 4
 from django.contrib.auth.decorators import login_required
@@ -13,15 +14,34 @@ def post_view(request):
13 14
     """A view that expects a POST, and returns a different template depending
14 15
     on whether any POST data is available
15 16
     """
16  
-    if request.POST:
17  
-        t = Template('Data received: {{ data }} is the value.', name='POST Template')
18  
-        c = Context({'data': request.POST['value']})
  17
+    if request.method == 'POST':
  18
+        if request.POST:
  19
+            t = Template('Data received: {{ data }} is the value.', name='POST Template')
  20
+            c = Context({'data': request.POST['value']})
  21
+        else:
  22
+            t = Template('Viewing POST page.', name='Empty POST Template')
  23
+            c = Context()
19 24
     else:
20  
-        t = Template('Viewing POST page.', name='Empty POST Template')
  25
+        t = Template('Viewing GET page.', name='Empty GET Template')
21 26
         c = Context()
22  
-        
  27
+    
23 28
     return HttpResponse(t.render(c))
24 29
     
  30
+def raw_post_view(request):
  31
+    """A view which expects raw XML to be posted and returns content extracted
  32
+    from the XML"""
  33
+    if request.method == 'POST':
  34
+        root = parseString(request.raw_post_data)
  35
+        first_book = root.firstChild.firstChild
  36
+        title, author = [n.firstChild.nodeValue for n in first_book.childNodes]
  37
+        t = Template("{{ title }} - {{ author }}", name="Book template")
  38
+        c = Context({"title": title, "author": author})
  39
+    else:
  40
+        t = Template("GET request.", name="Book GET template")
  41
+        c = Context()
  42
+
  43
+    return HttpResponse(t.render(c))
  44
+
25 45
 def redirect_view(request):
26 46
     "A view that redirects all requests to the GET view"
27 47
     return HttpResponseRedirect('/test_client/get_view/')

0 notes on commit d6d51c9

Please sign in to comment.
Something went wrong with that request. Please try again.