Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit e9f3899b20e067af51a869e5538a1e513ddd0702 1 parent 1ed6270
Jannis Leidel authored November 13, 2010
27  django/contrib/staticfiles/management/commands/runserver.py
... ...
@@ -0,0 +1,27 @@
  1
+from optparse import make_option
  2
+
  3
+from django.conf import settings
  4
+from django.core.management.commands.runserver import BaseRunserverCommand
  5
+
  6
+from django.contrib.staticfiles.handlers import StaticFilesHandler
  7
+
  8
+class Command(BaseRunserverCommand):
  9
+    option_list = BaseRunserverCommand.option_list + (
  10
+        make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
  11
+            help='Tells Django to NOT automatically serve static files at STATICFILES_URL.'),
  12
+        make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
  13
+            help='Allows serving static files even if DEBUG is False.'),
  14
+    )
  15
+    help = "Starts a lightweight Web server for development, including static files serving."
  16
+
  17
+    def get_handler(self, *args, **options):
  18
+        """
  19
+        Returns the static files serving handler.
  20
+        """
  21
+        handler = super(Command, self).get_handler(*args, **options)
  22
+        use_static_handler = options.get('use_static_handler', True)
  23
+        insecure_serving = options.get('insecure_serving', False)
  24
+        if (settings.DEBUG and use_static_handler or
  25
+                (use_static_handler and insecure_serving)):
  26
+            handler = StaticFilesHandler(handler)
  27
+        return handler
151  django/core/management/commands/runserver.py
... ...
@@ -1,20 +1,16 @@
1 1
 from optparse import make_option
2 2
 import os
3 3
 import sys
4  
-import warnings
5 4
 
6 5
 from django.core.management.base import BaseCommand, CommandError
  6
+from django.core.handlers.wsgi import WSGIHandler
  7
+from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException
  8
+from django.utils import autoreload
7 9
 
8  
-class Command(BaseCommand):
  10
+class BaseRunserverCommand(BaseCommand):
9 11
     option_list = BaseCommand.option_list + (
10 12
         make_option('--noreload', action='store_false', dest='use_reloader', default=True,
11 13
             help='Tells Django to NOT use the auto-reloader.'),
12  
-        make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
13  
-            help='Tells Django to NOT automatically serve static files at STATICFILES_URL.'),
14  
-        make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
15  
-            help='Allows serving static files even if DEBUG is False.'),
16  
-        make_option('--adminmedia', dest='admin_media_path', default='',
17  
-            help='Specifies the directory from which to serve admin media.'),
18 14
     )
19 15
     help = "Starts a lightweight Web server for development."
20 16
     args = '[optional port number, or ipaddr:port]'
@@ -22,79 +18,98 @@ class Command(BaseCommand):
22 18
     # Validation is called explicitly each time the server is reloaded.
23 19
     requires_model_validation = False
24 20
 
  21
+    def get_handler(self, *args, **options):
  22
+        """
  23
+        Returns the default WSGI handler for the runner.
  24
+        """
  25
+        return WSGIHandler()
  26
+
25 27
     def handle(self, addrport='', *args, **options):
26  
-        import django
27  
-        from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
28  
-        from django.core.handlers.wsgi import WSGIHandler
29  
-        from django.contrib.staticfiles.handlers import StaticFilesHandler
30 28
         if args:
31 29
             raise CommandError('Usage is runserver %s' % self.args)
32 30
         if not addrport:
33  
-            addr = ''
34  
-            port = '8000'
  31
+            self.addr = ''
  32
+            self.port = '8000'
35 33
         else:
36 34
             try:
37  
-                addr, port = addrport.split(':')
  35
+                self.addr, self.port = addrport.split(':')
38 36
             except ValueError:
39  
-                addr, port = '', addrport
40  
-        if not addr:
41  
-            addr = '127.0.0.1'
  37
+                self.addr, self.port = '', addrport
  38
+        if not self.addr:
  39
+            self.addr = '127.0.0.1'
  40
+
  41
+        if not self.port.isdigit():
  42
+            raise CommandError("%r is not a valid port number." % self.port)
42 43
 
43  
-        if not port.isdigit():
44  
-            raise CommandError("%r is not a valid port number." % port)
  44
+        self.run(*args, **options)
45 45
 
  46
+    def run(self, *args, **options):
  47
+        """
  48
+        Runs the server, using the autoreloader if needed
  49
+        """
46 50
         use_reloader = options.get('use_reloader', True)
47  
-        admin_media_path = options.get('admin_media_path', '')
  51
+
  52
+        if use_reloader:
  53
+            autoreload.main(self.inner_run, args, options)
  54
+        else:
  55
+            self.inner_run(*args, **options)
  56
+
  57
+    def inner_run(self, *args, **options):
  58
+        from django.conf import settings
  59
+        from django.utils import translation
  60
+
48 61
         shutdown_message = options.get('shutdown_message', '')
49  
-        use_static_handler = options.get('use_static_handler', True)
50  
-        insecure_serving = options.get('insecure_serving', False)
51 62
         quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
52 63
 
53  
-        def inner_run():
54  
-            from django.conf import settings
55  
-            from django.utils import translation
56  
-            print "Validating models..."
57  
-            self.validate(display_num_errors=True)
58  
-            print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
59  
-            print "Development server is running at http://%s:%s/" % (addr, port)
60  
-            print "Quit the server with %s." % quit_command
61  
-
62  
-            # django.core.management.base forces the locale to en-us. We should
63  
-            # set it up correctly for the first request (particularly important
64  
-            # in the "--noreload" case).
65  
-            translation.activate(settings.LANGUAGE_CODE)
  64
+        self.stdout.write("Validating models...\n\n")
  65
