Index: django/http/__init__.py
===================================================================
--- django/http/__init__.py	(revision 10054)
+++ django/http/__init__.py	(working copy)
@@ -393,6 +393,20 @@
             raise Exception("This %s instance cannot tell its position" % self.__class__)
         return sum([len(chunk) for chunk in self._container])
 
+class HttpResponseSendFile(HttpResponse):
+    def __init__(self, path_to_file, content_type=None, block_size=8192):
+        if not content_type:
+            from mimetypes import guess_type
+            content_type = guess_type(path_to_file)[0]
+            if content_type is None:
+                content_type = "application/octet-stream"
+        super(HttpResponseSendFile, self).__init__(None,
+                content_type=content_type)
+        self.sendfile_filename = path_to_file
+        self.block_size = block_size
+        self._headers['content-length'] = ('Content-Length',
+                os.path.getsize(path_to_file))
+
 class HttpResponseRedirect(HttpResponse):
     status_code = 302
 
Index: django/core/servers/basehttp.py
===================================================================
--- django/core/servers/basehttp.py	(revision 10054)
+++ django/core/servers/basehttp.py	(working copy)
@@ -313,10 +313,9 @@
         in the event loop to iterate over the data, and to call
         'self.close()' once the response is finished.
         """
-        if not self.result_is_file() and not self.sendfile():
-            for data in self.result:
-                self.write(data)
-            self.finish_content()
+        for data in self.result:
+            self.write(data)
+        self.finish_content()
         self.close()
 
     def get_scheme(self):
Index: django/core/handlers/wsgi.py
===================================================================
--- django/core/handlers/wsgi.py	(revision 10054)
+++ django/core/handlers/wsgi.py	(working copy)
@@ -231,30 +231,30 @@
             self.initLock.release()
 
         set_script_prefix(base.get_script_name(environ))
-        signals.request_started.send(sender=self.__class__)
-        try:
-            try:
-                request = self.request_class(environ)
-            except UnicodeDecodeError:
-                response = http.HttpResponseBadRequest()
-            else:
-                response = self.get_response(request)
 
-                # Apply response middleware
-                for middleware_method in self._response_middleware:
-                    response = middleware_method(request, response)
-                response = self.apply_response_fixes(request, response)
-        finally:
-            signals.request_finished.send(sender=self.__class__)
+        response = self.process_request(environ)
 
         try:
             status_text = STATUS_CODE_TEXT[response.status_code]
         except KeyError:
             status_text = 'UNKNOWN STATUS CODE'
         status = '%s %s' % (response.status_code, status_text)
+
         response_headers = [(str(k), str(v)) for k, v in response.items()]
         for c in response.cookies.values():
             response_headers.append(('Set-Cookie', str(c.output(header=''))))
+
         start_response(status, response_headers)
+
+        if isinstance(response, http.HttpResponseSendFile):
+            filelike = open(response.sendfile_filename, 'rb')
+            if 'wsgi.file_wrapper' in environ:
+                return environ['wsgi.file_wrapper'](filelike,
+                        response.block_size)
+            else:
+                # wraps close() as well
+                from django.core.servers.basehttp import FileWrapper
+                return FileWrapper(filelike, response.block_size)
+
         return response
 
Index: django/core/handlers/base.py
===================================================================
--- django/core/handlers/base.py	(revision 10054)
+++ django/core/handlers/base.py	(working copy)
@@ -62,6 +62,26 @@
         # as a flag for initialization being complete.
         self._request_middleware = request_middleware
 
+    def process_request(self, request_env):
+        signals.request_started.send(sender=self.__class__)
+        try:
+            try:
+                request = self.request_class(request_env)
+            except UnicodeDecodeError:
+                response = http.HttpResponseBadRequest()
+            else:
+                response = self.get_response(request)
+
+                # Apply response middleware
+                if not isinstance(response, http.HttpResponseSendFile):
+                    for middleware_method in self._response_middleware:
+                        response = middleware_method(request, response)
+                    response = self.apply_response_fixes(request, response)
+        finally:
+            signals.request_finished.send(sender=self.__class__)
+
+        return response
+
     def get_response(self, request):
         "Returns an HttpResponse object for the given HttpRequest"
         from django.core import exceptions, urlresolvers
Index: django/core/handlers/modpython.py
===================================================================
--- django/core/handlers/modpython.py	(revision 10054)
+++ django/core/handlers/modpython.py	(working copy)
@@ -2,7 +2,6 @@
 from pprint import pformat
 
 from django import http
-from django.core import signals
 from django.core.handlers.base import BaseHandler
 from django.core.urlresolvers import set_script_prefix
 from django.utils import datastructures
@@ -191,21 +190,8 @@
             self.load_middleware()
 
         set_script_prefix(req.get_options().get('django.root', ''))
-        signals.request_started.send(sender=self.__class__)
-        try:
-            try:
-                request = self.request_class(req)
-            except UnicodeDecodeError:
-                response = http.HttpResponseBadRequest()
-            else:
-                response = self.get_response(request)
 
-                # Apply response middleware
-                for middleware_method in self._response_middleware:
-                    response = middleware_method(request, response)
-                response = self.apply_response_fixes(request, response)
-        finally:
-            signals.request_finished.send(sender=self.__class__)
+        response = self.process_request(req)
 
         # Convert our custom HttpResponse object back into the mod_python req.
         req.content_type = response['Content-Type']
@@ -215,12 +201,16 @@
         for c in response.cookies.values():
             req.headers_out.add('Set-Cookie', c.output(header=''))
         req.status = response.status_code
-        try:
-            for chunk in response:
-                req.write(chunk)
-        finally:
-            response.close()
 
+        if isinstance(response, http.HttpResponseSendFile):
+            req.sendfile(response.sendfile_filename)
+        else:
+            try:
+                for chunk in response:
+                    req.write(chunk)
+            finally:
+                response.close()
+
         return 0 # mod_python.apache.OK
 
 def handler(req):
