Updated tutorials 1-4 to use manage.py instead of django-admin.py, new directory layout (no /apps/ subdirectory) and other various tweaks

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1901 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-01-11 02:06:27 +00:00
parent b94d78772f
commit 5de00f785f
5 changed files with 232 additions and 156 deletions

View File

@ -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
@ -210,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
------------
@ -221,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

View File

@ -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.

View File

@ -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 ``<select>`` box. In our case, only one poll exists at this point.
Also note the "Add Another" link next to "Poll." Every object with a ForeignKey
relationship to another gets this for free. When you click "Add Another," you'll
@ -363,7 +356,7 @@ This is shaping up well. Let's add some search capability::
That adds a search box at the top of the change list. When somebody enters
search terms, Django will search the ``question`` field. You can use as many
fields as you'd like -- although because it uses a LIKE query behind the
fields as you'd like -- although because it uses a ``LIKE`` query behind the
scenes, keep it reasonable, to keep your database happy.
Finally, because Poll objects have dates, it'd be convenient to be able to
@ -444,7 +437,7 @@ hard-code links to object-specific admin pages in whatever way you think is
best.
Django offers another shortcut in this department. Run the command
``django-admin.py adminindex polls`` to get a chunk of template code for
``python manage.py adminindex polls`` to get a chunk of template code for
inclusion in the admin index template. It's a useful starting point.
For full details on customizing the look and feel of the Django admin site in

View File

