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:
parent
4a85a75fb0
commit
d6d51c9546
|
@ -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``.
|
||||
``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.
|
||||
|
||||
However submitting files is a special case. To POST a file, you need only
|
||||
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,12 +14,31 @@ 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.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 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))
|
||||
|
||||
|
|
Loading…
Reference in New Issue