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 语句之后加上以下代码:
- importBaseHTTPServer,SocketServer
- classHTTPServer(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
- fromdjango.core.management.baseimportBaseCommand,CommandError
- fromoptparseimportmake_option
- importos,sys
- importcherrypy
- fromcherrypyimportwsgiserver
- classCommand(BaseCommand):
- option_list=BaseCommand.option_list+(
- make_option('--noreload',action='store_false',dest='use_reloader',default=True,
- help='TellsDjangotoNOTusetheauto-reloader.'),
- make_option('--adminmedia',dest='admin_media_path',default='',
- help='Specifiesthedirectoryfromwhichtoserveadminmedia.'),
- )
- help="StartsalightweightWebserverfordevelopment."
- args='[optionalportnumber,oripaddr:port]'
- #Validationiscalledexplicitlyeachtimetheserverisreloaded.
- requires_model_validation=False
- defhandle(self,addrport='',*args,**options):
- importdjango
- fromdjango.core.servers.basehttpimportAdminMediaHandler
- fromdjango.core.handlers.wsgiimportWSGIHandler
- ifargs:
- raiseCommandError('Usageisrunservercp%s'%self.args)
- ifnotaddrport:
- addr=''
- port='8000'
- else:
- try:
- addr,port=addrport.split(':')
- exceptValueError:
- addr,port='',addrport
- ifnotaddr:
- addr='127.0.0.1'
- ifnotport.isdigit():
- raiseCommandError("%risnotavalidportnumber."%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'
- definner_run():
- fromdjango.confimportsettings
- fromdjango.utilsimporttranslation
- print"\nValidatingmodels..."
- self.validate(display_num_errors=True)
- print"\nDjangoversion%s,usingsettings%r"%(django.get_version(),settings.SETTINGS_MODULE)
- print"Developmentserverisrunningathttp://%s:%s/"%(addr,port)
- print"Quittheserverwith%s."%quit_command
- #django.core.management.baseforcesthelocaletoen-us.Weshould
- #setitupcorrectlyforthefirstrequest(particularlyimportant
- #inthe"--noreload"case).
- translation.activate(settings.LANGUAGE_CODE)
- try:
- path=admin_media_pathordjango.__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:
- ifshutdown_message:
- printshutdown_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不受影响。