Refactored runserver command and moved code related to staticfiles to a subclass that is enabled if staticfiles app is installed.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14553 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1ed62706e7
commit
e9f3899b20
|
@ -0,0 +1,27 @@
|
||||||
|
from optparse import make_option
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.commands.runserver import BaseRunserverCommand
|
||||||
|
|
||||||
|
from django.contrib.staticfiles.handlers import StaticFilesHandler
|
||||||
|
|
||||||
|
class Command(BaseRunserverCommand):
|
||||||
|
option_list = BaseRunserverCommand.option_list + (
|
||||||
|
make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
|
||||||
|
help='Tells Django to NOT automatically serve static files at STATICFILES_URL.'),
|
||||||
|
make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
|
||||||
|
help='Allows serving static files even if DEBUG is False.'),
|
||||||
|
)
|
||||||
|
help = "Starts a lightweight Web server for development, including static files serving."
|
||||||
|
|
||||||
|
def get_handler(self, *args, **options):
|
||||||
|
"""
|
||||||
|
Returns the static files serving handler.
|
||||||
|
"""
|
||||||
|
handler = super(Command, self).get_handler(*args, **options)
|
||||||
|
use_static_handler = options.get('use_static_handler', True)
|
||||||
|
insecure_serving = options.get('insecure_serving', False)
|
||||||
|
if (settings.DEBUG and use_static_handler or
|
||||||
|
(use_static_handler and insecure_serving)):
|
||||||
|
handler = StaticFilesHandler(handler)
|
||||||
|
return handler
|
|
@ -1,20 +1,16 @@
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
|
from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException
|
||||||
|
from django.utils import autoreload
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class BaseRunserverCommand(BaseCommand):
|
||||||
option_list = BaseCommand.option_list + (
|
option_list = BaseCommand.option_list + (
|
||||||
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
|
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
|
||||||
help='Tells Django to NOT use the auto-reloader.'),
|
help='Tells Django to NOT use the auto-reloader.'),
|
||||||
make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
|
|
||||||
help='Tells Django to NOT automatically serve static files at STATICFILES_URL.'),
|
|
||||||
make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
|
|
||||||
help='Allows serving static files even if DEBUG is False.'),
|
|
||||||
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."
|
help = "Starts a lightweight Web server for development."
|
||||||
args = '[optional port number, or ipaddr:port]'
|
args = '[optional port number, or ipaddr:port]'
|
||||||
|
@ -22,79 +18,98 @@ class Command(BaseCommand):
|
||||||
# Validation is called explicitly each time the server is reloaded.
|
# Validation is called explicitly each time the server is reloaded.
|
||||||
requires_model_validation = False
|
requires_model_validation = False
|
||||||
|
|
||||||
|
def get_handler(self, *args, **options):
|
||||||
|
"""
|
||||||
|
Returns the default WSGI handler for the runner.
|
||||||
|
"""
|
||||||
|
return WSGIHandler()
|
||||||
|
|
||||||
def handle(self, addrport='', *args, **options):
|
def handle(self, addrport='', *args, **options):
|
||||||
import django
|
|
||||||
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
|
||||||
from django.contrib.staticfiles.handlers import StaticFilesHandler
|
|
||||||
if args:
|
if args:
|
||||||
raise CommandError('Usage is runserver %s' % self.args)
|
raise CommandError('Usage is runserver %s' % self.args)
|
||||||
if not addrport:
|
if not addrport:
|
||||||
addr = ''
|
self.addr = ''
|
||||||
port = '8000'
|
self.port = '8000'
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
addr, port = addrport.split(':')
|
self.addr, self.port = addrport.split(':')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
addr, port = '', addrport
|
self.addr, self.port = '', addrport
|
||||||
if not addr:
|
if not self.addr:
|
||||||
addr = '127.0.0.1'
|
self.addr = '127.0.0.1'
|
||||||
|
|
||||||
if not port.isdigit():
|
if not self.port.isdigit():
|
||||||
raise CommandError("%r is not a valid port number." % port)
|
raise CommandError("%r is not a valid port number." % self.port)
|
||||||
|
|
||||||
|
self.run(*args, **options)
|
||||||
|
|
||||||
|
def run(self, *args, **options):
|
||||||
|
"""
|
||||||
|
Runs the server, using the autoreloader if needed
|
||||||
|
"""
|
||||||
use_reloader = options.get('use_reloader', True)
|
use_reloader = options.get('use_reloader', True)
|
||||||
admin_media_path = options.get('admin_media_path', '')
|
|
||||||
shutdown_message = options.get('shutdown_message', '')
|
|
||||||
use_static_handler = options.get('use_static_handler', True)
|
|
||||||
insecure_serving = options.get('insecure_serving', False)
|
|
||||||
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 "Validating 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:
|
|
||||||
handler = WSGIHandler()
|
|
||||||
allow_serving = (settings.DEBUG and use_static_handler or
|
|
||||||
(use_static_handler and insecure_serving))
|
|
||||||
if (allow_serving and
|
|
||||||
"django.contrib.staticfiles" in settings.INSTALLED_APPS):
|
|
||||||
handler = StaticFilesHandler(handler)
|
|
||||||
# serve admin media like old-school (deprecation pending)
|
|
||||||
handler = AdminMediaHandler(handler, admin_media_path)
|
|
||||||
run(addr, int(port), handler)
|
|
||||||
except WSGIServerException, e:
|
|
||||||
# Use helpful error messages instead of ugly tracebacks.
|
|
||||||
ERRORS = {
|
|
||||||
13: "You don't have permission to access that port.",
|
|
||||||
98: "That port is already in use.",
|
|
||||||
99: "That IP address can't be assigned-to.",
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
error_text = ERRORS[e.args[0].args[0]]
|
|
||||||
except (AttributeError, KeyError):
|
|
||||||
error_text = str(e)
|
|
||||||
sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
|
|
||||||
# Need to use an OS exit because sys.exit doesn't work in a thread
|
|
||||||
os._exit(1)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
if shutdown_message:
|
|
||||||
print shutdown_message
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if use_reloader:
|
if use_reloader:
|
||||||
from django.utils import autoreload
|
autoreload.main(self.inner_run, args, options)
|
||||||
autoreload.main(inner_run)
|
|
||||||
else:
|
else:
|
||||||
inner_run()
|
self.inner_run(*args, **options)
|
||||||
|
|
||||||
|
def inner_run(self, *args, **options):
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import translation
|
||||||
|
|
||||||
|
shutdown_message = options.get('shutdown_message', '')
|
||||||
|
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
|
||||||
|
|
||||||
|
self.stdout.write("Validating models...\n\n")
|
||||||
|
self.validate(display_num_errors=True)
|
||||||
|
self.stdout.write((
|
||||||
|
"Django version %(version)s, using settings %(settings)r\n"
|
||||||
|
"Development server is running at http://%(addr)s:%(port)s/\n"
|
||||||
|
"Quit the server with %(quit_command)s.\n"
|
||||||
|
) % {
|
||||||
|
"version": self.get_version(),
|
||||||
|
"settings": settings.SETTINGS_MODULE,
|
||||||
|
"addr": self.addr,
|
||||||
|
"port": self.port,
|
||||||
|
"quit_command": 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:
|
||||||
|
handler = self.get_handler(*args, **options)
|
||||||
|
run(self.addr, int(self.port), handler)
|
||||||
|
except WSGIServerException, e:
|
||||||
|
# Use helpful error messages instead of ugly tracebacks.
|
||||||
|
ERRORS = {
|
||||||
|
13: "You don't have permission to access that port.",
|
||||||
|
98: "That port is already in use.",
|
||||||
|
99: "That IP address can't be assigned-to.",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
error_text = ERRORS[e.args[0].args[0]]
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
error_text = str(e)
|
||||||
|
sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
|
||||||
|
# Need to use an OS exit because sys.exit doesn't work in a thread
|
||||||
|
os._exit(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
if shutdown_message:
|
||||||
|
self.stdout.write("%s\n" % shutdown_message)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
class Command(BaseRunserverCommand):
|
||||||
|
option_list = BaseRunserverCommand.option_list + (
|
||||||
|
make_option('--adminmedia', dest='admin_media_path', default='',
|
||||||
|
help='Specifies the directory from which to serve admin media.'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_handler(self, *args, **options):
|
||||||
|
"""
|
||||||
|
Serves admin media like old-school (deprecation pending).
|
||||||
|
"""
|
||||||
|
handler = super(Command, self).get_handler(*args, **options)
|
||||||
|
return AdminMediaHandler(handler, options.get('admin_media_path', ''))
|
||||||
|
|
|
@ -164,6 +164,12 @@ Do not prompt the user for input.
|
||||||
.I \-\-noreload
|
.I \-\-noreload
|
||||||
Disable the development server's auto\-reloader.
|
Disable the development server's auto\-reloader.
|
||||||
.TP
|
.TP
|
||||||
|
.I \-\-nostatic
|
||||||
|
Disable automatic serving of static files from STATICFILES_URL.
|
||||||
|
.TP
|
||||||
|
.I \-\-insecure
|
||||||
|
Enables serving of static files even if DEBUG is False.
|
||||||
|
.TP
|
||||||
.I \-\-verbosity=VERBOSITY
|
.I \-\-verbosity=VERBOSITY
|
||||||
Verbosity level: 0=minimal output, 1=normal output, 2=all output.
|
Verbosity level: 0=minimal output, 1=normal output, 2=all output.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -684,7 +684,9 @@ Example usage::
|
||||||
.. django-admin-option:: --nostatic
|
.. django-admin-option:: --nostatic
|
||||||
|
|
||||||
Use the ``--nostatic`` option to disable serving of static files with the
|
Use the ``--nostatic`` option to disable serving of static files with the
|
||||||
:doc:`staticfiles </ref/contrib/staticfiles>` app entirely.
|
:doc:`staticfiles </ref/contrib/staticfiles>` app entirely. This option is
|
||||||
|
only available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
|
||||||
|
in your project's :setting:`INSTALLED_APPS` setting.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
|
@ -696,7 +698,9 @@ Use the ``--insecure`` option to force serving of static files with the
|
||||||
:doc:`staticfiles </ref/contrib/staticfiles>` app even if the :setting:`DEBUG`
|
:doc:`staticfiles </ref/contrib/staticfiles>` app even if the :setting:`DEBUG`
|
||||||
setting is ``False``. By using this you acknowledge the fact that it's
|
setting is ``False``. By using this you acknowledge the fact that it's
|
||||||
**grossly inefficient** and probably **insecure**. This is only intended for
|
**grossly inefficient** and probably **insecure**. This is only intended for
|
||||||
local development, and should **never be used in production**.
|
local development, should **never be used in production** and is only
|
||||||
|
available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
|
||||||
|
in your project's :setting:`INSTALLED_APPS` setting.
|
||||||
|
|
||||||
See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
|
See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
|
||||||
for more details and learn how to :doc:`manage and deploy static files
|
for more details and learn how to :doc:`manage and deploy static files
|
||||||
|
|
Loading…
Reference in New Issue