+        self.validate(display_num_errors=True)
  66
+        self.stdout.write((
  67
+            "Django version %(version)s, using settings %(settings)r\n"
  68
+            "Development server is running at http://%(addr)s:%(port)s/\n"
  69
+            "Quit the server with %(quit_command)s.\n"
  70
+        ) % {
  71
+            "version": self.get_version(),
  72
+            "settings": settings.SETTINGS_MODULE,
  73
+            "addr": self.addr,
  74
+            "port": self.port,
  75
+            "quit_command": quit_command,
  76
+        })
  77
+        # django.core.management.base forces the locale to en-us. We should
  78
+        # set it up correctly for the first request (particularly important
  79
+        # in the "--noreload" case).
  80
+        translation.activate(settings.LANGUAGE_CODE)
66 81
 
  82
+        try:
  83
+            handler = self.get_handler(*args, **options)
  84
+            run(self.addr, int(self.port), handler)
  85
+        except WSGIServerException, e:
  86
+            # Use helpful error messages instead of ugly tracebacks.
  87
+            ERRORS = {
  88
+                13: "You don't have permission to access that port.",
  89
+                98: "That port is already in use.",
  90
+                99: "That IP address can't be assigned-to.",
  91
+            }
67 92
             try:
68  
-                handler = WSGIHandler()
69  
-                allow_serving = (settings.DEBUG and use_static_handler or
70  
-                    (use_static_handler and insecure_serving))
71  
-                if (allow_serving and
72  
-                        "django.contrib.staticfiles" in settings.INSTALLED_APPS):
73  
-                    handler = StaticFilesHandler(handler)
74  
-                # serve admin media like old-school (deprecation pending)
75  
-                handler = AdminMediaHandler(handler, admin_media_path)
76  
-                run(addr, int(port), handler)
77  
-            except WSGIServerException, e:
78  
-                # Use helpful error messages instead of ugly tracebacks.
79  
-                ERRORS = {
80  
-                    13: "You don't have permission to access that port.",
81  
-                    98: "That port is already in use.",
82  
-                    99: "That IP address can't be assigned-to.",
83  
-                }
84  
-                try:
85  
-                    error_text = ERRORS[e.args[0].args[0]]
86  
-                except (AttributeError, KeyError):
87  
-                    error_text = str(e)
88  
-                sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
89  
-                # Need to use an OS exit because sys.exit doesn't work in a thread
90  
-                os._exit(1)
91  
-            except KeyboardInterrupt:
92  
-                if shutdown_message:
93  
-                    print shutdown_message
94  
-                sys.exit(0)
  93
+                error_text = ERRORS[e.args[0].args[0]]
  94
+            except (AttributeError, KeyError):
  95
+                error_text = str(e)
  96
+            sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
  97
+            # Need to use an OS exit because sys.exit doesn't work in a thread
  98
+            os._exit(1)
  99
+        except KeyboardInterrupt:
  100
+            if shutdown_message:
  101
+                self.stdout.write("%s\n" % shutdown_message)
  102
+            sys.exit(0)
95 103
 
96  
-        if use_reloader:
97  
-            from django.utils import autoreload
98  
-            autoreload.main(inner_run)
99  
-        else:
100  
-            inner_run()
  104
+class Command(BaseRunserverCommand):
  105
+    option_list = BaseRunserverCommand.option_list + (
  106
+        make_option('--adminmedia', dest='admin_media_path', default='',
  107
+            help='Specifies the directory from which to serve admin media.'),
  108
+    )
  109
+
  110
+    def get_handler(self, *args, **options):
  111
+        """
  112
+        Serves admin media like old-school (deprecation pending).
  113
+        """
  114
+        handler = super(Command, self).get_handler(*args, **options)
  115
+        return AdminMediaHandler(handler, options.get('admin_media_path', ''))
6  docs/man/django-admin.1
@@ -164,6 +164,12 @@ Do not prompt the user for input.
164 164
 .I \-\-noreload
165 165
 Disable the development server's auto\-reloader.
166 166
 .TP
  167
+.I \-\-nostatic
  168
+Disable automatic serving of static files from STATICFILES_URL.
  169
+.TP
  170
+.I \-\-insecure
  171
+Enables serving of static files even if DEBUG is False.
  172
+.TP
167 173
 .I \-\-verbosity=VERBOSITY
168 174
 Verbosity level: 0=minimal output, 1=normal output, 2=all output.
169 175
 .TP
8  docs/ref/django-admin.txt
@@ -684,7 +684,9 @@ Example usage::
684 684
 .. django-admin-option:: --nostatic
685 685
 
686 686
 Use the ``--nostatic`` option to disable serving of static files with the
687  
-:doc:`staticfiles </ref/contrib/staticfiles>` app entirely.
  687
+:doc:`staticfiles </ref/contrib/staticfiles>` app entirely. This option is
  688
+only available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
  689
+in your project's :setting:`INSTALLED_APPS` setting.
688 690
 
689 691
 Example usage::
690 692
 
@@ -696,7 +698,9 @@ Use the ``--insecure`` option to force serving of static files with the
696 698
 :doc:`staticfiles </ref/contrib/staticfiles>` app even if the :setting:`DEBUG`
697 699
 setting is ``False``. By using this you acknowledge the fact that it's
698 700
 **grossly inefficient** and probably **insecure**. This is only intended for
699  
-local development, and should **never be used in production**.
  701
+local development, should **never be used in production** and is only
  702
+available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
  703
+in your project's :setting:`INSTALLED_APPS` setting.
700 704
 
701 705
 See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
702 706
 for more details and learn how to :doc:`manage and deploy static files

0 notes on commit e9f3899

Please sign in to comment.
Something went wrong with that request. Please try again.