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:
parent
b94d78772f
commit
5de00f785f
|
@ -6,14 +6,29 @@ The django-admin.py utility
|
||||||
This document outlines all it can do.
|
This document outlines all it can do.
|
||||||
|
|
||||||
The ``django-admin.py`` script should be on your system path if you installed
|
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
|
``site-packages/django/bin`` within your Python installation. Consider
|
||||||
symlinking to it from some place on your path, such as ``/usr/local/bin``.
|
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
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
``django-admin.py action [options]``
|
``django-admin.py action [options]``
|
||||||
|
``manage.py action [options]``
|
||||||
|
|
||||||
``action`` should be one of the actions listed in this document. ``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
|
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,
|
in Python path syntax, e.g. "myproject.settings". If this isn't provided,
|
||||||
``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable.
|
``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
|
--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
|
isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment
|
||||||
variable.
|
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
|
.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
|
||||||
|
|
||||||
--help
|
--help
|
||||||
|
|
|
@ -34,15 +34,15 @@ on your path, such as /usr/local/bin.)
|
||||||
|
|
||||||
.. admonition:: Where should this code live?
|
.. admonition:: Where should this code live?
|
||||||
|
|
||||||
If your background is in PHP, you're probably used to putting code under the
|
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,
|
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
|
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
|
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
|
people may be able to view your code over the Web. That's not good for
|
||||||
security.
|
security.
|
||||||
|
|
||||||
Put your code in some directory **outside** of the document root, such as
|
Put your code in some directory **outside** of the document root, such as
|
||||||
``/home/mycode``.
|
``/home/mycode``.
|
||||||
|
|
||||||
A project is a collection of settings for an instance of Django -- including
|
A project is a collection of settings for an instance of Django -- including
|
||||||
database configuration, Django-specific options and application-specific
|
database configuration, Django-specific options and application-specific
|
||||||
|
@ -50,24 +50,68 @@ settings. Let's look at what ``startproject`` created::
|
||||||
|
|
||||||
myproject/
|
myproject/
|
||||||
__init__.py
|
__init__.py
|
||||||
apps/
|
manage.py
|
||||||
__init__.py
|
|
||||||
settings.py
|
settings.py
|
||||||
urls.py
|
urls.py
|
||||||
|
|
||||||
First, edit ``myproject/settings.py``. It's a normal Python module with
|
These files are:
|
||||||
module-level variables representing Django settings. Edit the file and change
|
|
||||||
these settings to match your database's connection parameters:
|
* ``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'.
|
* ``DATABASE_ENGINE`` -- Either 'postgresql', 'mysql' or 'sqlite3'.
|
||||||
More coming soon.
|
More coming soon.
|
||||||
* ``DATABASE_NAME`` -- The name of your database, or the full (absolute)
|
* ``DATABASE_NAME`` -- The name of your database, or the full (absolute)
|
||||||
path to the database file if you're using sqlite.
|
path to the database file if you're using SQLite.
|
||||||
* ``DATABASE_USER`` -- Your database username (not used for sqlite).
|
* ``DATABASE_USER`` -- Your database username (not used for SQLite).
|
||||||
* ``DATABASE_PASSWORD`` -- Your database password (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
|
* ``DATABASE_HOST`` -- The host your database is on. Leave this as an
|
||||||
empty string if your database server is on the same physical machine
|
empty string if your database server is on the same physical machine
|
||||||
(not used for sqlite).
|
(not used for SQLite).
|
||||||
|
|
||||||
.. admonition:: Note
|
.. 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
|
point. Do that with "``CREATE DATABASE database_name;``" within your
|
||||||
database's interactive prompt.
|
database's interactive prompt.
|
||||||
|
|
||||||
Now, take a second to make sure ``myproject`` is on your Python path. You
|
Run the following command to initialize your database with Django's core
|
||||||
can do this by copying ``myproject`` to Python's ``site-packages`` directory,
|
database tables::
|
||||||
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::
|
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
|
If you're interested, run the command-line client for your database and type
|
||||||
you're using. Here, we're doing that by specifying ``settings=`` on the command
|
``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
|
||||||
line, but that can get tedious. If you don't want to type ``settings=`` each
|
display the tables Django created.
|
||||||
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
|
.. admonition:: About those database tables
|
||||||
|
|
||||||
On Windows, you'd use ``set`` instead::
|
The tables created by ``manage.py init`` are for sessions, authentication
|
||||||
|
and other features Django provides. The next release of Django will have
|
||||||
set DJANGO_SETTINGS_MODULE=myproject.settings
|
a "lite" version of the ``init`` command that won't install any database
|
||||||
|
tables if you don't want them.
|
||||||
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
|
|
||||||
|
|
||||||
Creating models
|
Creating models
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Now that your environment -- a "project" -- is set up, you're set to start
|
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.)
|
again.)
|
||||||
|
|
||||||
Each application you write in Django -- e.g., a weblog system, a database of
|
Each application you write in Django consists of a Python package, somewhere
|
||||||
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
|
||||||
on your Python path, that follows a certain convention. Django comes with a
|
|
||||||
utility that automatically generates the basic directory structure of an app,
|
utility that automatically generates the basic directory structure of an app,
|
||||||
so you can focus on writing code rather than creating directories.
|
so you can focus on writing code rather than creating directories.
|
||||||
|
|
||||||
In this tutorial, we'll create our poll app in the ``myproject/apps``
|
.. admonition:: Projects vs. 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.
|
|
||||||
|
|
||||||
To create your app, change into the ``myproject/apps`` directory and type this
|
What's the difference between a project and an app? An app is a Web
|
||||||
command::
|
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
|
To create your app, make sure you're in the ``myproject`` directory and type
|
||||||
will assume you've either set your ``DJANGO_SETTINGS_MODULE`` environment
|
this command::
|
||||||
variable or included the ``--settings`` option in your call to the 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/
|
polls/
|
||||||
__init__.py
|
__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
|
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.
|
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
|
.. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself
|
||||||
|
|
||||||
Activating models
|
Activating models
|
||||||
|
@ -209,32 +242,30 @@ Activating models
|
||||||
That small bit of model code gives Django a lot of information. With it, Django
|
That small bit of model code gives Django a lot of information. With it, Django
|
||||||
is able to:
|
is able to:
|
||||||
|
|
||||||
* Create a database schema (``CREATE TABLE`` statements) for this app.
|
* Create a database schema (``CREATE TABLE`` statements) for this app.
|
||||||
* Create a Python database-access API for accessing Poll and Choice objects.
|
* 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.
|
But first we need to tell our project that the ``polls`` app is installed.
|
||||||
|
|
||||||
.. admonition:: Philosophy
|
.. admonition:: Philosophy
|
||||||
|
|
||||||
Django apps are "pluggable": You can use an app in multiple
|
Django apps are "pluggable": You can use an app in multiple projects, and
|
||||||
projects, and you can distribute apps, because they don't have to be tied to
|
you can distribute apps, because they don't have to be tied to a given
|
||||||
a given Django installation.
|
Django installation.
|
||||||
|
|
||||||
Edit the myproject/settings.py file again, and change the ``INSTALLED_APPS``
|
Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting
|
||||||
setting to include the string "myproject.apps.polls". So it'll look like this::
|
to include the string ``'myproject.polls'``. So it'll look like this::
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
'myproject.apps.polls',
|
'myproject.polls',
|
||||||
)
|
)
|
||||||
|
|
||||||
(Don't forget the trailing comma because of Python's rules about single-value
|
(Don't forget the trailing comma, because of Python's rule about single-value
|
||||||
tuples.)
|
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
|
python manage.py sql polls
|
||||||
|
|
||||||
(Note that it doesn't matter which directory you're in when you run this command.)
|
|
||||||
|
|
||||||
You should see the following (the CREATE TABLE SQL statements for the polls app)::
|
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:
|
Note the following:
|
||||||
|
|
||||||
* Table names are automatically generated by combining the name of the app
|
* 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
|
(``polls``) with a plural version of the object name (polls and choices).
|
||||||
can override this behavior.)
|
(You can override this behavior.)
|
||||||
|
|
||||||
* Primary keys (IDs) are added automatically. (You can override this, too.)
|
* 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.
|
* 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
|
* It's tailored to the database you're using, so database-specific field
|
||||||
such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or ``integer
|
types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or
|
||||||
primary key`` (SQLite) are handled for you automatically. Same goes for
|
``integer primary key`` (SQLite) are handled for you automatically. Same
|
||||||
quoting of field names -- e.g., using double quotes or single quotes. The
|
goes for quoting of field names -- e.g., using double quotes or single
|
||||||
author of this tutorial runs PostgreSQL, so the example output is in
|
quotes. The author of this tutorial runs PostgreSQL, so the example
|
||||||
PostgreSQL syntax.
|
output is inPostgreSQL syntax.
|
||||||
|
|
||||||
If you're interested, also run the following commands:
|
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.
|
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
|
TABLE`` statements for this app, according to which tables already exist
|
||||||
in your database (if any).
|
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.
|
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'.
|
'sqlinitialdata'.
|
||||||
|
|
||||||
Looking at the output of those commands can help you understand what's actually
|
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
|
Now, run this command to create the database tables for the polls app
|
||||||
automatically::
|
automatically::
|
||||||
|
|
||||||
django-admin.py install polls
|
python manage.py install polls
|
||||||
|
|
||||||
Behind the scenes, all that command does is take the output of
|
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.
|
your Django settings file.
|
||||||
|
|
||||||
Read the `django-admin.py documentation`_ for full information on what this
|
Read the `django-admin.py documentation`_ for full information on what the
|
||||||
utility can do.
|
``manage.py`` utility can do.
|
||||||
|
|
||||||
.. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
|
.. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
|
||||||
|
|
||||||
Playing with the API
|
Playing with the API
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Now, make sure your DJANGO_SETTINGS_MODULE environment variable is set (as
|
Now, let's hop into the interactive Python shell and play around with the free
|
||||||
explained above), and open the Python interactive shell to play around with the
|
API Django gives you. To invoke the Python shell, use this command::
|
||||||
free Python API Django gives you::
|
|
||||||
|
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.
|
# Modules are dynamically created within django.models.
|
||||||
# Their names are plural versions of the model class names.
|
# 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.
|
# Save the object into the database. You have to call save() explicitly.
|
||||||
>>> p.save()
|
>>> 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
|
>>> p.id
|
||||||
1
|
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
|
a handful of commonly-used variables for convenience, including the
|
||||||
``datetime`` module from the Python standard library.
|
``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
|
>>> from django.models.polls import polls, choices
|
||||||
# Make sure our __repr__() addition worked.
|
# Make sure our __repr__() addition worked.
|
||||||
|
|
|
@ -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:
|
activate the admin site for your installation, do these three things:
|
||||||
|
|
||||||
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
|
* 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.
|
extra database table that the admin needs.
|
||||||
* Edit your ``myproject/urls.py`` file and uncomment the line below
|
* Edit your ``myproject/urls.py`` file and uncomment the line below
|
||||||
"Uncomment this for admin:". This file is a URLconf; we'll dig into
|
"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::
|
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).
|
The script will prompt you for a username, e-mail address and password (twice).
|
||||||
|
|
||||||
Start the development server
|
Start the development server
|
||||||
============================
|
============================
|
||||||
|
|
||||||
To make things easy, Django comes with a pure-Python Web server that builds on
|
Let's start the development server and explore the admin site.
|
||||||
the BaseHTTPServer included in Python's standard library. Let's start the
|
|
||||||
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
|
python manage.py runserver
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
|
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:
|
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.
|
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
|
Just one thing to do: We need to specify in the ``Poll`` model that ``Poll``
|
||||||
objects have an admin interface. Edit the ``myproject/apps/polls/models/polls.py``
|
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
|
file and make the following change to add an inner ``META`` class with an
|
||||||
``admin`` attribute::
|
``admin`` attribute::
|
||||||
|
|
||||||
|
@ -101,11 +91,13 @@ file and make the following change to add an inner ``META`` class with an
|
||||||
class META:
|
class META:
|
||||||
admin = meta.Admin()
|
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
|
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.
|
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
|
Explore the free admin functionality
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
|
@ -216,14 +208,14 @@ aren't commonly used::
|
||||||
Adding related objects
|
Adding related objects
|
||||||
======================
|
======================
|
||||||
|
|
||||||
OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and the admin
|
OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and
|
||||||
page doesn't display choices.
|
the admin page doesn't display choices.
|
||||||
|
|
||||||
Yet.
|
Yet.
|
||||||
|
|
||||||
In this case, there are two ways to solve this problem. The first is to give
|
There are two ways to solve this problem. The first is to give the ``Choice``
|
||||||
the ``Choice`` model its own ``admin`` attribute, just as we did with ``Poll``.
|
model its own ``admin`` attribute, just as we did with ``Poll``. Here's what
|
||||||
Here's what that would look like::
|
that would look like::
|
||||||
|
|
||||||
class Choice(meta.Model):
|
class Choice(meta.Model):
|
||||||
# ...
|
# ...
|
||||||
|
@ -237,7 +229,8 @@ looks like this:
|
||||||
:alt: Choice admin page
|
:alt: Choice admin page
|
||||||
|
|
||||||
In that form, the "Poll" field is a select box containing every poll in the
|
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
|
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
|
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
|
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
|
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.
|
scenes, keep it reasonable, to keep your database happy.
|
||||||
|
|
||||||
Finally, because Poll objects have dates, it'd be convenient to be able to
|
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.
|
best.
|
||||||
|
|
||||||
Django offers another shortcut in this department. Run the command
|
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.
|
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
|
For full details on customizing the look and feel of the Django admin site in
|
||||||
|
|
|
@ -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 on ``HTTPRequest`` objects, see the `request and response documentation`_.
|
||||||
For more details on URLconfs, see the `URLconf 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
|
Tutorial 1, it created a default URLconf in ``myproject/urls.py``. It also
|
||||||
automatically set your ``ROOT_URLCONF`` setting to point at that file::
|
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 *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^polls/$', 'myproject.apps.polls.views.index'),
|
(r'^polls/$', 'myproject.polls.views.index'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
|
(r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
|
(r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
|
(r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
|
||||||
)
|
)
|
||||||
|
|
||||||
This is worth a review. When somebody requests a page from your Web site --
|
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
|
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``
|
by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns``
|
||||||
and traverses the regular expressions in order. When it finds a regular
|
and traverses the regular expressions in order. When it finds a regular
|
||||||
expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the
|
expression that matches -- ``r'^polls/(\d+)/$'`` -- it loads the
|
||||||
associated Python package/module: ``myproject.apps.polls.views.detail``. That
|
associated Python package/module: ``myproject.polls.views.detail``. That
|
||||||
corresponds to the function ``detail()`` in ``myproject/apps/polls/views.py``.
|
corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
|
||||||
Finally, it calls that ``detail()`` function like so::
|
Finally, it calls that ``detail()`` function like so::
|
||||||
|
|
||||||
detail(request=<HttpRequest object>, poll_id='23')
|
detail(request=<HttpRequest object>, poll_id='23')
|
||||||
|
|
||||||
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using
|
The ``poll_id='23'`` part comes from ``(\d+)``. Using parenthesis around a
|
||||||
``(?P<name>pattern)`` "captures" the text matched by ``pattern`` and sends it
|
pattern "captures" the text matched by that pattern and sends it as an argument
|
||||||
as a keyword argument to the view function.
|
to the view function.
|
||||||
|
|
||||||
Because the URL patterns are regular expressions, there really is no limit on
|
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
|
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
|
``.php`` -- unless you have a sick sense of humor, in which case you can do
|
||||||
something like this::
|
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.
|
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::
|
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.
|
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::
|
You should get a pleasantly-colored error page with the following message::
|
||||||
|
|
||||||
ViewDoesNotExist at /polls/
|
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'
|
object has no attribute 'index'
|
||||||
|
|
||||||
This error happened because you haven't written a function ``index()`` in the
|
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
|
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
|
messages tell you which view Django tried (and failed to find, because you
|
||||||
haven't written any views yet).
|
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::
|
and put the following Python code in it::
|
||||||
|
|
||||||
from django.utils.httpwrappers import HttpResponse
|
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
|
your server runs.) Don't put them under your document root, though. You
|
||||||
probably shouldn't make them public, just for security's sake.
|
probably shouldn't make them public, just for security's sake.
|
||||||
|
|
||||||
Then edit ``TEMPLATE_DIRS`` in your settings file (``settings.py``) to tell
|
Then edit ``TEMPLATE_DIRS`` in your ``settings.py`` to tell Django where it can
|
||||||
Django where it can find templates -- just as you did in the "Customize the
|
find templates -- just as you did in the "Customize the admin look and feel"
|
||||||
admin look and feel" section of Tutorial 2.
|
section of Tutorial 2.
|
||||||
|
|
||||||
When you've done that, create a directory ``polls`` in your template directory.
|
When you've done that, create a directory ``polls`` in your template directory.
|
||||||
Within that, create a file called ``index.html``. Django requires that
|
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::
|
the URLconf, you may notice there's a fair bit of redundancy in it::
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^polls/$', 'myproject.apps.polls.views.index'),
|
(r'^polls/$', 'myproject.polls.views.index'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
|
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.polls.views.detail'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
|
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.polls.views.results'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
|
(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
|
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
|
common prefixes. You can factor out the common prefixes and add them as the
|
||||||
first argument to ``patterns()``, like so::
|
first argument to ``patterns()``, like so::
|
||||||
|
|
||||||
urlpatterns = patterns('myproject.apps.polls.views',
|
urlpatterns = patterns('myproject.polls.views',
|
||||||
(r'^polls/$', 'index'),
|
(r'^polls/$', 'index'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
|
(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
|
||||||
(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
|
(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.
|
with minimal fuss.
|
||||||
|
|
||||||
Our poll app is pretty decoupled at this point, thanks to the strict directory
|
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.
|
coupled to the Django settings: The URLconf.
|
||||||
|
|
||||||
We've been editing the URLs in ``myproject/urls.py``, but the URL design of an
|
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
|
app is specific to the app, not to the Django installation -- so let's move the
|
||||||
URLs within the app directory.
|
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
|
change ``myproject/urls.py`` to remove the poll-specific URLs and insert an
|
||||||
``include()``::
|
``include()``::
|
||||||
|
|
||||||
(r'^polls/', include('myproject.apps.polls.urls')),
|
(r'^polls/', include('myproject.polls.urls')),
|
||||||
|
|
||||||
``include()``, simply, references another URLconf. Note that the regular
|
``include()``, simply, references another URLconf. Note that the regular
|
||||||
expression doesn't have a ``$`` (end-of-string match character) but has the
|
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/'``
|
* Django will find the match at ``'^polls/'``
|
||||||
* It will strip off the matching text (``"polls/"``) and send the remaining
|
* 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.
|
further processing.
|
||||||
|
|
||||||
Now that we've decoupled that, we need to decouple the
|
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::
|
line::
|
||||||
|
|
||||||
urlpatterns = patterns('myproject.apps.polls.views',
|
urlpatterns = patterns('myproject.polls.views',
|
||||||
(r'^$', 'index'),
|
(r'^$', 'index'),
|
||||||
(r'^(?P<poll_id>\d+)/$', 'detail'),
|
(r'^(?P<poll_id>\d+)/$', 'detail'),
|
||||||
(r'^(?P<poll_id>\d+)/results/$', 'results'),
|
(r'^(?P<poll_id>\d+)/results/$', 'results'),
|
||||||
|
|
|
@ -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
|
something with it. Remember, in `Tutorial 3`_, we create a URLconf that
|
||||||
included this line::
|
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.core.extensions import get_object_or_404, render_to_response
|
||||||
from django.models.polls import choices, polls
|
from django.models.polls import choices, polls
|
||||||
|
@ -158,7 +158,7 @@ so far::
|
||||||
|
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('myproject.apps.polls.views',
|
urlpatterns = patterns('myproject.polls.views',
|
||||||
(r'^$', 'index'),
|
(r'^$', 'index'),
|
||||||
(r'^(?P<poll_id>\d+)/$', 'detail'),
|
(r'^(?P<poll_id>\d+)/$', 'detail'),
|
||||||
(r'^(?P<poll_id>\d+)/results/$', 'results'),
|
(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'^$', '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+)/$', '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<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``.
|
We're using two generic views here: ``object_list`` and ``object_detail``.
|
||||||
|
|
Loading…
Reference in New Issue