From ec31445c527a22a736cc769d35791f3fea9b477b Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Wed, 20 Jul 2005 17:42:36 +0000 Subject: [PATCH] Added '--settings' option to django-admin. This specifies which settings module to use, if you don't want to deal with setting the DJANGO_SETTINGS_MODULE environment variable. Refactored django-admin to use optparse. Updated the tutorials to use '--settings' instead of environment variables, which can be confusing. git-svn-id: http://code.djangoproject.com/svn/django/trunk@247 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/bin/django-admin.py | 92 +++++++++++++++++++++++++------------- docs/tutorial01.txt | 42 +++++++++-------- docs/tutorial02.txt | 11 ++--- docs/tutorial03.txt | 6 +-- 4 files changed, 90 insertions(+), 61 deletions(-) diff --git a/django/bin/django-admin.py b/django/bin/django-admin.py index 64bfe39882..abb2d13d9f 100755 --- a/django/bin/django-admin.py +++ b/django/bin/django-admin.py @@ -1,5 +1,6 @@ #!/usr/bin/env python from django.core import management +from optparse import OptionParser import os, sys ACTION_MAPPING = { @@ -19,56 +20,83 @@ ACTION_MAPPING = { 'install': management.install, } -def usage(): - sys.stderr.write("Usage: %s [action]\n" % sys.argv[0]) +NO_SQL_TRANSACTION = ('adminindex', 'dbcheck', 'install', 'sqlindexes') + +def get_usage(): + """ + Returns a usage string. Doesn't do the options stuff, because optparse + takes care of that. + """ + usage = ["usage: %prog action [options]\nactions:"] available_actions = ACTION_MAPPING.keys() available_actions.sort() - sys.stderr.write("Available actions:\n") for a in available_actions: func = ACTION_MAPPING[a] - sys.stderr.write(" %s %s-- %s\n" % (a, func.args, getattr(func, 'help_doc', func.__doc__))) + usage.append(" %s %s-- %s" % (a, func.args, getattr(func, 'help_doc', func.__doc__))) + return '\n'.join(usage) + +class DjangoOptionParser(OptionParser): + def print_usage_and_exit(self): + self.print_help(sys.stderr) + sys.exit(1) + +def print_error(msg, cmd): + sys.stderr.write("Error: %s\nRun %s --help for help." % (msg, cmd)) sys.exit(1) -if __name__ == "__main__": +def main(): + # Parse the command-line arguments. optparse handles the dirty work. + parser = DjangoOptionParser(get_usage()) + parser.add_option('--settings', + help='Python path to settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.') + options, args = parser.parse_args() + + # Take care of options. + if options.settings: + os.environ['DJANGO_SETTINGS_MODULE'] = options.settings + + # Run the appropriate action. Unfortunately, optparse can't handle + # positional arguments, so this has to parse/validate them. try: - action = sys.argv[1] + action = args[0] except IndexError: - usage() + print_error("An 'action' is required.") if not ACTION_MAPPING.has_key(action): - usage() + print_error("Your 'action' was invalid.") if action == 'init': ACTION_MAPPING[action]() - sys.exit(0) elif action in ('startapp', 'startproject'): try: - name = sys.argv[2] + name = args[1] except IndexError: - usage() + parser.print_usage_and_exit() ACTION_MAPPING[action](name, os.getcwd()) - sys.exit(0) elif action == 'runserver': - if len(sys.argv) < 3: + if len(args) < 2: port = '8000' else: - port = sys.argv[2] + port = args[1] ACTION_MAPPING[action](port) - elif action == 'dbcheck': - from django.core import meta - mod_list = meta.get_all_installed_modules() else: from django.core import meta - try: - mod_list = [meta.get_app(app_label) for app_label in sys.argv[2:]] - except ImportError, e: - sys.stderr.write("Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n" % e) - sys.exit(1) - if not mod_list: - usage() - if action not in ('adminindex', 'dbcheck', 'install', 'sqlindexes'): - print "BEGIN;" - for mod in mod_list: - output = ACTION_MAPPING[action](mod) - if output: - print '\n'.join(output) - if action not in ('adminindex', 'dbcheck', 'install', 'sqlindexes'): - print "COMMIT;" + if action == 'dbcheck': + mod_list = meta.get_all_installed_modules() + else: + try: + mod_list = [meta.get_app(app_label) for app_label in args[1:]] + except ImportError, e: + sys.stderr.write("Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n" % e) + sys.exit(1) + if not mod_list: + parser.print_usage_and_exit() + if action not in NO_SQL_TRANSACTION: + print "BEGIN;" + for mod in mod_list: + output = ACTION_MAPPING[action](mod) + if output: + print '\n'.join(output) + if action not in NO_SQL_TRANSACTION: + print "COMMIT;" + +if __name__ == "__main__": + main() diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 39d77fafd2..179f248806 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -27,7 +27,7 @@ initial setup. Run the command ``django-admin.py startproject myproject``. That'll create a ``myproject`` directory in your current directory. -(``django-admin.py`` should be on your path if you installed Django via +(``django-admin.py`` should be on your system path if you installed Django via its setup.py utility. If it's not on your path, you can find it in ``site-packages/django/bin``; consider symlinking to it from some place on your path, such as /usr/local/bin.) @@ -67,9 +67,20 @@ comprehensively tested with that database. If you find any bugs in Django's MySQL bindings, please file them in `Django's ticket system`_ so we can fix them immediately. -Once you've done that, you need to tell Django which settings module you're -currently using. Do that by setting an environment variable, -``DJANGO_SETTINGS_MODULE``. Here's how you do that in the Bash shell on Unix:: +Now, take a second to make sure ``myproject`` is on your Python path. You +can do this by copying ``myproject`` to Python's ``site-packages`` directory, +or you can do it by altering the ``PYTHONPATH`` environment variable. See the +`Python path documentation`_ for more information. + +Run the following command:: + + django-admin.py init --settings='myproject.settings.main' + +The ``django-admin.py`` utility generally needs to know which settings module +you're using. Here, we're doing that by specifying ``settings=`` on the command +line, but that can get tedious. If you don't want to type ``settings=`` each +time, you can set the ``DJANGO_SETTINGS_MODULE`` environment variable. Here's +how you do that in the Bash shell on Unix:: export DJANGO_SETTINGS_MODULE=myproject.settings.main @@ -77,24 +88,15 @@ On Windows, you'd use ``set`` instead:: set DJANGO_SETTINGS_MODULE=myproject.settings.main -Note this path is in Python package syntax. Your project has to be somewhere on -your `Python path`_ -- so that the Python statement ``import myproject.settings.main`` -works. Throughout Django, you'll be referring to your projects and apps via -Python package syntax. - -Then run the following command:: - - django-admin.py init - -If you don't see any errors, you know it worked. That command initialized your -database with Django's core database tables. If you're interested, run the -PostgreSQL or MySQL command-line client and type "\\dt" (PostgreSQL) or -"SHOW TABLES;" (MySQL) to display the tables. +If you don't see any errors after running ``django-admin.py init``, you know it +worked. That command initialized your database with Django's core database +tables. If you're interested, run the PostgreSQL or MySQL command-line client +and type "\\dt" (PostgreSQL) or "SHOW TABLES;" (MySQL) to display the tables. Now you're set to start doing work. You won't have to take care of this boring administrative stuff again. -.. _`Python path`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000 +.. _`Python path documentation`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000 .. _Django's ticket system: http://code.djangoproject.com/report/1 Creating models @@ -104,6 +106,10 @@ Change into the ``myproject/apps`` directory and type this command:: django-admin.py startapp polls +(From now on, this tutorial will leave out the ``--settings`` parameter and +will assume you've either set your ``DJANGO_SETTINGS_MODULE`` environment +variable or included the ``--settings`` option in your call to the command.) + That'll create a directory structure like this:: polls/ diff --git a/docs/tutorial02.txt b/docs/tutorial02.txt index e3115eb4ad..8a760b1a1d 100644 --- a/docs/tutorial02.txt +++ b/docs/tutorial02.txt @@ -30,19 +30,16 @@ Start the development server To make things easy, Django comes with a pure-Python Web server that builds on the BaseHTTPServer included in Python's standard library. Let's start the -server and explore the admin site. First, set the ``DJANGO_SETTINGS_MODULE`` -environment variable to the location of your admin settings:: +server and explore the admin site. - export DJANGO_SETTINGS_MODULE=myproject.settings.admin +Just run the following command to start the server:: -Then, run this command to start the server:: - - django-admin.py runserver + django-admin.py runserver --settings="myproject.settings.admin" It'll start a Web server running locally -- on port 8000, by default. If you want to change the server's port, pass it as a command-line argument:: - django-admin.py runserver 8080 + django-admin.py runserver 8080 --settings="myproject.settings.admin" DON'T use this server in anything resembling a production environment. It's intended only for use while developing. diff --git a/docs/tutorial03.txt b/docs/tutorial03.txt index ea1851c407..87a5f38f21 100644 --- a/docs/tutorial03.txt +++ b/docs/tutorial03.txt @@ -113,11 +113,9 @@ Write your first view Well, we haven't created any views yet -- we just have the URLconf. But let's make sure Django is following the URLconf properly. -Set your ``DJANGO_SETTINGS_MODULE`` environment variable to your main settings -(``myproject.settings.main``), as we did with the admin settings in Tutorial 2. -Then, fire up the Django development Web server, as we also did in Tutorial 2:: +Fire up the Django development Web server, as we did in Tutorial 2:: - django-admin.py runserver + django-admin.py runserver --settings="myproject.settings.admin" Now go to "http://localhost:8000/polls/" on your domain in your Web browser. You should get a Python traceback with the following error message::