@ -62,7 +62,7 @@ arguments from the dictionary (an optional third item in the tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
For more details on URLconfs, see the `URLconf documentation`_.
When you ran ``django-admin.py startproject myproject`` at the beginning of
When you ran ``python manage.py startproject myproject`` at the beginning of
Tutorial 1, it created a default URLconf in ``myproject/urls.py``. It also
automatically set your ``ROOT_URLCONF`` setting to point at that file::
@ -73,33 +73,33 @@ Time for an example. Edit ``myproject/urls.py`` so it looks like this::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^polls/$', 'myproject.apps.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
(r'^polls/$', 'myproject.polls.views.index'),
(r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
(r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
(r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
)
This is worth a review. When somebody requests a page from your Web site --
say, "/polls/23/", Django will load this Python module, because it's pointed to
by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns``
and traverses the regular expressions in order. When it finds a regular
expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the
associated Python package/module: ``myproject.apps.polls.views.detail``. That
corresponds to the function ``detail()`` in ``myproject/apps/polls/views.py``.
expression that matches -- ``r'^polls/(\d+)/$'`` -- it loads the
associated Python package/module: ``myproject.polls.views.detail``. That
corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
Finally, it calls that ``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23')
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using
``(?P<name>pattern)`` "captures" the text matched by ``pattern`` and sends it
as a keyword argument to the view function.
The ``poll_id='23'`` part comes from ``(\d+)``. Using parenthesis around a
pattern "captures" the text matched by that pattern and sends it as an argument
to the view function.
Because the URL patterns are regular expressions, there really is no limit on
what you can do with them. And there's no need to add URL cruft such as
``.php`` -- unless you have a sick sense of humor, in which case you can do
something like this::
(r'^polls/latest\.php$', 'myproject.apps.polls.views.index'),
(r'^polls/latest\.php$', 'myproject.polls.views.index'),
But, don't do that. It's silly.
@ -128,24 +128,24 @@ make sure Django is following the URLconf properly.
Fire up the Django development Web server::
django-admin.py runserver --settings=myproject.settings
python manage.py runserver
Now go to "http://localhost:8000/polls/" on your domain in your Web browser.
You should get a pleasantly-colored error page with the following message::
ViewDoesNotExist at /polls/
Tried index in module myproject.apps.polls.views. Error was: 'module'
Tried index in module myproject.polls.views. Error was: 'module'
object has no attribute 'index'
This error happened because you haven't written a function ``index()`` in the
module ``myproject/apps/polls/views.py``.
module ``myproject/polls/views.py``.
Try "/polls/23/", "/polls/23/results/" and "/polls/23/vote/". The error
messages tell you which view Django tried (and failed to find, because you
haven't written any views yet).
Time to write the first view. Open the file ``myproject/apps/polls/views.py``
Time to write the first view. Open the file ``myproject/polls/views.py``
and put the following Python code in it::
from django.utils.httpwrappers import HttpResponse
@ -222,9 +222,9 @@ filesystem, whose contents Django can access. (Django runs as whatever user
your server runs.) Don't put them under your document root, though. You
probably shouldn't make them public, just for security's sake.
Then edit ``TEMPLATE_DIRS`` in your settings file (``settings.py``) to tell
Django where it can find templates -- just as you did in the "Customize the
admin look and feel" section of Tutorial 2.
Then edit ``TEMPLATE_DIRS`` in your ``settings.py`` to tell Django where it can
find templates -- just as you did in the "Customize the admin look and feel"
section of Tutorial 2.
When you've done that, create a directory ``polls`` in your template directory.
Within that, create a file called ``index.html``. Django requires that
@ -385,19 +385,19 @@ Take some time to play around with the views and template system. As you edit
the URLconf, you may notice there's a fair bit of redundancy in it::
urlpatterns = patterns('',
(r'^polls/$', 'myproject.apps.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
(r'^polls/$', 'myproject.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
)
Namely, ``myproject.apps.polls.views`` is in every callback.
Namely, ``myproject.polls.views`` is in every callback.
Because this is a common case, the URLconf framework provides a shortcut for
common prefixes. You can factor out the common prefixes and add them as the
first argument to ``patterns()``, like so::
urlpatterns = patterns('myproject.apps.polls.views',
urlpatterns = patterns('myproject.polls.views',
(r'^polls/$', 'index'),
(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
@ -416,18 +416,18 @@ is, each particular app should be transferrable to another Django installation
with minimal fuss.
Our poll app is pretty decoupled at this point, thanks to the strict directory
structure that ``django-admin.py startapp`` created, but one part of it is
structure that ``python manage.py startapp`` created, but one part of it is
coupled to the Django settings: The URLconf.
We've been editing the URLs in ``myproject/urls.py``, but the URL design of an
app is specific to the app, not to the Django installation -- so let's move the
URLs within the app directory.
Copy the file ``myproject/urls.py`` to ``myproject/apps/polls/urls.py``. Then,
Copy the file ``myproject/urls.py`` to ``myproject/polls/urls.py``. Then,
change ``myproject/urls.py`` to remove the poll-specific URLs and insert an
``include()``::
(r'^polls/', include('myproject.apps.polls.urls')),
(r'^polls/', include('myproject.polls.urls')),
``include()``, simply, references another URLconf. Note that the regular
expression doesn't have a ``$`` (end-of-string match character) but has the
@ -439,14 +439,14 @@ Here's what happens if a user goes to "/polls/34/" in this system:
* Django will find the match at ``'^polls/'``
* It will strip off the matching text (``"polls/"``) and send the remaining
text -- ``"34/"`` -- to the 'myproject.apps.polls.urls' urlconf for
text -- ``"34/"`` -- to the 'myproject.polls.urls' urlconf for
further processing.
Now that we've decoupled that, we need to decouple the
'myproject.apps.polls.urls' urlconf by removing the leading "polls/" from each
'myproject.polls.urls' urlconf by removing the leading "polls/" from each
line::
urlpatterns = patterns('myproject.apps.polls.views',
urlpatterns = patterns('myproject.polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),

View File

@ -44,9 +44,9 @@ Now, let's create a Django view that handles the submitted data and does
something with it. Remember, in `Tutorial 3`_, we create a URLconf that
included this line::
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
So let's create a ``vote()`` function in ``myproject/apps/polls/views.py``::
So let's create a ``vote()`` function in ``myproject/polls/views.py``::
from django.core.extensions import get_object_or_404, render_to_response
from django.models.polls import choices, polls
@ -158,7 +158,7 @@ so far::
from django.conf.urls.defaults import *
urlpatterns = patterns('myproject.apps.polls.views',
urlpatterns = patterns('myproject.polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),
@ -178,7 +178,7 @@ Change it like so::
(r'^$', 'django.views.generic.list_detail.object_list', info_dict),
(r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict),
(r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results')),
(r'^(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
(r'^(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
)
We're using two generic views here: ``object_list`` and ``object_detail``.