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.
|
||||
|
||||
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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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``.
|
||||
|
|
Loading…
Reference in New Issue