From 8013f76a40270283f9d3c04160ac9b8a72ffe2be Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Wed, 11 Jan 2006 05:07:38 +0000 Subject: [PATCH] magic-removal: Merged to [1903] git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1904 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/contrib/admin/media/css/global.css | 4 +- .../admin/templates/widget/one_to_one.html | 1 + django/core/formfields.py | 2 +- django/core/management.py | 9 +- django/core/template/defaultfilters.py | 2 +- docs/authentication.txt | 9 +- docs/cache.txt | 3 +- docs/db-api.txt | 2 - docs/django-admin.txt | 28 +- docs/email.txt | 2 - docs/generic_views.txt | 9 +- docs/request_response.txt | 7 +- docs/sessions.txt | 14 +- docs/settings.txt | 7 +- docs/templates.txt | 6 +- docs/templates_python.txt | 9 - docs/tutorial01.txt | 250 +++++++++++------- docs/tutorial02.txt | 45 ++-- docs/tutorial03.txt | 62 ++--- docs/tutorial04.txt | 8 +- docs/url_dispatch.txt | 6 - 22 files changed, 267 insertions(+), 219 deletions(-) create mode 100644 django/contrib/admin/templates/widget/one_to_one.html diff --git a/AUTHORS b/AUTHORS index 49bf7b56dd..b7c0994f0c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -82,6 +82,7 @@ answer newbie questions, and generally made Django that much better: phaedo Luke Plant plisk + Daniel Poelzleithner Brian Ray Oliver Rutherfurd David Schein diff --git a/django/contrib/admin/media/css/global.css b/django/contrib/admin/media/css/global.css index 73f01621db..454ac29010 100644 --- a/django/contrib/admin/media/css/global.css +++ b/django/contrib/admin/media/css/global.css @@ -122,7 +122,7 @@ textarea { vertical-align:top !important; } input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; } /* FORM BUTTONS */ -input[type=submit], input[type=button], .submit-row input { border:1px solid #ccc; background:white url(../img/admin/nav-bg.gif) bottom repeat-x; } +input[type=submit], input[type=button], .submit-row input { border:1px solid #ccc; background:white url(../img/admin/nav-bg.gif) bottom repeat-x; color:black; } input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; } input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; padding:3px; background:white url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; } input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; } @@ -339,4 +339,4 @@ p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; } .vURLField { width:30em; } .vLargeTextField, .vXMLLargeTextField { width:48em; } .flatpages-flatpage #id_content { height:40.2em; } -.module table .vPositiveSmallIntegerField { width:2.2em; } \ No newline at end of file +.module table .vPositiveSmallIntegerField { width:2.2em; } diff --git a/django/contrib/admin/templates/widget/one_to_one.html b/django/contrib/admin/templates/widget/one_to_one.html new file mode 100644 index 0000000000..151fe04f30 --- /dev/null +++ b/django/contrib/admin/templates/widget/one_to_one.html @@ -0,0 +1 @@ +{% include "widget/foreign" %} diff --git a/django/core/formfields.py b/django/core/formfields.py index 2efacbd290..8dd9d9f1c7 100644 --- a/django/core/formfields.py +++ b/django/core/formfields.py @@ -811,7 +811,7 @@ class TimeField(TextField): if (len(part_list) == 2): t = t.replace(microsecond=int(part_list[1])) return t - except (ValueError, TypeError): + except (ValueError, TypeError, AttributeError): return None html2python = staticmethod(html2python) diff --git a/django/core/management.py b/django/core/management.py index fb8b7d2f24..f65f62a46e 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -945,6 +945,12 @@ def createcachetable(tablename): connection.commit() createcachetable.args = "[tablename]" +def run_shell(): + "Runs a Python interactive interpreter" + import code + code.interact() +run_shell.args = '' + # Utilities for command-line script DEFAULT_ACTION_MAPPING = { @@ -958,6 +964,7 @@ DEFAULT_ACTION_MAPPING = { 'install': install, 'installperms': installperms, 'runserver': runserver, + 'shell': run_shell, 'sql': get_sql_create, 'sqlall': get_sql_all, 'sqlclear': get_sql_delete, @@ -1038,7 +1045,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING): sys.exit(1) else: action_mapping[action](username, email, password) - elif action in ('init', 'init-minimal', 'validate'): + elif action in ('init', 'init-minimal', 'shell', 'validate'): action_mapping[action]() elif action == 'inspectdb': try: diff --git a/django/core/template/defaultfilters.py b/django/core/template/defaultfilters.py index 73548c4afa..dd5fbef25e 100644 --- a/django/core/template/defaultfilters.py +++ b/django/core/template/defaultfilters.py @@ -136,7 +136,7 @@ def wordwrap(value, arg): Argument: number of words to wrap the text at. """ from django.utils.text import wrap - return wrap(value, int(arg)) + return wrap(str(value), int(arg)) def ljust(value, arg): """ diff --git a/docs/authentication.txt b/docs/authentication.txt index 634366096a..46a76b853c 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -170,8 +170,8 @@ Change a password with ``set_password()``:: Passwords --------- -**This only applies to the Django development version.** Previous versions, -such as Django 0.90, used simple MD5 hashes without password salts. +Previous versions, such as Django 0.90, used simple MD5 hashes without password +salts. The ``password`` field of a ``User`` object is a string in this format:: @@ -314,9 +314,8 @@ Here's the same thing, using Python 2.4's decorator syntax:: Note that ``user_passes_test`` does not automatically check that the ``User`` is not anonymous. -**New in the Django development version**: ``user_passes_test()`` takes an -optional ``login_url`` argument, which lets you specify the URL for your login -page (``/accounts/login/`` by default). +``user_passes_test()`` takes an optional ``login_url`` argument, which lets you +specify the URL for your login page (``/accounts/login/`` by default). Example in Python 2.3 syntax:: diff --git a/docs/cache.txt b/docs/cache.txt index 09e201a202..aaceb228d2 100644 --- a/docs/cache.txt +++ b/docs/cache.txt @@ -48,8 +48,7 @@ Examples: locmem:/// A more sophisticated local memory cache; this is multi-process- and thread-safe. - dummy:/// **New in Django development version.** - Doesn't actually cache; just implements the + dummy:/// Doesn't actually cache; just implements the cache backend interface and doesn't do anything. This is an easy way to turn off caching for a test environment. diff --git a/docs/db-api.txt b/docs/db-api.txt index e6b2238225..f4b4675c82 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -222,8 +222,6 @@ If you pass an invalid keyword argument, the function will raise ``TypeError``. OR lookups ---------- -**New in Django development version.** - By default, keyword argument queries are "AND"ed together. If you have more complex query requirements (for example, you need to include an ``OR`` statement in your query), you need to use ``Q`` objects. diff --git a/docs/django-admin.txt b/docs/django-admin.txt index 3f024b9f7f..5271853aa6 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -6,14 +6,29 @@ The django-admin.py utility This document outlines all it can do. The ``django-admin.py`` script 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 +Django via its ``setup.py`` utility. If it's not on your path, you can find it in ``site-packages/django/bin`` within your Python installation. Consider symlinking to it from some place on your path, such as ``/usr/local/bin``. +In addition, ``manage.py`` is automatically created in each Django project. +``manage.py`` is a thin wrapper around ``django-admin.py`` that takes care of +two things for you before delegating to ``django-admin.py``: + + * It puts your project's package on ``sys.path``. + + * It sets the ``DJANGO_SETTINGS_MODULE`` environment variable so that it + points to your project's ``settings.py`` file. + +Generally, when working on a single Django project, it's easier to use +``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the +``--settings`` command line option, if you need to switch between multiple +Django settings files. + Usage ===== ``django-admin.py action [options]`` +``manage.py action [options]`` ``action`` should be one of the actions listed in this document. ``options``, which is optional, should be zero or more of the options listed in this @@ -54,9 +69,8 @@ createsuperuser Creates a superuser account interactively. It asks you for a username, e-mail address and password. -**New in Django development version:** You can specify -``username email password`` on the command line, for convenient use in shell -scripts. Example:: +You can specify ``username email password`` on the command line, for convenient +use in shell scripts. Example:: django-admin.py createsuperuser john john@example.com mypassword @@ -211,6 +225,9 @@ Explicitly specifies the settings module to use. The settings module should be in Python path syntax, e.g. "myproject.settings". If this isn't provided, ``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable. +Note that this option is unnecessary in ``manage.py``, because it takes care of +setting ``DJANGO_SETTINGS_MODULE`` for you. + --pythonpath ------------ @@ -222,6 +239,9 @@ Adds the given filesystem path to the Python `import search path`_. If this isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment variable. +Note that this option is unnecessary in ``manage.py``, because it takes care of +setting the Python path for you. + .. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html --help diff --git a/docs/email.txt b/docs/email.txt index 2b00eb0570..e43a29da30 100644 --- a/docs/email.txt +++ b/docs/email.txt @@ -118,8 +118,6 @@ receiving a separate e-mail:: Preventing header injection =========================== -**New in Django development version.** - `Header injection`_ is a security exploit in which an attacker inserts extra e-mail headers to control the "To:" and "From:" in e-mail messages that your scripts generate. diff --git a/docs/generic_views.txt b/docs/generic_views.txt index cfca09d5b1..6881a7fd16 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -129,9 +129,9 @@ arguments: ``extra_context`` A dictionary of extra data to put into the template's context. - ``processors`` **New in Django development version.** A tuple of - processors to apply to the ``DjangoContext`` of - this view's template. See the `DjangoContext docs`_ + ``processors`` A tuple of processors to apply to the + ``DjangoContext`` of this view's template. See the + `DjangoContext docs`_ ======================= ================================================== .. _database API docs: http://www.djangoproject.com/documentation/db_api/ @@ -150,8 +150,7 @@ The date-based generic functions are: ``num_latest`` The number of items to display on the page. Defaults to 15. - ``allow_empty`` **New in Django development version.** - If ``False`` and there are no objects to display, + ``allow_empty`` If ``False`` and there are no objects to display, the view will raise a 404 instead of displaying an empty index page. ``False`` is default. ======================= ================================================= diff --git a/docs/request_response.txt b/docs/request_response.txt index 47e0ec9ccf..818c639d9a 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -151,9 +151,8 @@ subclass of dictionary. Exceptions are outlined here: other dictionary functions that have side effects, can only be called on a mutable ``QueryDict`` (one that was created via ``copy()``). - * ``__contains__(key)`` -- **New in Django development version.** Returns - ``True`` if the given key is set. This lets you do, e.g., - ``if "foo" in request.GET``. + * ``__contains__(key)`` -- Returns ``True`` if the given key is set. This + lets you do, e.g., ``if "foo" in request.GET``. * ``get(key, default)`` -- Uses the same logic as ``__getitem__()`` above, with a hook for returning a default value if the key doesn't exist. @@ -361,8 +360,6 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in an HTTP status code 302. ``HttpResponsePermanentRedirect`` - **New in Django development version.*** - Like ``HttpResponseRedirect``, but it returns a permanent redirect (HTTP status code 301) instead of a "found" redirect (status code 302). diff --git a/docs/sessions.txt b/docs/sessions.txt index 7c8abb9841..30e4b9706e 100644 --- a/docs/sessions.txt +++ b/docs/sessions.txt @@ -30,7 +30,7 @@ it and write to it. It implements the following standard dictionary methods: * ``__contains__(key)`` - **New in Django development version.** Example: ``'fav_color' in request.session`` + Example: ``'fav_color' in request.session`` * ``__getitem__(key)`` Example: ``fav_color = request.session['fav_color']`` @@ -177,10 +177,9 @@ deleted:: # request.session['foo'] instead of request.session. request.session['foo']['bar'] = 'baz' -**Only available in Django development version.** To change this default -behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting to ``True``. If -``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save the session to the -database on every single request. +To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting +to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save +the session to the database on every single request. Note that the session cookie is only sent when a session has been created or modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie @@ -213,8 +212,7 @@ domain cookie. SESSION_COOKIE_NAME ------------------- -Default: ``'sessionid'`` (**Django development version.** Previous default was -``'hotclub'``, which was deemed too pornish.) +Default: ``'sessionid'`` The name of the cookie to use for sessions. This can be whatever you want. @@ -223,8 +221,6 @@ SESSION_SAVE_EVERY_REQUEST Default: ``False`` -**Only available in Django development version.** - Whether to save the session data on every request. If this is ``False`` (default), then the session data will only be saved if it has been modified -- that is, if any of its dictionary values have been assigned or deleted. diff --git a/docs/settings.txt b/docs/settings.txt index 626106245e..ddc018b5e9 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -525,8 +525,7 @@ domain cookie. See the `session docs`_. SESSION_COOKIE_NAME ------------------- -Default: ``'sessionid'`` (**Django development version.** Previous default was -``'hotclub'``, which was deemed too pornish.) +Default: ``'sessionid'`` The name of the cookie to use for sessions. This can be whatever you want. See the `session docs`_. @@ -556,8 +555,6 @@ Default:: "django.core.context_processors.debug", "django.core.context_processors.i18n") -**Only available in Django development version.** - A tuple of callables that are used to populate the context in ``DjangoContext``. These callables take a request object as their argument and return a dictionary of items to be merged into the context. @@ -567,8 +564,6 @@ TEMPLATE_DEBUG Default: ``False`` -**Only available in Django development version.** - A boolean that turns on/off template debug mode. If this is ``True``, the fancy error page will display a detailed report for any ``TemplateSyntaxError``. This report contains the relevant snippet of the template, with the appropriate line diff --git a/docs/templates.txt b/docs/templates.txt index d2539a3440..d4bb468bd5 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -278,8 +278,8 @@ In the above, the ``load`` tag loads the ``comments`` tag library, which then makes the ``comment_form`` tag available for use. Consult the documentation area in your admin to find the list of custom libraries in your installation. -**New in Django development version:** The ``{% load %}`` tag can take multiple -library names, separated by spaces. Example:: +The ``{% load %}`` tag can take multiple library names, separated by spaces. +Example:: {% load comments i18n %} @@ -500,8 +500,6 @@ Just like ``ifequal``, except it tests that the two arguments are not equal. include ~~~~~~~ -**Only available in Django development version.** - Loads a template and renders it with the current context. This is a way of "including" other templates within a template. diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 1b804e8e80..13805875cf 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -282,11 +282,6 @@ optional, third positional argument, ``processors``. In this example, the 'foo': 'bar', }, [ip_address_processor]) -Note: The concept of template-context processors is new in the Django -development version. In Django 0.90, ``DjangoContext`` automatically populates -the context with all of the values explained below, but it's not possible to -add and remove processors. - Here's what each of the default processors does: .. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects @@ -540,8 +535,6 @@ filters are registered. So, near the top of your module, put the following:: Writing custom template filters ------------------------------- -**This section applies to the Django development version.** - Custom filters are just Python functions that take one or two arguments: * The value of the variable (input) -- not necessarily a string. @@ -601,8 +594,6 @@ will use the function's name as the filter name. Writing custom template tags ---------------------------- -**This section applies to the Django development version.** - Tags are more complex than filters, because tags can do anything. A quick overview diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 5feb51a27d..1ef5437467 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -34,15 +34,15 @@ on your path, such as /usr/local/bin.) .. admonition:: Where should this code live? - If your background is in PHP, you're probably used to putting code under the - Web server's document root (in a place such as ``/var/www``). With Django, - you don't do that. It's not a good idea to put any of this Python code within - your Web server's document root, because it risks the possibility that - people may be able to view your code over the Web. That's not good for - security. + If your background is in PHP, you're probably used to putting code under the + Web server's document root (in a place such as ``/var/www``). With Django, + you don't do that. It's not a good idea to put any of this Python code within + your Web server's document root, because it risks the possibility that + people may be able to view your code over the Web. That's not good for + security. - Put your code in some directory **outside** of the document root, such as - ``/home/mycode``. + Put your code in some directory **outside** of the document root, such as + ``/home/mycode``. A project is a collection of settings for an instance of Django -- including database configuration, Django-specific options and application-specific @@ -50,24 +50,68 @@ settings. Let's look at what ``startproject`` created:: myproject/ __init__.py - apps/ - __init__.py + manage.py settings.py urls.py -First, edit ``myproject/settings.py``. It's a normal Python module with -module-level variables representing Django settings. Edit the file and change -these settings to match your database's connection parameters: +These files are: + + * ``manage.py``: A command-line utility that lets you interact with this + Django project in various ways. + * ``settings.py``: Settings/configuration for this Django project. + * ``urls.py``: The URL declarations for this Django project; a "table of + contents" of your Django-powered site. + +The development server +---------------------- + +Change into the ``myproject`` directory, if you haven't already, and run the +command ``python manage.py runserver``. You'll see the following output on the +command line:: + + Validating models... + 0 errors found. + + Starting server on port 8000 with settings module 'myproject.settings'. + Go to http://127.0.0.1:8000/ for Django. + Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows). + +You've started the Django development server, a lightweight, pure-Python Web +server that builds on the BaseHTTPServer included in Python's standard library. +We've included this with Django so you can develop things rapidly, without +having to deal with configuring Apache until you're ready for production. + +DON'T use this server in anything resembling a production environment. It's +intended only for use while developing. + +.. admonition:: Changing the port + + By default, the ``runserver`` command starts the development server on port + 8000. If you want to change the server's port, pass it as a command-line + argument:: + + python manage.py runserver 8080 + +Now that the server's running, visit http://127.0.0.1:8000/ with your Web +browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel. +It worked! + +Database setup +-------------- + +Now, edit ``settings.py``. It's a normal Python module with module-level +variables representing Django settings. Change these settings to match your +database's connection parameters: * ``DATABASE_ENGINE`` -- Either 'postgresql', 'mysql' or 'sqlite3'. More coming soon. * ``DATABASE_NAME`` -- The name of your database, or the full (absolute) - path to the database file if you're using sqlite. - * ``DATABASE_USER`` -- Your database username (not used for sqlite). - * ``DATABASE_PASSWORD`` -- Your database password (not used for sqlite). + path to the database file if you're using SQLite. + * ``DATABASE_USER`` -- Your database username (not used for SQLite). + * ``DATABASE_PASSWORD`` -- Your database password (not used for SQLite). * ``DATABASE_HOST`` -- The host your database is on. Leave this as an empty string if your database server is on the same physical machine - (not used for sqlite). + (not used for SQLite). .. admonition:: Note @@ -75,67 +119,55 @@ these settings to match your database's connection parameters: point. Do that with "``CREATE DATABASE database_name;``" within your database's interactive prompt. -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. If you opt to set the -``PYTHONPATH`` environment variable, note that you'll need to set it to the -*parent* directory of ``myproject``. (You can test this by typing -"import myproject" into the Python interactive prompt.) +Run the following command to initialize your database with Django's core +database tables:: -Run the following command:: + python manage.py init - django-admin.py init --settings=myproject.settings +If you don't see any errors, it worked. -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:: +If you're interested, run the command-line client for your database and type +``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to +display the tables Django created. - export DJANGO_SETTINGS_MODULE=myproject.settings +.. admonition:: About those database tables -On Windows, you'd use ``set`` instead:: - - set DJANGO_SETTINGS_MODULE=myproject.settings - -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 command-line client for your database and -type ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to -display the tables. - -.. _`Python path documentation`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000 + The tables created by ``manage.py init`` are for sessions, authentication + and other features Django provides. The next release of Django will have + a "lite" version of the ``init`` command that won't install any database + tables if you don't want them. Creating models =============== Now that your environment -- a "project" -- is set up, you're set to start -doing work. (You won't have to take care of this boring administrative stuff +doing work. (You won't have to take care of that boring administrative stuff again.) -Each application you write in Django -- e.g., a weblog system, a database of -public records or a simple poll app -- consists of a Python package, somewhere -on your Python path, that follows a certain convention. Django comes with a +Each application you write in Django consists of a Python package, somewhere +on your `Python path`_, that follows a certain convention. Django comes with a utility that automatically generates the basic directory structure of an app, so you can focus on writing code rather than creating directories. -In this tutorial, we'll create our poll app in the ``myproject/apps`` -directory, for simplicity. As a consequence, the app will be coupled to the -project -- that is, Python code within the poll app will refer to -``myproject.apps.polls``. Later in this tutorial, we'll discuss decoupling -your apps for distribution. +.. admonition:: Projects vs. apps -To create your app, change into the ``myproject/apps`` directory and type this -command:: + What's the difference between a project and an app? An app is a Web + application that does something -- e.g., a weblog system, a database of + public records or a simple poll app. A project is a collection of + configuration and apps for a particular Web site. A project can contain + multiple apps. An app can be in multiple projects. - django-admin.py startapp polls +In this tutorial, we'll create our poll app in the ``myproject`` directory, +for simplicity. As a consequence, the app will be coupled to the project -- +that is, Python code within the poll app will refer to ``myproject.polls``. +Later in this tutorial, we'll discuss decoupling your apps for distribution. -(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.) +To create your app, make sure you're in the ``myproject`` directory and type +this command:: -That'll create a directory structure like this:: + python manage.py startapp polls + +That'll create a directory ``polls``, which is laid out like this:: polls/ __init__.py @@ -201,6 +233,7 @@ Finally, note a relationship is defined, using ``meta.ForeignKey``. That tells Django each Choice is related to a single Poll. Django supports all the common database relationships: many-to-ones, many-to-manys and one-to-ones. +.. _`Python path`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000 .. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself Activating models @@ -209,32 +242,30 @@ Activating models That small bit of model code gives Django a lot of information. With it, Django is able to: -* Create a database schema (``CREATE TABLE`` statements) for this app. -* Create a Python database-access API for accessing Poll and Choice objects. + * Create a database schema (``CREATE TABLE`` statements) for this app. + * Create a Python database-access API for accessing Poll and Choice objects. But first we need to tell our project that the ``polls`` app is installed. .. admonition:: Philosophy - Django apps are "pluggable": You can use an app in multiple - projects, and you can distribute apps, because they don't have to be tied to - a given Django installation. + Django apps are "pluggable": You can use an app in multiple projects, and + you can distribute apps, because they don't have to be tied to a given + Django installation. -Edit the myproject/settings.py file again, and change the ``INSTALLED_APPS`` -setting to include the string "myproject.apps.polls". So it'll look like this:: +Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting +to include the string ``'myproject.polls'``. So it'll look like this:: INSTALLED_APPS = ( - 'myproject.apps.polls', + 'myproject.polls', ) -(Don't forget the trailing comma because of Python's rules about single-value -tuples.) +(Don't forget the trailing comma, because of Python's rule about single-value +tuples: Without a trailing comma, Python wouldn't know this was a tuple.) -Now Django knows myproject includes the polls app. Let's run another command:: +Now Django knows ``myproject`` includes the ``polls`` app. Let's run another command:: - django-admin.py sql polls - -(Note that it doesn't matter which directory you're in when you run this command.) + python manage.py sql polls You should see the following (the CREATE TABLE SQL statements for the polls app):: @@ -255,8 +286,8 @@ You should see the following (the CREATE TABLE SQL statements for the polls app) Note the following: * Table names are automatically generated by combining the name of the app - (polls) with a plural version of the object name (polls and choices). (You - can override this behavior.) + (``polls``) with a plural version of the object name (polls and choices). + (You can override this behavior.) * Primary keys (IDs) are added automatically. (You can override this, too.) @@ -265,26 +296,26 @@ Note the following: * The foreign key relationship is made explicit by a ``REFERENCES`` statement. - * It's tailored to the database you're using, so database-specific field types - such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or ``integer - primary key`` (SQLite) are handled for you automatically. Same goes for - quoting of field names -- e.g., using double quotes or single quotes. The - author of this tutorial runs PostgreSQL, so the example output is in - PostgreSQL syntax. + * It's tailored to the database you're using, so database-specific field + types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or + ``integer primary key`` (SQLite) are handled for you automatically. Same + goes for quoting of field names -- e.g., using double quotes or single + quotes. The author of this tutorial runs PostgreSQL, so the example + output is inPostgreSQL syntax. If you're interested, also run the following commands: - * ``django-admin.py sqlinitialdata polls`` -- Outputs the initial-data + * ``python manage.py sqlinitialdata polls`` -- Outputs the initial-data inserts required for Django's admin framework. - * ``django-admin.py sqlclear polls`` -- Outputs the necessary ``DROP + * ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP TABLE`` statements for this app, according to which tables already exist in your database (if any). - * ``django-admin.py sqlindexes polls`` -- Outputs the ``CREATE INDEX`` + * ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX`` statements for this app. - * ``django-admin.py sqlall polls`` -- A combination of 'sql' and + * ``python manage.py sqlall polls`` -- A combination of 'sql' and 'sqlinitialdata'. Looking at the output of those commands can help you understand what's actually @@ -293,23 +324,50 @@ happening under the hood. Now, run this command to create the database tables for the polls app automatically:: - django-admin.py install polls + python manage.py install polls Behind the scenes, all that command does is take the output of -``django-admin.py sqlall polls`` and execute it in the database pointed-to by +``python manage.py sqlall polls`` and execute it in the database pointed-to by your Django settings file. -Read the `django-admin.py documentation`_ for full information on what this -utility can do. +Read the `django-admin.py documentation`_ for full information on what the +``manage.py`` utility can do. .. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/ Playing with the API ==================== -Now, make sure your DJANGO_SETTINGS_MODULE environment variable is set (as -explained above), and open the Python interactive shell to play around with the -free Python API Django gives you:: +Now, let's hop into the interactive Python shell and play around with the free +API Django gives you. To invoke the Python shell, use this command:: + + python manage.py shell + +We're using this instead of simply typing "python", because ``manage.py`` sets +up the project's environment for you. "Setting up the environment" involves two +things: + + * Putting ``myproject`` on ``sys.path``. For flexibility, several pieces of + Django refer to projects in Python dotted-path notation (e.g. + ``'myproject.polls.models'``). In order for this to work, the + ``myproject`` package has to be on ``sys.path``. + + We've already seen one example of this: the ``INSTALLED_APPS`` setting is + a list of packages in dotted-path notation. + + * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives + Django the path to your ``settings.py`` file. + +.. admonition:: Bypassing manage.py + + If you'd rather not use ``manage.py``, no problem. Just make sure + ``myproject`` is at the root level on the Python path (i.e., + ``import myproject`` works) and set the ``DJANGO_SETTINGS_MODULE`` + environment variable to ``myproject.settings``. + + For more information on all of this, see the `django-admin.py documentation`_. + +Once you're in the shell, explore the database API:: # Modules are dynamically created within django.models. # Their names are plural versions of the model class names. @@ -326,7 +384,10 @@ free Python API Django gives you:: # Save the object into the database. You have to call save() explicitly. >>> p.save() - # Now it has an ID. + # Now it has an ID. Note that this might say "1L" instead of "1", depending + # on which database you're using. That's no biggie; it just means your + # database backend prefers to return integers as Python long integer + # objects. >>> p.id 1 @@ -375,7 +436,8 @@ Note ``import datetime`` wasn't necessary. Each model method has access to a handful of commonly-used variables for convenience, including the ``datetime`` module from the Python standard library. -Let's jump back into the Python interactive shell:: +Let's jump back into the Python interactive shell by running +``python manage.py shell`` again:: >>> from django.models.polls import polls, choices # Make sure our __repr__() addition worked. diff --git a/docs/tutorial02.txt b/docs/tutorial02.txt index 21454523d0..c7a38f8a01 100644 --- a/docs/tutorial02.txt +++ b/docs/tutorial02.txt @@ -31,7 +31,7 @@ The Django admin site is not activated by default -- it's an opt-in thing. To activate the admin site for your installation, do these three things: * Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting. - * Run the command ``django-admin.py install admin``. This will create an + * Run the command ``python manage.py install admin``. This will create an extra database table that the admin needs. * Edit your ``myproject/urls.py`` file and uncomment the line below "Uncomment this for admin:". This file is a URLconf; we'll dig into @@ -43,28 +43,18 @@ Create a user account Run the following command to create a superuser account for your admin site:: - django-admin.py createsuperuser --settings=myproject.settings + python manage.py createsuperuser The script will prompt you for a username, e-mail address and password (twice). 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. +Let's start the development server and explore the admin site. -Just run the following command to start the server:: +Recall from Tutorial 1 that you start the development server like so:: - django-admin.py runserver --settings=myproject.settings - -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 --settings=myproject.settings - -DON'T use this server in anything resembling a production environment. It's -intended only for use while developing. + python manage.py runserver Now, open a Web browser and go to "/admin/" on your local domain -- e.g., http://127.0.0.1:8000/admin/. You should see the admin's login screen: @@ -91,8 +81,8 @@ Make the poll app modifiable in the admin But where's our poll app? It's not displayed on the admin index page. -Just one thing to do: We need to specify in the ``polls.Poll`` model that Poll -objects have an admin interface. Edit the ``myproject/apps/polls/models/polls.py`` +Just one thing to do: We need to specify in the ``Poll`` model that ``Poll`` +objects have an admin interface. Edit the ``myproject/polls/models/polls.py`` file and make the following change to add an inner ``Meta`` class with an ``admin`` attribute:: @@ -101,11 +91,13 @@ file and make the following change to add an inner ``Meta`` class with an class Meta: admin = meta.Admin() -The ``class Meta`` contains all non-field metadata about this model. +The ``class Meta`` contains all `non-field metadata`_ about this model. Now reload the Django admin page to see your changes. Note that you don't have to restart the development server -- it auto-reloads code. +.. _non-field metadata: http://www.djangoproject.com/documentation/model_api/#meta-options + Explore the free admin functionality ==================================== @@ -216,14 +208,14 @@ aren't commonly used:: Adding related objects ====================== -OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and the admin -page doesn't display choices. +OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and +the admin page doesn't display choices. Yet. -In this case, there are two ways to solve this problem. The first is to give -the ``Choice`` model its own ``admin`` attribute, just as we did with ``Poll``. -Here's what that would look like:: +There are two ways to solve this problem. The first is to give the ``Choice`` +model its own ``admin`` attribute, just as we did with ``Poll``. Here's what +that would look like:: class Choice(meta.Model): # ... @@ -237,7 +229,8 @@ looks like this: :alt: Choice admin page In that form, the "Poll" field is a select box containing every poll in the -database. In our case, only one poll exists at this point. +database. Django knows that a ``ForeignKey`` should be represented in the admin +as a ``