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:
Russell Keith-Magee 2007-02-17 00:23:09 +00:00
parent 4a85a75fb0
commit d6d51c9546
5 changed files with 60 additions and 21 deletions

View File

@ -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)

View File

@ -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')

View File

@ -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/')

View File

@ -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),

View File

@ -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/')