web/lib/django/test/client.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
    64             self.load_middleware()
    64             self.load_middleware()
    65 
    65 
    66         signals.request_started.send(sender=self.__class__)
    66         signals.request_started.send(sender=self.__class__)
    67         try:
    67         try:
    68             request = WSGIRequest(environ)
    68             request = WSGIRequest(environ)
       
    69             # sneaky little hack so that we can easily get round
       
    70             # CsrfViewMiddleware.  This makes life easier, and is probably
       
    71             # required for backwards compatibility with external tests against
       
    72             # admin views.
       
    73             request._dont_enforce_csrf_checks = True
    69             response = self.get_response(request)
    74             response = self.get_response(request)
    70 
    75 
    71             # Apply response middleware.
    76             # Apply response middleware.
    72             for middleware_method in self._response_middleware:
    77             for middleware_method in self._response_middleware:
    73                 response = middleware_method(request, response)
    78                 response = middleware_method(request, response)
   191         and passes to the handler, returning the result of the handler.
   196         and passes to the handler, returning the result of the handler.
   192         Assumes defaults for the query environment, which can be overridden
   197         Assumes defaults for the query environment, which can be overridden
   193         using the arguments to the request.
   198         using the arguments to the request.
   194         """
   199         """
   195         environ = {
   200         environ = {
   196             'HTTP_COOKIE':      self.cookies,
   201             'HTTP_COOKIE':       self.cookies.output(header='', sep='; '),
   197             'PATH_INFO':         '/',
   202             'PATH_INFO':         '/',
   198             'QUERY_STRING':      '',
   203             'QUERY_STRING':      '',
   199             'REMOTE_ADDR':       '127.0.0.1',
   204             'REMOTE_ADDR':       '127.0.0.1',
   200             'REQUEST_METHOD':    'GET',
   205             'REQUEST_METHOD':    'GET',
   201             'SCRIPT_NAME':       '',
   206             'SCRIPT_NAME':       '',
   214 
   219 
   215         # Curry a data dictionary into an instance of the template renderer
   220         # Curry a data dictionary into an instance of the template renderer
   216         # callback function.
   221         # callback function.
   217         data = {}
   222         data = {}
   218         on_template_render = curry(store_rendered_templates, data)
   223         on_template_render = curry(store_rendered_templates, data)
   219         signals.template_rendered.connect(on_template_render)
   224         signals.template_rendered.connect(on_template_render, dispatch_uid="template-render")
   220 
       
   221         # Capture exceptions created by the handler.
   225         # Capture exceptions created by the handler.
   222         got_request_exception.connect(self.store_exc_info)
   226         got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
   223 
       
   224         try:
   227         try:
   225             response = self.handler(environ)
   228 
   226         except TemplateDoesNotExist, e:
   229             try:
   227             # If the view raises an exception, Django will attempt to show
   230                 response = self.handler(environ)
   228             # the 500.html template. If that template is not available,
   231             except TemplateDoesNotExist, e:
   229             # we should ignore the error in favor of re-raising the
   232                 # If the view raises an exception, Django will attempt to show
   230             # underlying exception that caused the 500 error. Any other
   233                 # the 500.html template. If that template is not available,
   231             # template found to be missing during view error handling
   234                 # we should ignore the error in favor of re-raising the
   232             # should be reported as-is.
   235                 # underlying exception that caused the 500 error. Any other
   233             if e.args != ('500.html',):
   236                 # template found to be missing during view error handling
   234                 raise
   237                 # should be reported as-is.
   235 
   238                 if e.args != ('500.html',):
   236         # Look for a signalled exception, clear the current context
   239                     raise
   237         # exception data, then re-raise the signalled exception.
   240 
   238         # Also make sure that the signalled exception is cleared from
   241             # Look for a signalled exception, clear the current context
   239         # the local cache!
   242             # exception data, then re-raise the signalled exception.
   240         if self.exc_info:
   243             # Also make sure that the signalled exception is cleared from
   241             exc_info = self.exc_info
   244             # the local cache!
   242             self.exc_info = None
   245             if self.exc_info:
   243             raise exc_info[1], None, exc_info[2]
   246                 exc_info = self.exc_info
   244 
   247                 self.exc_info = None
   245         # Save the client and request that stimulated the response.
   248                 raise exc_info[1], None, exc_info[2]
   246         response.client = self
   249 
   247         response.request = request
   250             # Save the client and request that stimulated the response.
   248 
   251             response.client = self
   249         # Add any rendered template detail to the response.
   252             response.request = request
   250         # If there was only one template rendered (the most likely case),
   253 
   251         # flatten the list to a single element.
   254             # Add any rendered template detail to the response.
   252         for detail in ('template', 'context'):
   255             # If there was only one template rendered (the most likely case),
   253             if data.get(detail):
   256             # flatten the list to a single element.
   254                 if len(data[detail]) == 1:
   257             for detail in ('template', 'context'):
   255                     setattr(response, detail, data[detail][0]);
   258                 if data.get(detail):
       
   259                     if len(data[detail]) == 1:
       
   260                         setattr(response, detail, data[detail][0]);
       
   261                     else:
       
   262                         setattr(response, detail, data[detail])
   256                 else:
   263                 else:
   257                     setattr(response, detail, data[detail])
   264                     setattr(response, detail, None)
   258             else:
   265 
   259                 setattr(response, detail, None)
   266             # Update persistent cookie data.
   260 
   267             if response.cookies:
   261         # Update persistent cookie data.
   268                 self.cookies.update(response.cookies)
   262         if response.cookies:
   269 
   263             self.cookies.update(response.cookies)
   270             return response
   264 
   271         finally:
   265         return response
   272             signals.template_rendered.disconnect(dispatch_uid="template-render")
       
   273             got_request_exception.disconnect(dispatch_uid="request-exception")
       
   274 
   266 
   275 
   267     def get(self, path, data={}, follow=False, **extra):
   276     def get(self, path, data={}, follow=False, **extra):
   268         """
   277         """
   269         Requests a response from the server using GET.
   278         Requests a response from the server using GET.
   270         """
   279         """
   360         if content_type is MULTIPART_CONTENT:
   369         if content_type is MULTIPART_CONTENT:
   361             post_data = encode_multipart(BOUNDARY, data)
   370             post_data = encode_multipart(BOUNDARY, data)
   362         else:
   371         else:
   363             post_data = data
   372             post_data = data
   364 
   373 
       
   374         # Make `data` into a querystring only if it's not already a string. If
       
   375         # it is a string, we'll assume that the caller has already encoded it.
       
   376         query_string = None
       
   377         if not isinstance(data, basestring):
       
   378             query_string = urlencode(data, doseq=True)
       
   379 
   365         parsed = urlparse(path)
   380         parsed = urlparse(path)
   366         r = {
   381         r = {
   367             'CONTENT_LENGTH': len(post_data),
   382             'CONTENT_LENGTH': len(post_data),
   368             'CONTENT_TYPE':   content_type,
   383             'CONTENT_TYPE':   content_type,
   369             'PATH_INFO':      urllib.unquote(parsed[2]),
   384             'PATH_INFO':      urllib.unquote(parsed[2]),
   370             'QUERY_STRING':   urlencode(data, doseq=True) or parsed[4],
   385             'QUERY_STRING':   query_string or parsed[4],
   371             'REQUEST_METHOD': 'PUT',
   386             'REQUEST_METHOD': 'PUT',
   372             'wsgi.input':     FakePayload(post_data),
   387             'wsgi.input':     FakePayload(post_data),
   373         }
   388         }
   374         r.update(extra)
   389         r.update(extra)
   375 
   390 
   414             if self.session:
   429             if self.session:
   415                 request.session = self.session
   430                 request.session = self.session
   416             else:
   431             else:
   417                 request.session = engine.SessionStore()
   432                 request.session = engine.SessionStore()
   418             login(request, user)
   433             login(request, user)
       
   434 
       
   435             # Save the session values.
       
   436             request.session.save()
   419 
   437 
   420             # Set the cookie to represent the session.
   438             # Set the cookie to represent the session.
   421             session_cookie = settings.SESSION_COOKIE_NAME
   439             session_cookie = settings.SESSION_COOKIE_NAME
   422             self.cookies[session_cookie] = request.session.session_key
   440             self.cookies[session_cookie] = request.session.session_key
   423             cookie_data = {
   441             cookie_data = {
   427                 'secure': settings.SESSION_COOKIE_SECURE or None,
   445                 'secure': settings.SESSION_COOKIE_SECURE or None,
   428                 'expires': None,
   446                 'expires': None,
   429             }
   447             }
   430             self.cookies[session_cookie].update(cookie_data)
   448             self.cookies[session_cookie].update(cookie_data)
   431 
   449 
   432             # Save the session values.
       
   433             request.session.save()
       
   434 
       
   435             return True
   450             return True
   436         else:
   451         else:
   437             return False
   452             return False
   438 
   453 
   439     def logout(self):
   454     def logout(self):
   457             scheme, netloc, path, query, fragment = urlsplit(url)
   472             scheme, netloc, path, query, fragment = urlsplit(url)
   458 
   473 
   459             redirect_chain = response.redirect_chain
   474             redirect_chain = response.redirect_chain
   460             redirect_chain.append((url, response.status_code))
   475             redirect_chain.append((url, response.status_code))
   461 
   476 
       
   477             extra = {}
       
   478             if scheme:
       
   479                 extra['wsgi.url_scheme'] = scheme
       
   480 
   462             # The test client doesn't handle external links,
   481             # The test client doesn't handle external links,
   463             # but since the situation is simulated in test_client,
   482             # but since the situation is simulated in test_client,
   464             # we fake things here by ignoring the netloc portion of the
   483             # we fake things here by ignoring the netloc portion of the
   465             # redirected URL.
   484             # redirected URL.
   466             response = self.get(path, QueryDict(query), follow=False)
   485             response = self.get(path, QueryDict(query), follow=False, **extra)
   467             response.redirect_chain = redirect_chain
   486             response.redirect_chain = redirect_chain
   468 
   487 
   469             # Prevent loops
   488             # Prevent loops
   470             if response.redirect_chain[-1] in response.redirect_chain[0:-1]:
   489             if response.redirect_chain[-1] in response.redirect_chain[0:-1]:
   471                 break
   490                 break