magic-removal: Merged to [1903]
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1904 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8f42a92465
commit
8013f76a40
1
AUTHORS
1
AUTHORS
|
@ -82,6 +82,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
phaedo <http://phaedo.cx/>
|
phaedo <http://phaedo.cx/>
|
||||||
Luke Plant <http://lukeplant.me.uk/>
|
Luke Plant <http://lukeplant.me.uk/>
|
||||||
plisk
|
plisk
|
||||||
|
Daniel Poelzleithner <http://poelzi.org/>
|
||||||
Brian Ray <http://brianray.chipy.org/>
|
Brian Ray <http://brianray.chipy.org/>
|
||||||
Oliver Rutherfurd <http://rutherfurd.net/>
|
Oliver Rutherfurd <http://rutherfurd.net/>
|
||||||
David Schein
|
David Schein
|
||||||
|
|
|
@ -122,7 +122,7 @@ textarea { vertical-align:top !important; }
|
||||||
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
|
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
|
||||||
|
|
||||||
/* FORM BUTTONS */
|
/* FORM BUTTONS */
|
||||||
input[type=submit], input[type=button], .submit-row input { border:1px solid #ccc; background:white url(../img/admin/nav-bg.gif) bottom repeat-x; }
|
input[type=submit], input[type=button], .submit-row input { border:1px solid #ccc; background:white url(../img/admin/nav-bg.gif) bottom repeat-x; color:black; }
|
||||||
input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
|
input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
|
||||||
input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; padding:3px; background:white url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
|
input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; padding:3px; background:white url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
|
||||||
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
|
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
|
||||||
|
@ -339,4 +339,4 @@ p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
|
||||||
.vURLField { width:30em; }
|
.vURLField { width:30em; }
|
||||||
.vLargeTextField, .vXMLLargeTextField { width:48em; }
|
.vLargeTextField, .vXMLLargeTextField { width:48em; }
|
||||||
.flatpages-flatpage #id_content { height:40.2em; }
|
.flatpages-flatpage #id_content { height:40.2em; }
|
||||||
.module table .vPositiveSmallIntegerField { width:2.2em; }
|
.module table .vPositiveSmallIntegerField { width:2.2em; }
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{% include "widget/foreign" %}
|
|
@ -811,7 +811,7 @@ class TimeField(TextField):
|
||||||
if (len(part_list) == 2):
|
if (len(part_list) == 2):
|
||||||
t = t.replace(microsecond=int(part_list[1]))
|
t = t.replace(microsecond=int(part_list[1]))
|
||||||
return t
|
return t
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError, AttributeError):
|
||||||
return None
|
return None
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
|
|
|
@ -945,6 +945,12 @@ def createcachetable(tablename):
|
||||||
connection.commit()
|
connection.commit()
|
||||||
createcachetable.args = "[tablename]"
|
createcachetable.args = "[tablename]"
|
||||||
|
|
||||||
|
def run_shell():
|
||||||
|
"Runs a Python interactive interpreter"
|
||||||
|
import code
|
||||||
|
code.interact()
|
||||||
|
run_shell.args = ''
|
||||||
|
|
||||||
# Utilities for command-line script
|
# Utilities for command-line script
|
||||||
|
|
||||||
DEFAULT_ACTION_MAPPING = {
|
DEFAULT_ACTION_MAPPING = {
|
||||||
|
@ -958,6 +964,7 @@ DEFAULT_ACTION_MAPPING = {
|
||||||
'install': install,
|
'install': install,
|
||||||
'installperms': installperms,
|
'installperms': installperms,
|
||||||
'runserver': runserver,
|
'runserver': runserver,
|
||||||
|
'shell': run_shell,
|
||||||
'sql': get_sql_create,
|
'sql': get_sql_create,
|
||||||
'sqlall': get_sql_all,
|
'sqlall': get_sql_all,
|
||||||
'sqlclear': get_sql_delete,
|
'sqlclear': get_sql_delete,
|
||||||
|
@ -1038,7 +1045,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
action_mapping[action](username, email, password)
|
action_mapping[action](username, email, password)
|
||||||
elif action in ('init', 'init-minimal', 'validate'):
|
elif action in ('init', 'init-minimal', 'shell', 'validate'):
|
||||||
action_mapping[action]()
|
action_mapping[action]()
|
||||||
elif action == 'inspectdb':
|
elif action == 'inspectdb':
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -136,7 +136,7 @@ def wordwrap(value, arg):
|
||||||
Argument: number of words to wrap the text at.
|
Argument: number of words to wrap the text at.
|
||||||
"""
|
"""
|
||||||
from django.utils.text import wrap
|
from django.utils.text import wrap
|
||||||
return wrap(value, int(arg))
|
return wrap(str(value), int(arg))
|
||||||
|
|
||||||
def ljust(value, arg):
|
def ljust(value, arg):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -170,8 +170,8 @@ Change a password with ``set_password()``::
|
||||||
Passwords
|
Passwords
|
||||||
---------
|
---------
|
||||||
|
|
||||||
**This only applies to the Django development version.** Previous versions,
|
Previous versions, such as Django 0.90, used simple MD5 hashes without password
|
||||||
such as Django 0.90, used simple MD5 hashes without password salts.
|
salts.
|
||||||
|
|
||||||
The ``password`` field of a ``User`` object is a string in this format::
|
The ``password`` field of a ``User`` object is a string in this format::
|
||||||
|
|
||||||
|
@ -314,9 +314,8 @@ Here's the same thing, using Python 2.4's decorator syntax::
|
||||||
Note that ``user_passes_test`` does not automatically check that the ``User``
|
Note that ``user_passes_test`` does not automatically check that the ``User``
|
||||||
is not anonymous.
|
is not anonymous.
|
||||||
|
|
||||||
**New in the Django development version**: ``user_passes_test()`` takes an
|
``user_passes_test()`` takes an optional ``login_url`` argument, which lets you
|
||||||
optional ``login_url`` argument, which lets you specify the URL for your login
|
specify the URL for your login page (``/accounts/login/`` by default).
|
||||||
page (``/accounts/login/`` by default).
|
|
||||||
|
|
||||||
Example in Python 2.3 syntax::
|
Example in Python 2.3 syntax::
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,7 @@ Examples:
|
||||||
locmem:/// A more sophisticated local memory cache;
|
locmem:/// A more sophisticated local memory cache;
|
||||||
this is multi-process- and thread-safe.
|
this is multi-process- and thread-safe.
|
||||||
|
|
||||||
dummy:/// **New in Django development version.**
|
dummy:/// Doesn't actually cache; just implements the
|
||||||
Doesn't actually cache; just implements the
|
|
||||||
cache backend interface and doesn't do
|
cache backend interface and doesn't do
|
||||||
anything. This is an easy way to turn off
|
anything. This is an easy way to turn off
|
||||||
caching for a test environment.
|
caching for a test environment.
|
||||||
|
|
|
@ -222,8 +222,6 @@ If you pass an invalid keyword argument, the function will raise ``TypeError``.
|
||||||
OR lookups
|
OR lookups
|
||||||
----------
|
----------
|
||||||
|
|
||||||
**New in Django development version.**
|
|
||||||
|
|
||||||
By default, keyword argument queries are "AND"ed together. If you have more complex query
|
By default, keyword argument queries are "AND"ed together. If you have more complex query
|
||||||
requirements (for example, you need to include an ``OR`` statement in your query), you need
|
requirements (for example, you need to include an ``OR`` statement in your query), you need
|
||||||
to use ``Q`` objects.
|
to use ``Q`` objects.
|
||||||
|
|
|
@ -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
|
||||||
|
@ -54,9 +69,8 @@ createsuperuser
|
||||||
Creates a superuser account interactively. It asks you for a username, e-mail
|
Creates a superuser account interactively. It asks you for a username, e-mail
|
||||||
address and password.
|
address and password.
|
||||||
|
|
||||||
**New in Django development version:** You can specify
|
You can specify ``username email password`` on the command line, for convenient
|
||||||
``username email password`` on the command line, for convenient use in shell
|
use in shell scripts. Example::
|
||||||
scripts. Example::
|
|
||||||
|
|
||||||
django-admin.py createsuperuser john john@example.com mypassword
|
django-admin.py createsuperuser john john@example.com mypassword
|
||||||
|
|
||||||
|
@ -211,6 +225,9 @@ Explicitly specifies the settings module to use. The settings module should be
|
||||||
in Python path syntax, e.g. "myproject.settings". If this isn't provided,
|
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
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@ -222,6 +239,9 @@ Adds the given filesystem path to the Python `import search path`_. If this
|
||||||
isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment
|
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
|
||||||
|
|
|
@ -118,8 +118,6 @@ receiving a separate e-mail::
|
||||||
Preventing header injection
|
Preventing header injection
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
**New in Django development version.**
|
|
||||||
|
|
||||||
`Header injection`_ is a security exploit in which an attacker inserts extra
|
`Header injection`_ is a security exploit in which an attacker inserts extra
|
||||||
e-mail headers to control the "To:" and "From:" in e-mail messages that your
|
e-mail headers to control the "To:" and "From:" in e-mail messages that your
|
||||||
scripts generate.
|
scripts generate.
|
||||||
|
|
|
@ -129,9 +129,9 @@ arguments:
|
||||||
``extra_context`` A dictionary of extra data to put into the
|
``extra_context`` A dictionary of extra data to put into the
|
||||||
template's context.
|
template's context.
|
||||||
|
|
||||||
``processors`` **New in Django development version.** A tuple of
|
``processors`` A tuple of processors to apply to the
|
||||||
processors to apply to the ``DjangoContext`` of
|
``DjangoContext`` of this view's template. See the
|
||||||
this view's template. See the `DjangoContext docs`_
|
`DjangoContext docs`_
|
||||||
======================= ==================================================
|
======================= ==================================================
|
||||||
|
|
||||||
.. _database API docs: http://www.djangoproject.com/documentation/db_api/
|
.. _database API docs: http://www.djangoproject.com/documentation/db_api/
|
||||||
|
@ -150,8 +150,7 @@ The date-based generic functions are:
|
||||||
``num_latest`` The number of items to display on the page.
|
``num_latest`` The number of items to display on the page.
|
||||||
Defaults to 15.
|
Defaults to 15.
|
||||||
|
|
||||||
``allow_empty`` **New in Django development version.**
|
``allow_empty`` If ``False`` and there are no objects to display,
|
||||||
If ``False`` and there are no objects to display,
|
|
||||||
the view will raise a 404 instead of displaying
|
the view will raise a 404 instead of displaying
|
||||||
an empty index page. ``False`` is default.
|
an empty index page. ``False`` is default.
|
||||||
======================= =================================================
|
======================= =================================================
|
||||||
|
|
|
@ -151,9 +151,8 @@ subclass of dictionary. Exceptions are outlined here:
|
||||||
other dictionary functions that have side effects, can only be called on
|
other dictionary functions that have side effects, can only be called on
|
||||||
a mutable ``QueryDict`` (one that was created via ``copy()``).
|
a mutable ``QueryDict`` (one that was created via ``copy()``).
|
||||||
|
|
||||||
* ``__contains__(key)`` -- **New in Django development version.** Returns
|
* ``__contains__(key)`` -- Returns ``True`` if the given key is set. This
|
||||||
``True`` if the given key is set. This lets you do, e.g.,
|
lets you do, e.g., ``if "foo" in request.GET``.
|
||||||
``if "foo" in request.GET``.
|
|
||||||
|
|
||||||
* ``get(key, default)`` -- Uses the same logic as ``__getitem__()`` above,
|
* ``get(key, default)`` -- Uses the same logic as ``__getitem__()`` above,
|
||||||
with a hook for returning a default value if the key doesn't exist.
|
with a hook for returning a default value if the key doesn't exist.
|
||||||
|
@ -361,8 +360,6 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
|
||||||
an HTTP status code 302.
|
an HTTP status code 302.
|
||||||
|
|
||||||
``HttpResponsePermanentRedirect``
|
``HttpResponsePermanentRedirect``
|
||||||
**New in Django development version.***
|
|
||||||
|
|
||||||
Like ``HttpResponseRedirect``, but it returns a permanent redirect (HTTP
|
Like ``HttpResponseRedirect``, but it returns a permanent redirect (HTTP
|
||||||
status code 301) instead of a "found" redirect (status code 302).
|
status code 301) instead of a "found" redirect (status code 302).
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ it and write to it.
|
||||||
It implements the following standard dictionary methods:
|
It implements the following standard dictionary methods:
|
||||||
|
|
||||||
* ``__contains__(key)``
|
* ``__contains__(key)``
|
||||||
**New in Django development version.** Example: ``'fav_color' in request.session``
|
Example: ``'fav_color' in request.session``
|
||||||
|
|
||||||
* ``__getitem__(key)``
|
* ``__getitem__(key)``
|
||||||
Example: ``fav_color = request.session['fav_color']``
|
Example: ``fav_color = request.session['fav_color']``
|
||||||
|
@ -177,10 +177,9 @@ deleted::
|
||||||
# request.session['foo'] instead of request.session.
|
# request.session['foo'] instead of request.session.
|
||||||
request.session['foo']['bar'] = 'baz'
|
request.session['foo']['bar'] = 'baz'
|
||||||
|
|
||||||
**Only available in Django development version.** To change this default
|
To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting
|
||||||
behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting to ``True``. If
|
to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save
|
||||||
``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save the session to the
|
the session to the database on every single request.
|
||||||
database on every single request.
|
|
||||||
|
|
||||||
Note that the session cookie is only sent when a session has been created or
|
Note that the session cookie is only sent when a session has been created or
|
||||||
modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie
|
modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie
|
||||||
|
@ -213,8 +212,7 @@ domain cookie.
|
||||||
SESSION_COOKIE_NAME
|
SESSION_COOKIE_NAME
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Default: ``'sessionid'`` (**Django development version.** Previous default was
|
Default: ``'sessionid'``
|
||||||
``'hotclub'``, which was deemed too pornish.)
|
|
||||||
|
|
||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
|
|
||||||
|
@ -223,8 +221,6 @@ SESSION_SAVE_EVERY_REQUEST
|
||||||
|
|
||||||
Default: ``False``
|
Default: ``False``
|
||||||
|
|
||||||
**Only available in Django development version.**
|
|
||||||
|
|
||||||
Whether to save the session data on every request. If this is ``False``
|
Whether to save the session data on every request. If this is ``False``
|
||||||
(default), then the session data will only be saved if it has been modified --
|
(default), then the session data will only be saved if it has been modified --
|
||||||
that is, if any of its dictionary values have been assigned or deleted.
|
that is, if any of its dictionary values have been assigned or deleted.
|
||||||
|
|
|
@ -525,8 +525,7 @@ domain cookie. See the `session docs`_.
|
||||||
SESSION_COOKIE_NAME
|
SESSION_COOKIE_NAME
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Default: ``'sessionid'`` (**Django development version.** Previous default was
|
Default: ``'sessionid'``
|
||||||
``'hotclub'``, which was deemed too pornish.)
|
|
||||||
|
|
||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
See the `session docs`_.
|
See the `session docs`_.
|
||||||
|
@ -556,8 +555,6 @@ Default::
|
||||||
"django.core.context_processors.debug",
|
"django.core.context_processors.debug",
|
||||||
"django.core.context_processors.i18n")
|
"django.core.context_processors.i18n")
|
||||||
|
|
||||||
**Only available in Django development version.**
|
|
||||||
|
|
||||||
A tuple of callables that are used to populate the context in ``DjangoContext``.
|
A tuple of callables that are used to populate the context in ``DjangoContext``.
|
||||||
These callables take a request object as their argument and return a dictionary
|
These callables take a request object as their argument and return a dictionary
|
||||||
of items to be merged into the context.
|
of items to be merged into the context.
|
||||||
|
@ -567,8 +564,6 @@ TEMPLATE_DEBUG
|
||||||
|
|
||||||
Default: ``False``
|
Default: ``False``
|
||||||
|
|
||||||
**Only available in Django development version.**
|
|
||||||
|
|
||||||
A boolean that turns on/off template debug mode. If this is ``True``, the fancy
|
A boolean that turns on/off template debug mode. If this is ``True``, the fancy
|
||||||
error page will display a detailed report for any ``TemplateSyntaxError``. This
|
error page will display a detailed report for any ``TemplateSyntaxError``. This
|
||||||
report contains the relevant snippet of the template, with the appropriate line
|
report contains the relevant snippet of the template, with the appropriate line
|
||||||
|
|
|
@ -278,8 +278,8 @@ In the above, the ``load`` tag loads the ``comments`` tag library, which then
|
||||||
makes the ``comment_form`` tag available for use. Consult the documentation
|
makes the ``comment_form`` tag available for use. Consult the documentation
|
||||||
area in your admin to find the list of custom libraries in your installation.
|
area in your admin to find the list of custom libraries in your installation.
|
||||||
|
|
||||||
**New in Django development version:** The ``{% load %}`` tag can take multiple
|
The ``{% load %}`` tag can take multiple library names, separated by spaces.
|
||||||
library names, separated by spaces. Example::
|
Example::
|
||||||
|
|
||||||
{% load comments i18n %}
|
{% load comments i18n %}
|
||||||
|
|
||||||
|
@ -500,8 +500,6 @@ Just like ``ifequal``, except it tests that the two arguments are not equal.
|
||||||
include
|
include
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
**Only available in Django development version.**
|
|
||||||
|
|
||||||
Loads a template and renders it with the current context. This is a way of
|
Loads a template and renders it with the current context. This is a way of
|
||||||
"including" other templates within a template.
|
"including" other templates within a template.
|
||||||
|
|
||||||
|
|
|
@ -282,11 +282,6 @@ optional, third positional argument, ``processors``. In this example, the
|
||||||
'foo': 'bar',
|
'foo': 'bar',
|
||||||
}, [ip_address_processor])
|
}, [ip_address_processor])
|
||||||
|
|
||||||
Note: The concept of template-context processors is new in the Django
|
|
||||||
development version. In Django 0.90, ``DjangoContext`` automatically populates
|
|
||||||
the context with all of the values explained below, but it's not possible to
|
|
||||||
add and remove processors.
|
|
||||||
|
|
||||||
Here's what each of the default processors does:
|
Here's what each of the default processors does:
|
||||||
|
|
||||||
.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
|
.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
|
||||||
|
@ -540,8 +535,6 @@ filters are registered. So, near the top of your module, put the following::
|
||||||
Writing custom template filters
|
Writing custom template filters
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
**This section applies to the Django development version.**
|
|
||||||
|
|
||||||
Custom filters are just Python functions that take one or two arguments:
|
Custom filters are just Python functions that take one or two arguments:
|
||||||
|
|
||||||
* The value of the variable (input) -- not necessarily a string.
|
* The value of the variable (input) -- not necessarily a string.
|
||||||
|
@ -601,8 +594,6 @@ will use the function's name as the filter name.
|
||||||
Writing custom template tags
|
Writing custom template tags
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
**This section applies to the Django development version.**
|
|
||||||
|
|
||||||
Tags are more complex than filters, because tags can do anything.
|
Tags are more complex than filters, because tags can do anything.
|
||||||
|
|
||||||
A quick overview
|
A quick overview
|
||||||
|
|
|
@ -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``.
|
||||||
|
|
|
@ -51,9 +51,6 @@ algorithm the system follows to determine which Python code to execute:
|
||||||
Example
|
Example
|
||||||
=======
|
=======
|
||||||
|
|
||||||
**This syntax is new in the Django development version.** See "Named groups"
|
|
||||||
below if you're using Django 0.90.
|
|
||||||
|
|
||||||
Here's a sample URLconf::
|
Here's a sample URLconf::
|
||||||
|
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
@ -110,9 +107,6 @@ to a view. In more advanced usage, it's possible to use *named*
|
||||||
regular-expression groups to capture URL bits and pass them as *keyword*
|
regular-expression groups to capture URL bits and pass them as *keyword*
|
||||||
arguments to a view.
|
arguments to a view.
|
||||||
|
|
||||||
(Note that support for non-named regex groups is a new feature in the Django
|
|
||||||
development version. Django 0.90 requires named groups.)
|
|
||||||
|
|
||||||
In Python regular expressions, the syntax for named regular-expression groups
|
In Python regular expressions, the syntax for named regular-expression groups
|
||||||
is ``(?P<name>pattern)``, where ``name`` is the name of the group and
|
is ``(?P<name>pattern)``, where ``name`` is the name of the group and
|
||||||
``pattern`` is some pattern to match.
|
``pattern`` is some pattern to match.
|
||||||
|
|
Loading…
Reference in New Issue