mirror of
https://github.com/django/django.git
synced 2025-01-03 06:55:47 +00:00
Fixed #20864 -- Made the test client use common method for performing requests.
This commit is contained in:
parent
4e50e40654
commit
4eeb8ec147
1
AUTHORS
1
AUTHORS
@ -317,6 +317,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Michael Josephson <http://www.sdjournal.com/>
|
Michael Josephson <http://www.sdjournal.com/>
|
||||||
jpellerin@gmail.com
|
jpellerin@gmail.com
|
||||||
junzhang.jn@gmail.com
|
junzhang.jn@gmail.com
|
||||||
|
Krzysztof Jurewicz <krzysztof.jurewicz@gmail.com>
|
||||||
Xia Kai <http://blog.xiaket.org/>
|
Xia Kai <http://blog.xiaket.org/>
|
||||||
Antti Kaihola <http://djangopeople.net/akaihola/>
|
Antti Kaihola <http://djangopeople.net/akaihola/>
|
||||||
Peter van Kampen
|
Peter van Kampen
|
||||||
|
@ -37,6 +37,7 @@ BOUNDARY = 'BoUnDaRyStRiNg'
|
|||||||
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
|
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
|
||||||
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
|
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
|
||||||
|
|
||||||
|
|
||||||
class FakePayload(object):
|
class FakePayload(object):
|
||||||
"""
|
"""
|
||||||
A wrapper around BytesIO that restricts what can be read since data from
|
A wrapper around BytesIO that restricts what can be read since data from
|
||||||
@ -123,6 +124,7 @@ class ClientHandler(BaseHandler):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def store_rendered_templates(store, signal, sender, template, context, **kwargs):
|
def store_rendered_templates(store, signal, sender, template, context, **kwargs):
|
||||||
"""
|
"""
|
||||||
Stores templates and contexts that are rendered.
|
Stores templates and contexts that are rendered.
|
||||||
@ -133,6 +135,7 @@ def store_rendered_templates(store, signal, sender, template, context, **kwargs)
|
|||||||
store.setdefault('templates', []).append(template)
|
store.setdefault('templates', []).append(template)
|
||||||
store.setdefault('context', ContextList()).append(copy(context))
|
store.setdefault('context', ContextList()).append(copy(context))
|
||||||
|
|
||||||
|
|
||||||
def encode_multipart(boundary, data):
|
def encode_multipart(boundary, data):
|
||||||
"""
|
"""
|
||||||
Encodes multipart POST data from a dictionary of form values.
|
Encodes multipart POST data from a dictionary of form values.
|
||||||
@ -178,6 +181,7 @@ def encode_multipart(boundary, data):
|
|||||||
])
|
])
|
||||||
return b'\r\n'.join(lines)
|
return b'\r\n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
def encode_file(boundary, key, file):
|
def encode_file(boundary, key, file):
|
||||||
to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
|
to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
|
||||||
if hasattr(file, 'content_type'):
|
if hasattr(file, 'content_type'):
|
||||||
@ -189,8 +193,8 @@ def encode_file(boundary, key, file):
|
|||||||
content_type = 'application/octet-stream'
|
content_type = 'application/octet-stream'
|
||||||
return [
|
return [
|
||||||
to_bytes('--%s' % boundary),
|
to_bytes('--%s' % boundary),
|
||||||
to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"' \
|
to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"'
|
||||||
% (key, os.path.basename(file.name))),
|
% (key, os.path.basename(file.name))),
|
||||||
to_bytes('Content-Type: %s' % content_type),
|
to_bytes('Content-Type: %s' % content_type),
|
||||||
b'',
|
b'',
|
||||||
file.read()
|
file.read()
|
||||||
@ -274,14 +278,11 @@ class RequestFactory(object):
|
|||||||
def get(self, path, data={}, **extra):
|
def get(self, path, data={}, **extra):
|
||||||
"Construct a GET request."
|
"Construct a GET request."
|
||||||
|
|
||||||
parsed = urlparse(path)
|
|
||||||
r = {
|
r = {
|
||||||
'PATH_INFO': self._get_path(parsed),
|
'QUERY_STRING': urlencode(data, doseq=True),
|
||||||
'QUERY_STRING': urlencode(data, doseq=True) or force_str(parsed[4]),
|
|
||||||
'REQUEST_METHOD': str('GET'),
|
|
||||||
}
|
}
|
||||||
r.update(extra)
|
r.update(extra)
|
||||||
return self.request(**r)
|
return self.generic('GET', path, **r)
|
||||||
|
|
||||||
def post(self, path, data={}, content_type=MULTIPART_CONTENT,
|
def post(self, path, data={}, content_type=MULTIPART_CONTENT,
|
||||||
**extra):
|
**extra):
|
||||||
@ -289,32 +290,19 @@ class RequestFactory(object):
|
|||||||
|
|
||||||
post_data = self._encode_data(data, content_type)
|
post_data = self._encode_data(data, content_type)
|
||||||
|
|
||||||
parsed = urlparse(path)
|
return self.generic('POST', path, post_data, content_type, **extra)
|
||||||
r = {
|
|
||||||
'CONTENT_LENGTH': len(post_data),
|
|
||||||
'CONTENT_TYPE': content_type,
|
|
||||||
'PATH_INFO': self._get_path(parsed),
|
|
||||||
'QUERY_STRING': force_str(parsed[4]),
|
|
||||||
'REQUEST_METHOD': str('POST'),
|
|
||||||
'wsgi.input': FakePayload(post_data),
|
|
||||||
}
|
|
||||||
r.update(extra)
|
|
||||||
return self.request(**r)
|
|
||||||
|
|
||||||
def head(self, path, data={}, **extra):
|
def head(self, path, data={}, **extra):
|
||||||
"Construct a HEAD request."
|
"Construct a HEAD request."
|
||||||
|
|
||||||
parsed = urlparse(path)
|
|
||||||
r = {
|
r = {
|
||||||
'PATH_INFO': self._get_path(parsed),
|
'QUERY_STRING': urlencode(data, doseq=True),
|
||||||
'QUERY_STRING': urlencode(data, doseq=True) or force_str(parsed[4]),
|
|
||||||
'REQUEST_METHOD': str('HEAD'),
|
|
||||||
}
|
}
|
||||||
r.update(extra)
|
r.update(extra)
|
||||||
return self.request(**r)
|
return self.generic('HEAD', path, **r)
|
||||||
|
|
||||||
def options(self, path, data='', content_type='application/octet-stream',
|
def options(self, path, data='', content_type='application/octet-stream',
|
||||||
**extra):
|
**extra):
|
||||||
"Construct an OPTIONS request."
|
"Construct an OPTIONS request."
|
||||||
return self.generic('OPTIONS', path, data, content_type, **extra)
|
return self.generic('OPTIONS', path, data, content_type, **extra)
|
||||||
|
|
||||||
@ -324,22 +312,22 @@ class RequestFactory(object):
|
|||||||
return self.generic('PUT', path, data, content_type, **extra)
|
return self.generic('PUT', path, data, content_type, **extra)
|
||||||
|
|
||||||
def patch(self, path, data='', content_type='application/octet-stream',
|
def patch(self, path, data='', content_type='application/octet-stream',
|
||||||
**extra):
|
**extra):
|
||||||
"Construct a PATCH request."
|
"Construct a PATCH request."
|
||||||
return self.generic('PATCH', path, data, content_type, **extra)
|
return self.generic('PATCH', path, data, content_type, **extra)
|
||||||
|
|
||||||
def delete(self, path, data='', content_type='application/octet-stream',
|
def delete(self, path, data='', content_type='application/octet-stream',
|
||||||
**extra):
|
**extra):
|
||||||
"Construct a DELETE request."
|
"Construct a DELETE request."
|
||||||
return self.generic('DELETE', path, data, content_type, **extra)
|
return self.generic('DELETE', path, data, content_type, **extra)
|
||||||
|
|
||||||
def generic(self, method, path,
|
def generic(self, method, path,
|
||||||
data='', content_type='application/octet-stream', **extra):
|
data='', content_type='application/octet-stream', **extra):
|
||||||
|
"""Constructs an arbitrary HTTP request."""
|
||||||
parsed = urlparse(path)
|
parsed = urlparse(path)
|
||||||
data = force_bytes(data, settings.DEFAULT_CHARSET)
|
data = force_bytes(data, settings.DEFAULT_CHARSET)
|
||||||
r = {
|
r = {
|
||||||
'PATH_INFO': self._get_path(parsed),
|
'PATH_INFO': self._get_path(parsed),
|
||||||
'QUERY_STRING': force_str(parsed[4]),
|
|
||||||
'REQUEST_METHOD': str(method),
|
'REQUEST_METHOD': str(method),
|
||||||
}
|
}
|
||||||
if data:
|
if data:
|
||||||
@ -349,8 +337,12 @@ class RequestFactory(object):
|
|||||||
'wsgi.input': FakePayload(data),
|
'wsgi.input': FakePayload(data),
|
||||||
})
|
})
|
||||||
r.update(extra)
|
r.update(extra)
|
||||||
|
# If QUERY_STRING is absent or empty, we want to extract it from the URL.
|
||||||
|
if not r.get('QUERY_STRING'):
|
||||||
|
r['QUERY_STRING'] = force_str(parsed[4])
|
||||||
return self.request(**r)
|
return self.request(**r)
|
||||||
|
|
||||||
|
|
||||||
class Client(RequestFactory):
|
class Client(RequestFactory):
|
||||||
"""
|
"""
|
||||||
A class that can act as a client for testing purposes.
|
A class that can act as a client for testing purposes.
|
||||||
@ -392,7 +384,6 @@ class Client(RequestFactory):
|
|||||||
return {}
|
return {}
|
||||||
session = property(_session)
|
session = property(_session)
|
||||||
|
|
||||||
|
|
||||||
def request(self, **request):
|
def request(self, **request):
|
||||||
"""
|
"""
|
||||||
The master request method. Composes the environment dictionary
|
The master request method. Composes the environment dictionary
|
||||||
@ -485,12 +476,11 @@ class Client(RequestFactory):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def options(self, path, data='', content_type='application/octet-stream',
|
def options(self, path, data='', content_type='application/octet-stream',
|
||||||
follow=False, **extra):
|
follow=False, **extra):
|
||||||
"""
|
"""
|
||||||
Request a response from the server using OPTIONS.
|
Request a response from the server using OPTIONS.
|
||||||
"""
|
"""
|
||||||
response = super(Client, self).options(path,
|
response = super(Client, self).options(path, data=data, content_type=content_type, **extra)
|
||||||
data=data, content_type=content_type, **extra)
|
|
||||||
if follow:
|
if follow:
|
||||||
response = self._handle_redirects(response, **extra)
|
response = self._handle_redirects(response, **extra)
|
||||||
return response
|
return response
|
||||||
@ -500,14 +490,13 @@ class Client(RequestFactory):
|
|||||||
"""
|
"""
|
||||||
Send a resource to the server using PUT.
|
Send a resource to the server using PUT.
|
||||||
"""
|
"""
|
||||||
response = super(Client, self).put(path,
|
response = super(Client, self).put(path, data=data, content_type=content_type, **extra)
|
||||||
data=data, content_type=content_type, **extra)
|
|
||||||
if follow:
|
if follow:
|
||||||
response = self._handle_redirects(response, **extra)
|
response = self._handle_redirects(response, **extra)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def patch(self, path, data='', content_type='application/octet-stream',
|
def patch(self, path, data='', content_type='application/octet-stream',
|
||||||
follow=False, **extra):
|
follow=False, **extra):
|
||||||
"""
|
"""
|
||||||
Send a resource to the server using PATCH.
|
Send a resource to the server using PATCH.
|
||||||
"""
|
"""
|
||||||
@ -518,12 +507,12 @@ class Client(RequestFactory):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def delete(self, path, data='', content_type='application/octet-stream',
|
def delete(self, path, data='', content_type='application/octet-stream',
|
||||||
follow=False, **extra):
|
follow=False, **extra):
|
||||||
"""
|
"""
|
||||||
Send a DELETE request to the server.
|
Send a DELETE request to the server.
|
||||||
"""
|
"""
|
||||||
response = super(Client, self).delete(path,
|
response = super(Client, self).delete(
|
||||||
data=data, content_type=content_type, **extra)
|
path, data=data, content_type=content_type, **extra)
|
||||||
if follow:
|
if follow:
|
||||||
response = self._handle_redirects(response, **extra)
|
response = self._handle_redirects(response, **extra)
|
||||||
return response
|
return response
|
||||||
|
Loading…
Reference in New Issue
Block a user