1
1
from django .conf import settings
2
- from django .core .management .base import BaseCommand , CommandError , handle_default_options
2
+ from django .core .management .commands .runserver import Command as BaseCommand
3
+ from django .core .management .base import CommandError , handle_default_options
3
4
from django .core .servers .basehttp import WSGIServerException , WSGIServer
4
5
from django .core .handlers .wsgi import WSGIHandler
5
6
6
7
import os
7
8
import sys
8
- import django
9
9
import imp
10
10
import SocketServer
11
11
from optparse import make_option
14
14
from devserver .utils .http import SlimWSGIRequestHandler
15
15
16
16
17
+ STATICFILES_APPS = ('django.contrib.staticfiles' , 'staticfiles' )
18
+
19
+
17
20
def null_technical_500_response (request , exc_type , exc_value , tb ):
18
21
raise exc_type , exc_value , tb
19
22
20
23
21
- def run (addr , port , wsgi_handler , mixin = None ):
24
+ def run (addr , port , wsgi_handler , mixin = None , ipv6 = False ):
22
25
if mixin :
23
26
class new (mixin , WSGIServer ):
24
27
def __init__ (self , * args , ** kwargs ):
@@ -27,29 +30,30 @@ def __init__(self, *args, **kwargs):
27
30
new = WSGIServer
28
31
server_address = (addr , port )
29
32
new .request_queue_size = 10
30
- httpd = new (server_address , SlimWSGIRequestHandler )
33
+ httpd = new (server_address , SlimWSGIRequestHandler , ipv6 = ipv6 )
31
34
httpd .set_app (wsgi_handler )
32
35
httpd .serve_forever ()
33
36
34
37
35
38
class Command (BaseCommand ):
36
39
option_list = BaseCommand .option_list + (
37
- make_option ('--noreload' , action = 'store_false' , dest = 'use_reloader' , default = True ,
38
- help = 'Tells Django to NOT use the auto-reloader.' ),
39
- make_option ('--werkzeug' , action = 'store_true' , dest = 'use_werkzeug' , default = False ,
40
+ make_option (
41
+ '--werkzeug' , action = 'store_true' , dest = 'use_werkzeug' , default = False ,
40
42
help = 'Tells Django to use the Werkzeug interactive debugger.' ),
41
- make_option ('--adminmedia' , dest = 'admin_media_path' , default = '' ,
42
- help = 'Specifies the directory from which to serve admin media.' ),
43
- make_option ('--forked' , action = 'store_true' , dest = 'use_forked' , default = False ,
43
+ make_option (
44
+ '--forked' , action = 'store_true' , dest = 'use_forked' , default = False ,
44
45
help = 'Use forking instead of threading for multiple web requests.' ),
45
- make_option ('--dozer' , action = 'store_true' , dest = 'use_dozer' , default = False ,
46
+ make_option (
47
+ '--dozer' , action = 'store_true' , dest = 'use_dozer' , default = False ,
46
48
help = 'Enable the Dozer memory debugging middleware.' ),
47
- make_option ('--wsgi-app' , dest = 'wsgi_app' , default = None ,
49
+ make_option (
50
+ '--wsgi-app' , dest = 'wsgi_app' , default = None ,
48
51
help = 'Load the specified WSGI app as the server endpoint.' ),
49
52
)
50
- if any (map (lambda app : app in settings .INSTALLED_APPS , ('django.contrib.staticfiles' , 'staticfiles' , ))):
51
- option_list += make_option ('--nostatic' , dest = 'use_static_files' , default = True ,
52
- help = 'Tells Django to NOT automatically serve static files at STATIC_URL.' ),
53
+ if any (map (lambda app : app in settings .INSTALLED_APPS , STATICFILES_APPS )):
54
+ option_list += make_option (
55
+ '--nostatic' , dest = 'use_static_files' , action = 'store_false' , default = True ,
56
+ help = 'Tells Django to NOT automatically serve static files at STATIC_URL.' ),
53
57
54
58
help = "Starts a lightweight Web server for development which outputs additional debug information."
55
59
args = '[optional port number, or ipaddr:port]'
@@ -75,135 +79,132 @@ def handle(self, addrport='', *args, **options):
75
79
raise CommandError ('Usage is runserver %s' % self .args )
76
80
77
81
if not addrport :
78
- addr = getattr (settings , 'DEVSERVER_DEFAULT_ADDR' , '' )
82
+ addr = getattr (settings , 'DEVSERVER_DEFAULT_ADDR' , '127.0.0.1 ' )
79
83
port = getattr (settings , 'DEVSERVER_DEFAULT_PORT' , '8000' )
84
+ addrport = '%s:%s' % (addr , port )
85
+
86
+ return super (Command , self ).handle (addrport = addrport , * args , ** options )
87
+
88
+ def get_handler (self , * args , ** options ):
89
+ if int (options ['verbosity' ]) < 1 :
90
+ handler = WSGIHandler ()
80
91
else :
81
- try :
82
- addr , port = addrport .split (':' )
83
- except ValueError :
84
- addr , port = '' , addrport
85
- if not addr :
86
- addr = '127.0.0.1'
92
+ handler = DevServerHandler ()
93
+
94
+ # AdminMediaHandler is removed in Django 1.5
95
+ # Add it only when it avialable.
96
+ try :
97
+ from django .core .servers .basehttp import AdminMediaHandler
98
+ except ImportError :
99
+ pass
100
+ else :
101
+ handler = AdminMediaHandler (
102
+ handler , options ['admin_media_path' ])
87
103
88
- if not port .isdigit ():
89
- raise CommandError ("%r is not a valid port number." % port )
104
+ if 'django.contrib.staticfiles' in settings .INSTALLED_APPS and options ['use_static_files' ]:
105
+ from django .contrib .staticfiles .handlers import StaticFilesHandler
106
+ handler = StaticFilesHandler (handler )
107
+
108
+ return handler
109
+
110
+ def inner_run (self , * args , ** options ):
111
+ # Flag the server as active
112
+ from devserver import settings
113
+ import devserver
114
+ settings .DEVSERVER_ACTIVE = True
115
+ settings .DEBUG = True
116
+
117
+ from django .conf import settings
118
+ from django .utils import translation
90
119
91
- use_reloader = options .get ('use_reloader' , True )
92
- admin_media_path = options .get ('admin_media_path' , '' )
93
120
shutdown_message = options .get ('shutdown_message' , '' )
94
121
use_werkzeug = options .get ('use_werkzeug' , False )
95
122
quit_command = (sys .platform == 'win32' ) and 'CTRL-BREAK' or 'CONTROL-C'
96
123
wsgi_app = options .get ('wsgi_app' , None )
97
- use_static_files = options .get ('use_static_files' , True )
98
124
99
125
if use_werkzeug :
100
126
try :
101
127
from werkzeug import run_simple , DebuggedApplication
102
128
except ImportError , e :
103
- print >> sys .stderr , "WARNING: Unable to initialize werkzeug: %s" % e
129
+ self .stderr . write ( "WARNING: Unable to initialize werkzeug: %s\n " % e )
104
130
use_werkzeug = False
105
131
else :
106
- use_werkzeug = True
107
132
from django .views import debug
108
133
debug .technical_500_response = null_technical_500_response
109
134
110
- def inner_run ():
111
- # Flag the server as active
112
- from devserver import settings
113
- import devserver
114
- settings .DEVSERVER_ACTIVE = True
115
- settings .DEBUG = True
116
-
117
- from django .conf import settings
118
- from django .utils import translation
119
-
120
- print "Validating models..."
121
- self .validate (display_num_errors = True )
122
- print "\n Django version %s, using settings %r" % (django .get_version (), settings .SETTINGS_MODULE )
123
- print "Running django-devserver %s" % (devserver .get_version (),)
124
- if use_werkzeug :
125
- server_type = 'werkzeug'
135
+ self .stdout .write ("Validating models...\n \n " )
136
+ self .validate (display_num_errors = True )
137
+ self .stdout .write ((
138
+ "Django version %(version)s, using settings %(settings)r\n "
139
+ "Running django-devserver %(devserver_version)s\n "
140
+ "%(server_model)s %(server_type)s server is running at http://%(addr)s:%(port)s/\n "
141
+ "Quit the server with %(quit_command)s.\n "
142
+ ) % {
143
+ "server_type" : use_werkzeug and 'werkzeug' or 'Django' ,
144
+ "server_model" : options ['use_forked' ] and 'Forked' or 'Threaded' ,
145
+ "version" : self .get_version (),
146
+ "devserver_version" : devserver .get_version (),
147
+ "settings" : settings .SETTINGS_MODULE ,
148
+ "addr" : self ._raw_ipv6 and '[%s]' % self .addr or self .addr ,
149
+ "port" : self .port ,
150
+ "quit_command" : quit_command ,
151
+ })
152
+
153
+ # django.core.management.base forces the locale to en-us. We should
154
+ # set it up correctly for the first request (particularly important
155
+ # in the "--noreload" case).
156
+ translation .activate (settings .LANGUAGE_CODE )
157
+
158
+ app = self .get_handler (* args , ** options )
159
+ if wsgi_app :
160
+ self .stdout .write ("Using WSGI application %r\n " % wsgi_app )
161
+ if os .path .exists (os .path .abspath (wsgi_app )):
162
+ # load from file
163
+ app = imp .load_source ('wsgi_app' , os .path .abspath (wsgi_app )).application
126
164
else :
127
- server_type = 'django'
128
- print "%s %s server is running at http://%s:%s/" % (options ['use_forked' ] and 'Forked' or 'Threaded' , server_type , addr , port )
129
- print "Quit the server with %s." % quit_command
165
+ try :
166
+ app = __import__ (wsgi_app , {}, {}, ['application' ]).application
167
+ except (ImportError , AttributeError ):
168
+ raise
130
169
131
- # django.core.management.base forces the locale to en-us. We should
132
- # set it up correctly for the first request (particularly important
133
- # in the "--noreload" case).
134
- translation . activate ( settings . LANGUAGE_CODE )
170
+ if options [ 'use_forked' ]:
171
+ mixin = SocketServer . ForkingMixIn
172
+ else :
173
+ mixin = SocketServer . ThreadingMixIn
135
174
136
- if int (options ['verbosity' ]) < 1 :
137
- app = WSGIHandler ()
138
- else :
139
- app = DevServerHandler ()
140
-
141
- if wsgi_app :
142
- print "Using WSGI application %r" % wsgi_app
143
- if os .path .exists (os .path .abspath (wsgi_app )):
144
- # load from file
145
- app = imp .load_source ('wsgi_app' , os .path .abspath (wsgi_app )).application
146
- else :
147
- try :
148
- app = __import__ (wsgi_app , {}, {}, ['application' ]).application
149
- except (ImportError , AttributeError ):
150
- raise
151
-
152
- if options ['use_forked' ]:
153
- mixin = SocketServer .ForkingMixIn
154
- else :
155
- mixin = SocketServer .ThreadingMixIn
175
+ middleware = getattr (settings , 'DEVSERVER_WSGI_MIDDLEWARE' , [])
176
+ for middleware in middleware :
177
+ module , class_name = middleware .rsplit ('.' , 1 )
178
+ app = getattr (__import__ (module , {}, {}, [class_name ]), class_name )(app )
156
179
157
- middleware = getattr (settings , 'DEVSERVER_WSGI_MIDDLEWARE' , [])
158
- for middleware in middleware :
159
- module , class_name = middleware .rsplit ('.' , 1 )
160
- app = getattr (__import__ (module , {}, {}, [class_name ]), class_name )(app )
180
+ if options ['use_dozer' ]:
181
+ from dozer import Dozer
182
+ app = Dozer (app )
161
183
162
- if 'django.contrib.staticfiles' in settings .INSTALLED_APPS and use_static_files :
163
- from django .contrib .staticfiles .handlers import StaticFilesHandler
164
- app = StaticFilesHandler (app )
184
+ try :
185
+ if use_werkzeug :
186
+ run_simple (
187
+ self .addr , int (self .port ), DebuggedApplication (app , True ),
188
+ use_reloader = False , use_debugger = True )
165
189
else :
166
- # AdminMediaHandler is removed in Django 1.5
167
- # Add it only when it avialable.
168
- try :
169
- from django .core .servers .basehttp import AdminMediaHandler
170
- except ImportError :
171
- pass
172
- else :
173
- app = AdminMediaHandler (app , admin_media_path )
174
-
175
- if options ['use_dozer' ]:
176
- from dozer import Dozer
177
- app = Dozer (app )
178
-
190
+ run (self .addr , int (self .port ), app , mixin , ipv6 = options ['use_ipv6' ])
191
+
192
+ except WSGIServerException , e :
193
+ # Use helpful error messages instead of ugly tracebacks.
194
+ ERRORS = {
195
+ 13 : "You don't have permission to access that port." ,
196
+ 98 : "That port is already in use." ,
197
+ 99 : "That IP address can't be assigned-to." ,
198
+ }
179
199
try :
180
- if use_werkzeug :
181
- run_simple (addr , int (port ), DebuggedApplication (app , True ),
182
- use_reloader = False , use_debugger = True )
183
- else :
184
- run (addr , int (port ), app , mixin )
185
- except WSGIServerException , e :
186
- # Use helpful error messages instead of ugly tracebacks.
187
- ERRORS = {
188
- 13 : "You don't have permission to access that port." ,
189
- 98 : "That port is already in use." ,
190
- 99 : "That IP address can't be assigned-to." ,
191
- }
192
- try :
193
- error_text = ERRORS [e .args [0 ].args [0 ]]
194
- except (AttributeError , KeyError ):
195
- error_text = str (e )
196
- sys .stderr .write (self .style .ERROR ("Error: %s" % error_text ) + '\n ' )
197
- # Need to use an OS exit because sys.exit doesn't work in a thread
198
- os ._exit (1 )
199
- except KeyboardInterrupt :
200
- if shutdown_message :
201
- print shutdown_message
202
- sys .exit (0 )
203
-
204
- # werkzeug does its own autoreload stuff
205
- if use_reloader :
206
- from django .utils import autoreload
207
- autoreload .main (inner_run )
208
- else :
209
- inner_run ()
200
+ error_text = ERRORS [e .args [0 ].args [0 ]]
201
+ except (AttributeError , KeyError ):
202
+ error_text = str (e )
203
+ sys .stderr .write (self .style .ERROR ("Error: %s" % error_text ) + '\n ' )
204
+ # Need to use an OS exit because sys.exit doesn't work in a thread
205
+ os ._exit (1 )
206
+
207
+ except KeyboardInterrupt :
208
+ if shutdown_message :
209
+ self .stdout .write ("%s\n " % shutdown_message )
210
+ sys .exit (0 )
0 commit comments