runserver.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. from optparse import make_option
  2. import os
  3. import re
  4. import sys
  5. import socket
  6. from django.core.management.base import BaseCommand, CommandError
  7. from django.core.servers.basehttp import run, WSGIServerException, get_internal_wsgi_application
  8. from django.utils import autoreload
  9. naiveip_re = re.compile(r"""^(?:
  10. (?P<addr>
  11. (?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address
  12. (?P<ipv6>\[[a-fA-F0-9:]+\]) | # IPv6 address
  13. (?P<fqdn>[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN
  14. ):)?(?P<port>\d+)$""", re.X)
  15. DEFAULT_PORT = "8000"
  16. class Command(BaseCommand):
  17. option_list = BaseCommand.option_list + (
  18. make_option('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
  19. help='Tells Django to use a IPv6 address.'),
  20. make_option('--nothreading', action='store_false', dest='use_threading', default=True,
  21. help='Tells Django to NOT use threading.'),
  22. make_option('--noreload', action='store_false', dest='use_reloader', default=True,
  23. help='Tells Django to NOT use the auto-reloader.'),
  24. )
  25. help = "Starts a lightweight Web server for development."
  26. args = '[optional port number, or ipaddr:port]'
  27. # Validation is called explicitly each time the server is reloaded.
  28. requires_model_validation = False
  29. def get_handler(self, *args, **options):
  30. """
  31. Returns the default WSGI handler for the runner.
  32. """
  33. return get_internal_wsgi_application()
  34. def handle(self, addrport='', *args, **options):
  35. self.use_ipv6 = options.get('use_ipv6')
  36. if self.use_ipv6 and not socket.has_ipv6:
  37. raise CommandError('Your Python does not support IPv6.')
  38. if args:
  39. raise CommandError('Usage is runserver %s' % self.args)
  40. self._raw_ipv6 = False
  41. if not addrport:
  42. self.addr = ''
  43. self.port = DEFAULT_PORT
  44. else:
  45. m = re.match(naiveip_re, addrport)
  46. if m is None:
  47. raise CommandError('"%s" is not a valid port number '
  48. 'or address:port pair.' % addrport)
  49. self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups()
  50. if not self.port.isdigit():
  51. raise CommandError("%r is not a valid port number." % self.port)
  52. if self.addr:
  53. if _ipv6:
  54. self.addr = self.addr[1:-1]
  55. self.use_ipv6 = True
  56. self._raw_ipv6 = True
  57. elif self.use_ipv6 and not _fqdn:
  58. raise CommandError('"%s" is not a valid IPv6 address.' % self.addr)
  59. if not self.addr:
  60. self.addr = self.use_ipv6 and '::1' or '127.0.0.1'
  61. self._raw_ipv6 = bool(self.use_ipv6)
  62. self.run(*args, **options)
  63. def run(self, *args, **options):
  64. """
  65. Runs the server, using the autoreloader if needed
  66. """
  67. use_reloader = options.get('use_reloader')
  68. if use_reloader:
  69. autoreload.main(self.inner_run, args, options)
  70. else:
  71. self.inner_run(*args, **options)
  72. def inner_run(self, *args, **options):
  73. from django.conf import settings
  74. from django.utils import translation
  75. threading = options.get('use_threading')
  76. shutdown_message = options.get('shutdown_message', '')
  77. quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
  78. self.stdout.write("Validating models...\n\n")
  79. self.validate(display_num_errors=True)
  80. self.stdout.write((
  81. "Django version %(version)s, using settings %(settings)r\n"
  82. "Development server is running at http://%(addr)s:%(port)s/\n"
  83. "Quit the server with %(quit_command)s.\n"
  84. ) % {
  85. "version": self.get_version(),
  86. "settings": settings.SETTINGS_MODULE,
  87. "addr": self._raw_ipv6 and '[%s]' % self.addr or self.addr,
  88. "port": self.port,
  89. "quit_command": quit_command,
  90. })
  91. # django.core.management.base forces the locale to en-us. We should
  92. # set it up correctly for the first request (particularly important
  93. # in the "--noreload" case).
  94. translation.activate(settings.LANGUAGE_CODE)
  95. try:
  96. handler = self.get_handler(*args, **options)
  97. run(self.addr, int(self.port), handler,
  98. ipv6=self.use_ipv6, threading=threading)
  99. except WSGIServerException, e:
  100. # Use helpful error messages instead of ugly tracebacks.
  101. ERRORS = {
  102. 13: "You don't have permission to access that port.",
  103. 98: "That port is already in use.",
  104. 99: "That IP address can't be assigned-to.",
  105. }
  106. try:
  107. error_text = ERRORS[e.args[0].args[0]]
  108. except (AttributeError, KeyError):
  109. error_text = str(e)
  110. sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
  111. # Need to use an OS exit because sys.exit doesn't work in a thread
  112. os._exit(1)
  113. except KeyboardInterrupt:
  114. if shutdown_message:
  115. self.stdout.write("%s\n" % shutdown_message)
  116. sys.exit(0)
  117. # Kept for backward compatibility
  118. BaseRunserverCommand = Command