Django自带的Development Server作为调试开发时的临时服务器是一个非常方便的工具,因为避免了在还没有代码之前就需要配置一大堆环境的麻烦。
但是此服务器也有一个不足的地方就是它是单线程模式的,也就是同时只能处理一个请求,当需要调试ajax应用时,这就显得非常麻烦了,因为这经常需要同时处理多个请求。
经过搜索,查找,简单的解决方法有以下两种:
1、修改Django自带的Development Server为多线程模式,这其实只需要改几行代码就可以了。(详见 http://code.djangoproject.com/ticket/3357 )
打开文件 django/core/servers/basehttp.py
第10行:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
修改为
from BaseHTTPServer import BaseHTTPRequestHandler
在所有的 import 语句之后加上以下代码:
import BaseHTTPServer, SocketServer class HTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): def __init__(self, server_address, RequestHandlerClass=None): BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass)
是的,这样就可以了。 但是他还有一个小问题就是它不是线程安全的。可能在请求很多时会出现数据不同步,当然,这一般不是问题,因为我们通常只在自己机器上调试时才用Development Server。
2、使用CherryPy 作为 Development Server
在安装好CherryPy 之后,将以下代码保存为文件runservercp.py
from django.core.management.base import BaseCommand, CommandError from optparse import make_option import os, sys import cherrypy from cherrypy import wsgiserver class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--noreload', action='store_false', dest='use_reloader', default=True, help='Tells Django to NOT use the auto-reloader.'), make_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media.'), ) help = "Starts a lightweight Web server for development." args = '[optional port number, or ipaddr:port]' # Validation is called explicitly each time the server is reloaded. requires_model_validation = False def handle(self, addrport='', *args, **options): import django from django.core.servers.basehttp import AdminMediaHandler from django.core.handlers.wsgi import WSGIHandler if args: raise CommandError('Usage is runservercp %s' % self.args) if not addrport: addr = '' port = '8000' else: try: addr, port = addrport.split(':') except ValueError: addr, port = '', addrport if not addr: addr = '127.0.0.1' if not port.isdigit(): raise CommandError("%r is not a valid port number." % port) use_reloader = options.get('use_reloader', True) admin_media_path = options.get('admin_media_path', '') shutdown_message = options.get('shutdown_message', '') quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' def inner_run(): from django.conf import settings from django.utils import translation print "\nValidating models..." self.validate(display_num_errors=True) print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE) print "Development server is running at http://%s:%s/" % (addr, port) print "Quit the server with %s." % quit_command # django.core.management.base forces the locale to en-us. We should # set it up correctly for the first request (particularly important # in the "--noreload" case). translation.activate(settings.LANGUAGE_CODE) try: path = admin_media_path or django.__path__[0] + '/contrib/admin/media' handler = AdminMediaHandler(WSGIHandler(), path) cherrypy.config.update({ 'server.socket_host': addr, 'server.socket_port': int(port), 'engine.autoreload_on': use_reloader }) cherrypy.tree.graft(handler, '/') cherrypy.engine.start() cherrypy.engine.block() finally: if shutdown_message: print shutdown_message cherrypy.engine.exit() inner_run()
将该文件放到djang源代码目录 django\core\management\commands 下,这样运行命令
python manage.py runservercp
时就使用了CherryPy 作为服务器了,其中命令名是根据文件的名字而定的,因为该文件保存为runservercp.py,所以命令名为 runservercp。
另外放在django的源代码目录的好处是所有的django project都可以使用该命令使用到CherryPy 。
另外一种放置方式是新建一个app,在该app下新建package management,再在该package下建另一package commands,将该文件放在commands 目录下(可参考django\contrib\auth 应用),同时在settings.py 中的 INSTALLED_APPS 加上该app,那么该project 就可以使用该命令了。其他project不受影响。