Commit 95d8c061 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #9351 -- Modified the test client to pass on URL encoded parameters to...

Fixed #9351 -- Modified the test client to pass on URL encoded parameters to the underlying views. Thanks to sime for the suggestion.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9398 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent a53ccc82
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
import urllib
from urlparse import urlparse, urlunparse
import sys
import os
try:
@@ -260,10 +261,11 @@ class Client(object):
        """
        Requests a response from the server using GET.
        """
        parsed = urlparse(path)
        r = {
            'CONTENT_TYPE':    'text/html; charset=utf-8',
            'PATH_INFO':       urllib.unquote(path),
            'QUERY_STRING':    urlencode(data, doseq=True),
            'PATH_INFO':       urllib.unquote(parsed.path),
            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query,
            'REQUEST_METHOD': 'GET',
            'wsgi.input':      FakePayload('')
        }
@@ -280,10 +282,12 @@ class Client(object):
        else:
            post_data = data

        parsed = urlparse(path)
        r = {
            'CONTENT_LENGTH': len(post_data),
            'CONTENT_TYPE':   content_type,
            'PATH_INFO':      urllib.unquote(path),
            'PATH_INFO':      urllib.unquote(parsed.path),
            'QUERY_STRING':   parsed.query,
            'REQUEST_METHOD': 'POST',
            'wsgi.input':     FakePayload(post_data),
        }
@@ -295,10 +299,11 @@ class Client(object):
        """
        Request a response from the server using HEAD.
        """
        parsed = urlparse(path)
        r = {
            'CONTENT_TYPE':    'text/html; charset=utf-8',
            'PATH_INFO':       urllib.unquote(path),
            'QUERY_STRING':    urlencode(data, doseq=True),
            'PATH_INFO':       urllib.unquote(parsed.path),
            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query,
            'REQUEST_METHOD': 'HEAD',
            'wsgi.input':      FakePayload('')
        }
@@ -310,9 +315,10 @@ class Client(object):
        """
        Request a response from the server using OPTIONS.
        """
        parsed = urlparse(path)
        r = {
            'PATH_INFO':       urllib.unquote(path),
            'QUERY_STRING':    urlencode(data, doseq=True),
            'PATH_INFO':       urllib.unquote(parsed.path),
            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query,
            'REQUEST_METHOD': 'OPTIONS',
            'wsgi.input':      FakePayload('')
        }
@@ -328,11 +334,13 @@ class Client(object):
            post_data = encode_multipart(BOUNDARY, data)
        else:
            post_data = data

        parsed = urlparse(path)
        r = {
            'CONTENT_LENGTH': len(post_data),
            'CONTENT_TYPE':   content_type,
            'PATH_INFO':      urllib.unquote(path),
            'QUERY_STRING':   urlencode(data, doseq=True),
            'PATH_INFO':      urllib.unquote(parsed.path),
            'QUERY_STRING':   urlencode(data, doseq=True) or parsed.query,
            'REQUEST_METHOD': 'PUT',
            'wsgi.input':     FakePayload(post_data),
        }
@@ -344,9 +352,10 @@ class Client(object):
        """
        Send a DELETE request to the server.
        """
        parsed = urlparse(path)
        r = {
            'PATH_INFO':       urllib.unquote(path),
            'QUERY_STRING':    urlencode(data, doseq=True),
            'PATH_INFO':       urllib.unquote(parsed.path),
            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query,
            'REQUEST_METHOD': 'DELETE',
            'wsgi.input':      FakePayload('')
        }
+24 −0
Original line number Diff line number Diff line
@@ -493,6 +493,18 @@ arguments at time of construction:

            /customers/details/?name=fred&age=7

        .. versionadded:: development

        If you already have the GET arguments in URL-encoded form, you can
        use that encoding instead of using the data argument. For example,
        the previous GET request could also be posed as::

        >>> c = Client()
        >>> c.get('/customers/details/?name=fred&age=7')

        If you provide URL both an encoded GET data and a data argument,
        the data argument will take precedence.

    .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT)

        Makes a POST request on the provided ``path`` and returns a
