diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py
index 49e270d..618fa4d 100644
a
|
b
|
|
1 | 1 | from optparse import make_option |
2 | 2 | import os |
| 3 | import socket |
3 | 4 | import sys |
4 | 5 | import warnings |
| 6 | import re |
5 | 7 | |
6 | 8 | from django.core.management.base import BaseCommand, CommandError |
7 | 9 | |
| 10 | naiveip_re = r'^(?:(?P<addr>\d{1,3}(?:\.\d{1,3}){3}|\[[a-fA-F0-9:]+\]):)?(?P<port>\d+)$' |
| 11 | DEFAULT_PORT = "8000" |
| 12 | |
8 | 13 | class Command(BaseCommand): |
9 | 14 | option_list = BaseCommand.option_list + ( |
| 15 | make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False, |
| 16 | help='Force the use of IPv6 address.'), |
10 | 17 | make_option('--noreload', action='store_false', dest='use_reloader', default=True, |
11 | 18 | help='Tells Django to NOT use the auto-reloader.'), |
12 | 19 | make_option('--nostatic', action="store_false", dest='use_static_handler', default=True, |
… |
… |
class Command(BaseCommand):
|
27 | 34 | from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException |
28 | 35 | from django.core.handlers.wsgi import WSGIHandler |
29 | 36 | from django.contrib.staticfiles.handlers import StaticFilesHandler |
| 37 | enable_ipv6 = options.get('enable_ipv6') |
| 38 | if enable_ipv6 and not hasattr(socket, 'AF_INET6'): |
| 39 | raise CommandError("Your Python does not support IPv6.") |
| 40 | |
30 | 41 | if args: |
31 | 42 | raise CommandError('Usage is runserver %s' % self.args) |
32 | 43 | if not addrport: |
33 | 44 | addr = '' |
34 | | port = '8000' |
| 45 | port = DEFAULT_PORT |
35 | 46 | else: |
36 | | try: |
37 | | addr, port = addrport.split(':') |
38 | | except ValueError: |
39 | | addr, port = '', addrport |
| 47 | m = re.match(naiveip_re, addrport) |
| 48 | if m is None: |
| 49 | raise CommandError("%r is not a valid port number or address:port pair." % addrport) |
| 50 | addr, port = m.groups() |
| 51 | if not port.isdigit(): |
| 52 | raise CommandError("%r is not a valid port number." % port) |
| 53 | if addr: |
| 54 | if addr[0] == '[' and addr[-1] == ']': |
| 55 | enable_ipv6 = True |
| 56 | addr = addr[1:-1] |
| 57 | elif enable_ipv6: |
| 58 | raise CommandError("IPv6 addresses must be surrounded with brackets") |
40 | 59 | if not addr: |
41 | | addr = '127.0.0.1' |
42 | | |
43 | | if not port.isdigit(): |
44 | | raise CommandError("%r is not a valid port number." % port) |
45 | | |
| 60 | addr = (enable_ipv6 and '::1') or '127.0.0.1' |
46 | 61 | use_reloader = options.get('use_reloader', True) |
47 | 62 | admin_media_path = options.get('admin_media_path', '') |
48 | 63 | shutdown_message = options.get('shutdown_message', '') |
… |
… |
class Command(BaseCommand):
|
56 | 71 | print "Validating models..." |
57 | 72 | self.validate(display_num_errors=True) |
58 | 73 | 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) |
| 74 | fmt_addr = (enable_ipv6 and '[%s]' % addr) or addr |
| 75 | print "Development server is running at http://%s:%s/" % (fmt_addr, port) |
60 | 76 | print "Quit the server with %s." % quit_command |
61 | 77 | |
62 | 78 | # django.core.management.base forces the locale to en-us. We should |
… |
… |
class Command(BaseCommand):
|
73 | 89 | handler = StaticFilesHandler(handler) |
74 | 90 | # serve admin media like old-school (deprecation pending) |
75 | 91 | handler = AdminMediaHandler(handler, admin_media_path) |
76 | | run(addr, int(port), handler) |
| 92 | run(addr, int(port), handler, enable_ipv6=enable_ipv6) |
77 | 93 | except WSGIServerException, e: |
78 | 94 | # Use helpful error messages instead of ugly tracebacks. |
79 | 95 | ERRORS = { |
diff --git a/django/core/management/commands/testserver.py b/django/core/management/commands/testserver.py
index d3d9698..be5b9ea 100644
a
|
b
|
class Command(BaseCommand):
|
9 | 9 | make_option('--addrport', action='store', dest='addrport', |
10 | 10 | type='string', default='', |
11 | 11 | help='port number or ipaddr:port to run the server on'), |
| 12 | make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False, |
| 13 | help='Forces IPv6 support.'), |
12 | 14 | ) |
13 | 15 | help = 'Runs a development server with data from the given fixture(s).' |
14 | 16 | args = '[fixture ...]' |
… |
… |
class Command(BaseCommand):
|
33 | 35 | # a strange error -- it causes this handle() method to be called |
34 | 36 | # multiple times. |
35 | 37 | shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name |
36 | | call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False) |
| 38 | call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, enable_ipv6=options['enable_ipv6']) |
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 9c92a88..35bb990 100644
a
|
b
|
been reviewed for security issues. Don't use it for production use.
|
10 | 10 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer |
11 | 11 | import os |
12 | 12 | import re |
| 13 | import socket |
13 | 14 | import sys |
14 | 15 | import urllib |
15 | 16 | import warnings |
… |
… |
class AdminMediaHandler(StaticFilesHandler):
|
678 | 679 | """ |
679 | 680 | return path.startswith(self.media_url[2]) and not self.media_url[1] |
680 | 681 | |
| 682 | class WSGIServerV6(WSGIServer): |
| 683 | address_family = socket.AF_INET6 |
681 | 684 | |
682 | | def run(addr, port, wsgi_handler): |
| 685 | def run(addr, port, wsgi_handler, enable_ipv6=False): |
683 | 686 | server_address = (addr, port) |
684 | | httpd = WSGIServer(server_address, WSGIRequestHandler) |
| 687 | server_class = (enable_ipv6 and WSGIServerV6) or WSGIServer |
| 688 | httpd = server_class(server_address, WSGIRequestHandler) |
685 | 689 | httpd.set_app(wsgi_handler) |
686 | 690 | httpd.serve_forever() |
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 14fc69f..0570fcb 100644
a
|
b
|
runserver [port or ipaddr:port]
|
630 | 630 | .. django-admin:: runserver |
631 | 631 | |
632 | 632 | Starts a lightweight development Web server on the local machine. By default, |
633 | | the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an |
| 633 | the server runs on port 8000 on the IP address ``127.0.0.1``. You can pass in an |
634 | 634 | IP address and port number explicitly. |
635 | 635 | |
636 | 636 | If you run this script as a user with normal privileges (recommended), you |
… |
… |
them to standard output, but it won't stop the server.
|
654 | 654 | You can run as many servers as you want, as long as they're on separate ports. |
655 | 655 | Just execute ``django-admin.py runserver`` more than once. |
656 | 656 | |
657 | | Note that the default IP address, 127.0.0.1, is not accessible from other |
| 657 | Note that the default IP address, ``127.0.0.1``, is not accessible from other |
658 | 658 | machines on your network. To make your development server viewable to other |
659 | 659 | machines on the network, use its own IP address (e.g. ``192.168.2.1``) or |
660 | | ``0.0.0.0``. |
| 660 | ``0.0.0.0`` or ``::`` (with IPv6 enabled). |
| 661 | |
| 662 | .. versionchanged:: 1.3 |
| 663 | |
| 664 | You can also provide an IPv6 address surrounded by brackets |
| 665 | (eg. ``[200a::1]:8000``). This will automaticaly enable IPv6 support. |
661 | 666 | |
662 | 667 | .. django-admin-option:: --adminmedia |
663 | 668 | |
… |
… |
Example usage::
|
706 | 711 | |
707 | 712 | django-admin.py runserver --insecure |
708 | 713 | |
| 714 | .. django-admin-option:: --ipv6, -6 |
| 715 | |
| 716 | .. versionadded:: 1.3 |
| 717 | |
| 718 | Use the ``--ipv6`` (or shorter ``-6``) option to tell Django to use IPv6 for |
| 719 | the development server. This changes the default IP address from |
| 720 | ``127.0.0.1`` to ``::1``. |
| 721 | |
| 722 | Example usage:: |
| 723 | |
| 724 | django-admin.py runserver --ipv6 |
| 725 | |
709 | 726 | Examples of using different ports and addresses |
710 | 727 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
711 | 728 | |
712 | | Port 8000 on IP address 127.0.0.1:: |
| 729 | Port 8000 on IP address ``127.0.0.1``:: |
713 | 730 | |
714 | | django-admin.py runserver |
| 731 | django-admin.py runserver |
715 | 732 | |
716 | | Port 8000 on IP address 1.2.3.4:: |
| 733 | Port 8000 on IP address ``1.2.3.4``:: |
717 | 734 | |
718 | | django-admin.py runserver 1.2.3.4:8000 |
| 735 | django-admin.py runserver 1.2.3.4:8000 |
719 | 736 | |
720 | | Port 7000 on IP address 127.0.0.1:: |
| 737 | Port 7000 on IP address ``127.0.0.1``:: |
721 | 738 | |
722 | 739 | django-admin.py runserver 7000 |
723 | 740 | |
724 | | Port 7000 on IP address 1.2.3.4:: |
| 741 | Port 7000 on IP address ``1.2.3.4``:: |
725 | 742 | |
726 | 743 | django-admin.py runserver 1.2.3.4:7000 |
727 | 744 | |
| 745 | Port 8000 on IPv6 address ``::1``:: |
| 746 | |
| 747 | django-admin.py runserver -6 |
| 748 | |
| 749 | Port 7000 on IPv6 address ``::1``:: |
| 750 | |
| 751 | django-admin.py runserver -6 7000 |
| 752 | |
| 753 | Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``:: |
| 754 | |
| 755 | django-admin.py runserver [2001:0db8:1234:5678::9]:7000 |
| 756 | |
728 | 757 | Serving static files with the development server |
729 | 758 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
730 | 759 | |
… |
… |
templates.
|
988 | 1017 | .. django-admin-option:: --addrport [port number or ipaddr:port] |
989 | 1018 | |
990 | 1019 | Use ``--addrport`` to specify a different port, or IP address and port, from |
991 | | the default of 127.0.0.1:8000. This value follows exactly the same format and |
| 1020 | the default of ``127.0.0.1:8000``. This value follows exactly the same format and |
992 | 1021 | serves exactly the same function as the argument to the ``runserver`` command. |
993 | 1022 | |
994 | 1023 | Examples: |