validation is called explicitly each time the server is reloaded we rely on the environment because it s currently the only way to reach wsgirequesthandler this seems an acceptable compromise considering runserver runs indefinitely return the default wsgi handler for the runner return getinternalwsgiapplication def handleself args options if not settings debug and not settings allowedhosts raise commanderroryou must set settings allowedhosts if debug is false self useipv6 optionsuseipv6 if self useipv6 and not socket hasipv6 raise commanderroryour python does not support ipv6 self rawipv6 false if not optionsaddrport self addr self port self defaultport else m re matchnaiveipre optionsaddrport if m is none raise commanderror s is not a valid port number or address port pair optionsaddrport self addr ipv4 ipv6 fqdn self port m groups if not self port isdigit raise commanderrorr is not a valid port number self port if self addr if ipv6 self addr self addr1 1 self useipv6 true self rawipv6 true elif self useipv6 and not fqdn raise commanderror s is not a valid ipv6 address self addr if not self addr self addr self defaultaddripv6 if self useipv6 else self defaultaddr self rawipv6 self useipv6 self runoptions def runself options if an exception was silenced in managementutility execute in order to be raised in the child process raise it now shutdownmessage is a stealth option need to check migrations here so can t use the requiresmigrationscheck attribute use helpful error messages instead of ugly tracebacks need to use an os exit because sys exit doesn t work in a thread p addr p ipv4 d 1 3 d 1 3 3 ipv4 address p ipv6 a fa f0 9 ipv6 address p fqdn a za z0 9 a za z0 9 fqdn p port d validation is called explicitly each time the server is reloaded we rely on the environment because it s currently the only way to reach wsgirequesthandler this seems an acceptable compromise considering runserver runs indefinitely return the default wsgi handler for the runner run the server using the autoreloader if needed if an exception was silenced in managementutility execute in order to be raised in the child process raise it now shutdown_message is a stealth option need to check migrations here so can t use the requires_migrations_check attribute use helpful error messages instead of ugly tracebacks need to use an os exit because sys exit doesn t work in a thread
import errno
import os
import re
import socket
import sys
from datetime import datetime

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.core.servers.basehttp import WSGIServer, get_internal_wsgi_application, run
from django.utils import autoreload
from django.utils.regex_helper import _lazy_re_compile

naiveip_re = _lazy_re_compile(
    r,
    re.X,
)


class Command(BaseCommand):
    help = "Starts a lightweight web server for development."

    
    requires_system_checks = []
    stealth_options = ("shutdown_message",)
    suppressed_base_arguments = {"--verbosity", "--traceback"}

    default_addr = "127.0.0.1"
    default_addr_ipv6 = "::1"
    default_port = "8000"
    protocol = "http"
    server_cls = WSGIServer

    def add_arguments(self, parser):
        parser.add_argument(
            "addrport", nargs="?", help="Optional port number, or ipaddr:port"
        )
        parser.add_argument(
            "--ipv6",
            "-6",
            action="store_true",
            dest="use_ipv6",
            help="Tells Django to use an IPv6 address.",
        )
        parser.add_argument(
            "--nothreading",
            action="store_false",
            dest="use_threading",
            help="Tells Django to NOT use threading.",
        )
        parser.add_argument(
            "--noreload",
            action="store_false",
            dest="use_reloader",
            help="Tells Django to NOT use the auto-reloader.",
        )
        parser.add_argument(
            "--skip-checks",
            action="store_true",
            help="Skip system checks.",
        )

    def execute(self, *args, **options):
        if options["no_color"]:
            
            
            
            os.environ["DJANGO_COLORS"] = "nocolor"
        super().execute(*args, **options)

    def get_handler(self, *args, **options):
        
        return get_internal_wsgi_application()

    def handle(self, *args, **options):
        if not settings.DEBUG and not settings.ALLOWED_HOSTS:
            raise CommandError("You must set settings.ALLOWED_HOSTS if DEBUG is False.")

        self.use_ipv6 = options["use_ipv6"]
        if self.use_ipv6 and not socket.has_ipv6:
            raise CommandError("Your Python does not support IPv6.")
        self._raw_ipv6 = False
        if not options["addrport"]:
            self.addr = ""
            self.port = self.default_port
        else:
            m = re.match(naiveip_re, options["addrport"])
            if m is None:
                raise CommandError(
                    '"%s" is not a valid port number '
                    "or address:port pair." % options["addrport"]
                )
            self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups()
            if not self.port.isdigit():
                raise CommandError("%r is not a valid port number." % self.port)
            if self.addr:
                if _ipv6:
                    self.addr = self.addr[1:-1]
                    self.use_ipv6 = True
                    self._raw_ipv6 = True
                elif self.use_ipv6 and not _fqdn:
                    raise CommandError('"%s" is not a valid IPv6 address.' % self.addr)
        if not self.addr:
            self.addr = self.default_addr_ipv6 if self.use_ipv6 else self.default_addr
            self._raw_ipv6 = self.use_ipv6
        self.run(**options)

    def run(self, **options):
        
        use_reloader = options["use_reloader"]

        if use_reloader:
            autoreload.run_with_reloader(self.inner_run, **options)
        else:
            self.inner_run(None, **options)

    def inner_run(self, *args, **options):
        
        
        autoreload.raise_last_exception()

        threading = options["use_threading"]
        
        shutdown_message = options.get("shutdown_message", "")

        if not options["skip_checks"]:
            self.stdout.write("Performing system checks...\n\n")
            self.check(display_num_errors=True)
        
        
        self.check_migrations()

        try:
            handler = self.get_handler(*args, **options)
            run(
                self.addr,
                int(self.port),
                handler,
                ipv6=self.use_ipv6,
                threading=threading,
                on_bind=self.on_bind,
                server_cls=self.server_cls,
            )
        except OSError as e:
            
            ERRORS = {
                errno.EACCES: "You don't have permission to access that port.",
                errno.EADDRINUSE: "That port is already in use.",
                errno.EADDRNOTAVAIL: "That IP address can't be assigned to.",
            }
            try:
                error_text = ERRORS[e.errno]
            except KeyError:
                error_text = e
            self.stderr.write("Error: %s" % error_text)
            
            os._exit(1)
        except KeyboardInterrupt:
            if shutdown_message:
                self.stdout.write(shutdown_message)
            sys.exit(0)

    def on_bind(self, server_port):
        quit_command = "CTRL-BREAK" if sys.platform == "win32" else "CONTROL-C"

        if self._raw_ipv6:
            addr = f"[{self.addr}]"
        elif self.addr == "0":
            addr = "0.0.0.0"
        else:
            addr = self.addr

        now = datetime.now().strftime("%B %d, %Y - %X")
        version = self.get_version()
        print(
            f"{now}\n"
            f"Django version {version}, using settings {settings.SETTINGS_MODULE!r}\n"
            f"Starting development server at {self.protocol}://{addr}:{server_port}/\n"
            f"Quit the server with {quit_command}.",
            file=self.stdout,
        )