@@ -544,6 +556,18 @@ arguments at time of construction:
        Note that you should manually close the file after it has been provided
        to ``post()``.

        .. versionadded:: development

        If the URL you request with a POST contains encoded parameters, these
        parameters will be made available in the request.GET data. For example,
        if you were to make the request::

        >>> c.post('/login/?vistor=true', {'name': 'fred', 'passwd': 'secret'})

        ... the view handling this request could interrogate request.POST
        to retrieve the username and password, and could interrogate request.GET
        to determine if the user was a visitor.

    .. method:: Client.head(path, data={})

        .. versionadded:: development
+56 −5
Original line number Diff line number Diff line
@@ -421,3 +421,54 @@ class RequestMethodTests(TestCase):
        response = self.client.delete('/test_client_regress/request_methods/')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'request method: DELETE')

class QueryStringTests(TestCase):
    def test_get_like_requests(self):
        for method_name in ('get','head','options','put','delete'):
            # A GET-like request can pass a query string as data
            method = getattr(self.client, method_name)
            response = method("/test_client_regress/request_data/", data={'foo':'whiz'})
            self.assertEqual(response.context['get-foo'], 'whiz')
            self.assertEqual(response.context['request-foo'], 'whiz')

            # A GET-like request can pass a query string as part of the URL
            response = method("/test_client_regress/request_data/?foo=whiz")
            self.assertEqual(response.context['get-foo'], 'whiz')
            self.assertEqual(response.context['request-foo'], 'whiz')

            # Data provided in the URL to a GET-like request is overridden by actual form data
            response = method("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
            self.assertEqual(response.context['get-foo'], 'bang')
            self.assertEqual(response.context['request-foo'], 'bang')

            response = method("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
            self.assertEqual(response.context['get-foo'], None)
            self.assertEqual(response.context['get-bar'], 'bang')
            self.assertEqual(response.context['request-foo'], None)
            self.assertEqual(response.context['request-bar'], 'bang')

    def test_post_like_requests(self):
        # A POST-like request can pass a query string as data
        response = self.client.post("/test_client_regress/request_data/", data={'foo':'whiz'})
        self.assertEqual(response.context['get-foo'], None)
        self.assertEqual(response.context['post-foo'], 'whiz')

        # A POST-like request can pass a query string as part of the URL
        response = self.client.post("/test_client_regress/request_data/?foo=whiz")
        self.assertEqual(response.context['get-foo'], 'whiz')
        self.assertEqual(response.context['post-foo'], None)
        self.assertEqual(response.context['request-foo'], 'whiz')

        # POST data provided in the URL augments actual form data
        response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
        self.assertEqual(response.context['get-foo'], 'whiz')
        self.assertEqual(response.context['post-foo'], 'bang')
        self.assertEqual(response.context['request-foo'], 'bang')

        response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
        self.assertEqual(response.context['get-foo'], 'whiz')
        self.assertEqual(response.context['get-bar'], None)
        self.assertEqual(response.context['post-foo'], None)
        self.assertEqual(response.context['post-bar'], 'bang')
        self.assertEqual(response.context['request-foo'], 'whiz')
        self.assertEqual(response.context['request-bar'], 'bang')
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ urlpatterns = patterns('',
    (r'^no_template_view/$', views.no_template_view),
    (r'^staff_only/$', views.staff_only_view),
    (r'^get_view/$', views.get_view),
    (r'^request_data/$', views.request_data),
    url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'),
    (r'^login_protected_redirect_view/$', views.login_protected_redirect_view),
    (r'^set_session/$', views.set_session_view),
+12 −0
Original line number Diff line number Diff line
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect
from django.core.exceptions import SuspiciousOperation
from django.shortcuts import render_to_response

def no_template_view(request):
    "A simple view that expects a GET request, and returns a rendered template"
@@ -18,6 +19,17 @@ def get_view(request):
    return HttpResponse("Hello world")
get_view = login_required(get_view)

def request_data(request):
    "A simple view that returns the request data in the context"
    return render_to_response('base.html', {
        'get-foo':request.GET.get('foo',None),
        'get-bar':request.GET.get('bar',None),
        'post-foo':request.POST.get('foo',None),
        'post-bar':request.POST.get('bar',None),
        'request-foo':request.REQUEST.get('foo',None),
        'request-bar':request.REQUEST.get('bar',None),
    })

def view_with_argument(request, name):
    """A view that takes a string argument