1
0
mirror of https://github.com/django/django.git synced 2025-10-23 21:59:11 +00:00

Massive reorganization of the docs. See the new docs online at http://docs.djangoproject.com/.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss
2008-08-23 22:25:40 +00:00
parent b3688e8194
commit 97cb07c3a1
188 changed files with 19913 additions and 17059 deletions

122
docs/howto/apache-auth.txt Normal file
View File

@@ -0,0 +1,122 @@
.. _howto-apache-auth:
=========================================================
Authenticating against Django's user database from Apache
=========================================================
Since keeping multiple authentication databases in sync is a common problem when
dealing with Apache, you can configuring Apache to authenticate against Django's
:ref:`authentication system <topics-auth>` directly. For example, you
could:
* Serve static/media files directly from Apache only to authenticated users.
* Authenticate access to a Subversion_ repository against Django users with
a certain permission.
* Allow certain users to connect to a WebDAV share created with mod_dav_.
.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
Configuring Apache
==================
To check against Django's authorization database from a Apache configuration
file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along
with the standard ``Auth*`` and ``Require`` directives:
.. code-block:: apache
<Location /example/>
AuthType Basic
AuthName "example.com"
Require valid-user
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonAuthenHandler django.contrib.auth.handlers.modpython
</Location>
.. admonition:: Using the authentication handler with Apache 2.2
If you're using Apache 2.2, you'll need to take a couple extra steps.
You'll need to ensure that ``mod_auth_basic`` and ``mod_authz_user``
are loaded. These might be compiled statically into Apache, or you might
need to use ``LoadModule`` to load them dynamically (as shown in the
example at the bottom of this note).
You'll also need to insert configuration directives that prevent Apache
from trying to use other authentication modules, as well as specifying
the ``AuthUserFile`` directive and pointing it to ``/dev/null``. Depending
on which other authentication modules you have loaded, you might need one
or more of the following directives::
.. code-block:: apache
AuthBasicAuthoritative Off
AuthDefaultAuthoritative Off
AuthzLDAPAuthoritative Off
AuthzDBMAuthoritative Off
AuthzDefaultAuthoritative Off
AuthzGroupFileAuthoritative Off
AuthzOwnerAuthoritative Off
AuthzUserAuthoritative Off
A complete configuration, with differences between Apache 2.0 and
Apache 2.2 marked in bold, would look something like:
.. parsed-literal::
**LoadModule auth_basic_module modules/mod_auth_basic.so**
**LoadModule authz_user_module modules/mod_authz_user.so**
...
<Location /example/>
AuthType Basic
AuthName "example.com"
**AuthUserFile /dev/null**
**AuthBasicAuthoritative Off**
Require valid-user
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonAuthenHandler django.contrib.auth.handlers.modpython
</Location>
By default, the authentication handler will limit access to the ``/example/``
location to users marked as staff members. You can use a set of
``PythonOption`` directives to modify this behavior:
================================ =========================================
``PythonOption`` Explanation
================================ =========================================
``DjangoRequireStaffStatus`` If set to ``on`` only "staff" users (i.e.
those with the ``is_staff`` flag set)
will be allowed.
Defaults to ``on``.
``DjangoRequireSuperuserStatus`` If set to ``on`` only superusers (i.e.
those with the ``is_superuser`` flag set)
will be allowed.
Defaults to ``off``.
``DjangoPermissionName`` The name of a permission to require for
access. See :ref:`custom permissions
<custom-permissions>` for more
information.
By default no specific permission will be
required.
================================ =========================================
Note that sometimes ``SetEnv`` doesn't play well in this mod_python
configuration, for reasons unknown. If you're having problems getting
mod_python to recognize your ``DJANGO_SETTINGS_MODULE``, you can set it using
``PythonOption`` instead of ``SetEnv``. Therefore, these two Apache directives
are equivalent::
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption DJANGO_SETTINGS_MODULE mysite.settings

View File

@@ -0,0 +1,78 @@
.. _howto-custom-file-storage:
Writing a custom storage system
===============================
If you need to provide custom file storage -- a common example is storing files
on some remote system -- you can do so by defining a custom storage class.
You'll need to follow these steps:
#. Your custom storage system must be a subclass of
``django.core.files.storage.Storage``::
from django.core.files.storage import Storage
class MyStorage(Storage):
...
#. Django must be able to instantiate your storage system without any arguments.
This means that any settings should be taken from ``django.conf.settings``::
from django.conf import settings
from django.core.files.storage import Storage
class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...
#. Your storage class must implement the ``_open()`` and ``_save()`` methods,
along with any other methods appropriate to your storage class. See below for
more on these methods.
In addition, if your class provides local file storage, it must override
the ``path()`` method.
Your custom storage system may override any of the storage methods explained in
:ref:`ref-files-storage`. However, it's usually better to use the hooks
specifically designed for custom storage objects. These are:
``_open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~
**Required**.
Called by ``Storage.open()``, this is the actual mechanism the storage class
uses to open the file. This must return a ``File`` object, though in most cases,
you'll want to return some subclass here that implements logic specific to the
backend storage system.
``_save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~
Called by ``Storage.save()``. The ``name`` will already have gone through
``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
``File`` object itself. No return value is expected.
``get_valid_name(name)``
------------------------
Returns a filename suitable for use with the underlying storage system. The
``name`` argument passed to this method is the original filename sent to the
server, after having any path information removed. Override this to customize
how non-standard characters are converted to safe filenames.
The code provided on ``Storage`` retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.
``get_available_name(name)``
----------------------------
Returns a filename that is available in the storage mechanism, possibly taking
the provided filename into account. The ``name`` argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the ``get_valid_name()`` method described above.
The code provided on ``Storage`` simply appends underscores to the filename
until it finds one that's available in the destination directory.

View File

@@ -0,0 +1,33 @@
.. _howto-custom-management-commands:
Writing custom django-admin commands
====================================
**New in Django development version**
Applications can register their own actions with ``manage.py``. For example,
you might want to add a ``manage.py`` action for a Django app that you're
distributing.
To do this, just add a ``management/commands`` directory to your application.
Each Python module in that directory will be auto-discovered and registered as
a command that can be executed as an action when you run ``manage.py``::
blog/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
explode.py
views.py
In this example, the ``explode`` command will be made available to any project
that includes the ``blog`` application in ``settings.INSTALLED_APPS``.
The ``explode.py`` module has only one requirement -- it must define a class
called ``Command`` that extends ``django.core.management.base.BaseCommand``.
For more details on how to define your own commands, look at the code for the
existing ``django-admin.py`` commands, in ``/django/core/management/commands``.

View File

@@ -0,0 +1,658 @@
.. _howto-custom-model-fields:
===========================
Writing custom model fields
===========================
**New in Django development version**
Introduction
============
The :ref:`model reference <topics-db-models>` documentation explains how to use
Django's standard field classes -- :class:`~django.db.models.CharField`,
:class:`~django.db.models.DateField`, etc. For many purposes, those classes are
all you'll need. Sometimes, though, the Django version won't meet your precise
requirements, or you'll want to use a field that is entirely different from
those shipped with Django.
Django's built-in field types don't cover every possible database column type --
only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure
column types, such as geographic polygons or even user-created types such as
`PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses.
.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html
Alternatively, you may have a complex Python object that can somehow be
serialized to fit into a standard database column type. This is another case
where a ``Field`` subclass will help you use your object with your models.
Our example object
------------------
Creating custom fields requires a bit of attention to detail. To make things
easier to follow, we'll use a consistent example throughout this document.
Suppose you have a Python object representing the deal of cards in a hand of
Bridge_. (Don't worry, you don't know how to play Bridge to follow this
example. You only need to know that 52 cards are dealt out equally to four
players, who are traditionally called *north*, *east*, *south* and *west*.)
Our class looks something like this::
class Hand(object):
def __init__(self, north, east, south, west):
# Input parameters are lists of cards ('Ah', '9s', etc)
self.north = north
self.east = east
self.south = south
self.west = west
# ... (other possibly useful methods omitted) ...
.. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge
This is just an ordinary Python class, with nothing Django-specific about it.
We'd like to be able to do things like this in our models (we assume the
``hand`` attribute on the model is an instance of ``Hand``)::
example = MyModel.objects.get(pk=1)
print example.hand.north
new_hand = Hand(north, east, south, west)
example.hand = new_hand
example.save()
We assign to and retrieve from the ``hand`` attribute in our model just like
any other Python class. The trick is to tell Django how to handle saving and
loading such an object.
In order to use the ``Hand`` class in our models, we **do not** have to change
this class at all. This is ideal, because it means you can easily write
model support for existing classes where you cannot change the source code.
.. note::
You might only be wanting to take advantage of custom database column
types and deal with the data as standard Python types in your models;
strings, or floats, for example. This case is similar to our ``Hand``
example and we'll note any differences as we go along.
Background theory
=================
Database storage
----------------
The simplest way to think of a model field is that it provides a way to take a
normal Python object -- string, boolean, ``datetime``, or something more
complex like ``Hand`` -- and convert it to and from a format that is useful
when dealing with the database (and serialization, but, as we'll see later,
that falls out fairly naturally once you have the database side under control).
Fields in a model must somehow be converted to fit into an existing database
column type. Different databases provide different sets of valid column types,
but the rule is still the same: those are the only types you have to work
with. Anything you want to store in the database must fit into one of
those types.
Normally, you're either writing a Django field to match a particular database
column type, or there's a fairly straightforward way to convert your data to,
say, a string.
For our ``Hand`` example, we could convert the card data to a string of 104
characters by concatenating all the cards together in a pre-determined order --
say, all the *north* cards first, then the *east*, *south* and *west* cards. So
``Hand`` objects can be saved to text or character columns in the database.
What does a field class do?
---------------------------
All of Django's fields (and when we say *fields* in this document, we always
mean model fields and not :ref:`form fields <ref-forms-fields>`) are subclasses
of :class:`django.db.models.Field`. Most of the information that Django records
about a field is common to all fields -- name, help text, validator lists,
uniqueness and so forth. Storing all that information is handled by ``Field``.
We'll get into the precise details of what ``Field`` can do later on; for now,
suffice it to say that everything descends from ``Field`` and then customizes
key pieces of the class behavior.
It's important to realize that a Django field class is not what is stored in
your model attributes. The model attributes contain normal Python objects. The
field classes you define in a model are actually stored in the ``Meta`` class
when the model class is created (the precise details of how this is done are
unimportant here). This is because the field classes aren't necessary when
you're just creating and modifying attributes. Instead, they provide the
machinery for converting between the attribute value and what is stored in the
database or sent to the :ref:`serializer <topics-serialization>`.
Keep this in mind when creating your own custom fields. The Django ``Field``
subclass you write provides the machinery for converting between your Python
instances and the database/serializer values in various ways (there are
differences between storing a value and using a value for lookups, for
example). If this sounds a bit tricky, don't worry -- it will become clearer in
the examples below. Just remember that you will often end up creating two
classes when you want a custom field:
* The first class is the Python object that your users will manipulate.
They will assign it to the model attribute, they will read from it for
displaying purposes, things like that. This is the ``Hand`` class in our
example.
* The second class is the ``Field`` subclass. This is the class that knows
how to convert your first class back and forth between its permanent
storage form and the Python form.
Writing a field subclass
========================
When planning your :class:`~django.db.models.Field` subclass, first give some
thought to which existing :class:`~django.db.models.Field` class your new field
is most similar to. Can you subclass an existing Django field and save yourself
some work? If not, you should subclass the :class:`~django.db.models.Field`
class, from which everything is descended.
Initializing your new field is a matter of separating out any arguments that are
specific to your case from the common arguments and passing the latter to the
:meth:`~django.db.models.Field.__init__` method of
:class:`~django.db.models.Field` (or your parent class).
In our example, we'll call our field ``HandField``. (It's a good idea to call
your :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's
easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't
behave like any existing field, so we'll subclass directly from
:class:`~django.db.models.Field`::
from django.db import models
class HandField(models.Field):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)
Our ``HandField`` accept most of the standard field options (see the list
below), but we ensure it has a fixed length, since it only needs to hold 52
card values plus their suits; 104 characters in total.
.. note::
Many of Django's model fields accept options that they don't do anything
with. For example, you can pass both
:attr:`~django.db.models.Field.editable` and
:attr:`~django.db.models.Field.auto_now` to a
:class:`django.db.models.DateField` and it will simply ignore the
:attr:`~django.db.models.Field.editable` parameter
(:attr:`~django.db.models.Field.auto_now` being set implies
``editable=False``). No error is raised in this case.
This behavior simplifies the field classes, because they don't need to
check for options that aren't necessary. They just pass all the options to
the parent class and then don't use them later on. It's up to you whether
you want your fields to be more strict about the options they select, or
to use the simpler, more permissive behavior of the current fields.
The :meth:`~django.db.models.Field.__init__` method takes the following
parameters:
* :attr:`~django.db.models.Field.verbose_name`
* :attr:`~django.db.models.Field.name`
* :attr:`~django.db.models.Field.primary_key`
* :attr:`~django.db.models.Field.max_length`
* :attr:`~django.db.models.Field.unique`
* :attr:`~django.db.models.Field.blank`
* :attr:`~django.db.models.Field.null`
* :attr:`~django.db.models.Field.db_index`
* :attr:`~django.db.models.Field.core`
* :attr:`~django.db.models.Field.rel`: Used for related fields (like
:attr:`~django.db.models.Field.ForeignKey`). For advanced use only.
* :attr:`~django.db.models.Field.default`
* :attr:`~django.db.models.Field.editable`
* :attr:`~django.db.models.Field.serialize`: If
:attr:`~django.db.models.Field.False`, the field will not be serialized
when the model is passed to Django's :ref:`serializers
<topics-serialization>`. Defaults to
:attr:`~django.db.models.Field.True`.
* :attr:`~django.db.models.Field.prepopulate_from`
* :attr:`~django.db.models.Field.unique_for_date`
* :attr:`~django.db.models.Field.unique_for_month`
* :attr:`~django.db.models.Field.unique_for_year`
* :attr:`~django.db.models.Field.validator_list`
* :attr:`~django.db.models.Field.choices`
* :attr:`~django.db.models.Field.help_text`
* :attr:`~django.db.models.Field.db_column`
* :attr:`~django.db.models.Field.db_tablespace`: Currently only used with
the Oracle backend and only for index creation. You can usually ignore
this option.
All of the options without an explanation in the above list have the same
meaning they do for normal Django fields. See the :ref:`field documentation
<ref-models-fields>` for examples and details.
The ``SubfieldBase`` metaclass
------------------------------
As we indicated in the introduction_, field subclasses are often needed for
two reasons: either to take advantage of a custom database column type, or to
handle complex Python types. Obviously, a combination of the two is also
possible. If you're only working with custom database column types and your
model fields appear in Python as standard Python types direct from the
database backend, you don't need to worry about this section.
If you're handling custom Python types, such as our ``Hand`` class, we need to
make sure that when Django initializes an instance of our model and assigns a
database value to our custom field attribute, we convert that value into the
appropriate Python object. The details of how this happens internally are a
little complex, but the code you need to write in your ``Field`` class is
simple: make sure your field subclass uses a special metaclass:
.. class:: django.db.models.SubfieldBase
For example::
class HandField(models.Field):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
# ...
This ensures that the :meth:`to_python` method, documented below, will always be
called when the attribute is initialized.
Useful methods
--------------
Once you've created your :class:`~django.db.models.Field` subclass and set up up
the ``__metaclass__``, you might consider overriding a few standard methods,
depending on your field's behavior. The list of methods below is in
approximately decreasing order of importance, so start from the top.
Custom database types
~~~~~~~~~~~~~~~~~~~~~
.. method:: db_type(self)
Returns the database column data type for the :class:`~django.db.models.Field`,
taking into account the current :setting:`DATABASE_ENGINE` setting.
Say you've created a PostgreSQL custom type called ``mytype``. You can use this
field with Django by subclassing ``Field`` and implementing the :meth:`db_type`
method, like so::
from django.db import models
class MytypeField(models.Field):
def db_type(self):
return 'mytype'
Once you have ``MytypeField``, you can use it in any model, just like any other
``Field`` type::
class Person(models.Model):
name = models.CharField(max_length=80)
gender = models.CharField(max_length=1)
something_else = MytypeField()
If you aim to build a database-agnostic application, you should account for
differences in database column types. For example, the date/time column type
in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
``datetime``. The simplest way to handle this in a ``db_type()`` method is to
import the Django settings module and check the :setting:`DATABASE_ENGINE` setting.
For example::
class MyDateField(models.Field):
def db_type(self):
from django.conf import settings
if settings.DATABASE_ENGINE == 'mysql':
return 'datetime'
else:
return 'timestamp'
The :meth:`db_type` method is only called by Django when the framework
constructs the ``CREATE TABLE`` statements for your application -- that is, when
you first create your tables. It's not called at any other time, so it can
afford to execute slightly complex code, such as the :setting:`DATABASE_ENGINE`
check in the above example.
Some database column types accept parameters, such as ``CHAR(25)``, where the
parameter ``25`` represents the maximum column length. In cases like these,
it's more flexible if the parameter is specified in the model rather than being
hard-coded in the ``db_type()`` method. For example, it wouldn't make much
sense to have a ``CharMaxlength25Field``, shown here::
# This is a silly example of hard-coded parameters.
class CharMaxlength25Field(models.Field):
def db_type(self):
return 'char(25)'
# In the model:
class MyModel(models.Model):
# ...
my_field = CharMaxlength25Field()
The better way of doing this would be to make the parameter specifiable at run
time -- i.e., when the class is instantiated. To do that, just implement
:meth:`django.db.models.Field.__init__`, like so::
# This is a much more flexible example.
class BetterCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(BetterCharField, self).__init__(*args, **kwargs)
def db_type(self):
return 'char(%s)' % self.max_length
# In the model:
class MyModel(models.Model):
# ...
my_field = BetterCharField(25)
Finally, if your column requires truly complex SQL setup, return ``None`` from
:meth:`db_type`. This will cause Django's SQL creation code to skip over this
field. You are then responsible for creating the column in the right table in
some other way, of course, but this gives you a way to tell Django to get out of
the way.
Converting database values to Python objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: to_python(self, value)
Converts a value as returned by your database (or a serializer) to a Python
object.
The default implementation simply returns ``value``, for the common case in
which the database backend already returns data in the correct format (as a
Python string, for example).
If your custom :class:`~django.db.models.Field` class deals with data structures
that are more complex than strings, dates, integers or floats, then you'll need
to override this method. As a general rule, the method should deal gracefully
with any of the following arguments:
* An instance of the correct type (e.g., ``Hand`` in our ongoing example).
* A string (e.g., from a deserializer).
* Whatever the database returns for the column type you're using.
In our ``HandField`` class, we're storing the data as a VARCHAR field in the
database, so we need to be able to process strings and ``Hand`` instances in
:meth:`to_python`::
import re
class HandField(models.Field):
# ...
def to_python(self, value):
if isinstance(value, Hand):
return value
# The string case.
p1 = re.compile('.{26}')
p2 = re.compile('..')
args = [p2.findall(x) for x in p1.findall(value)]
return Hand(*args)
Notice that we always return a ``Hand`` instance from this method. That's the
Python object type we want to store in the model's attribute.
**Remember:** If your custom field needs the :meth:`to_python` method to be
called when it is created, you should be using `The SubfieldBase metaclass`_
mentioned earlier. Otherwise :meth:`to_python` won't be called automatically.
Converting Python objects to database values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: get_db_prep_value(self, value)
This is the reverse of :meth:`to_python` when working with the database backends
(as opposed to serialization). The ``value`` parameter is the current value of
the model's attribute (a field has no reference to its containing model, so it
cannot retrieve the value itself), and the method should return data in a format
that can be used as a parameter in a query for the database backend.
For example::
class HandField(models.Field):
# ...
def get_db_prep_value(self, value):
return ''.join([''.join(l) for l in (value.north,
value.east, value.south, value.west)])
.. method:: get_db_prep_save(self, value)
Same as the above, but called when the Field value must be *saved* to the
database. As the default implementation just calls ``get_db_prep_value``, you
shouldn't need to implement this method unless your custom field need a special
conversion when being saved that is not the same as the used for normal query
parameters (which is implemented by ``get_db_prep_value``).
Preprocessing values before saving
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: pre_save(self, model_instance, add)
This method is called just prior to :meth:`get_db_prep_save` and should return
the value of the appropriate attribute from ``model_instance`` for this field.
The attribute name is in ``self.attname`` (this is set up by
:class:`~django.db.models.Field`). If the model is being saved to the database
for the first time, the ``add`` parameter will be ``True``, otherwise it will be
``False``.
You only need to override this method if you want to preprocess the value
somehow, just before saving. For example, Django's
`:class:`~django.db.models.DateTimeField` uses this method to set the attribute
correctly in the case of :attr:`~django.db.models.Field.auto_now` or
:attr:`~django.db.models.Field.auto_now_add`.
If you do override this method, you must return the value of the attribute at
the end. You should also update the model's attribute if you make any changes
to the value so that code holding references to the model will always see the
correct value.
Preparing values for use in database lookups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: get_db_prep_lookup(self, lookup_type, value)
Prepares the ``value`` for passing to the database when used in a lookup (a
``WHERE`` constraint in SQL). The ``lookup_type`` will be one of the valid
Django filter lookups: ``exact``, ``iexact``, ``contains``, ``icontains``,
``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``,
``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``,
``isnull``, ``search``, ``regex``, and ``iregex``.
Your method must be prepared to handle all of these ``lookup_type`` values and
should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a
list when you were expecting an object, for example) or a ``TypeError`` if
your field does not support that type of lookup. For many fields, you can get
by with handling the lookup types that need special handling for your field
and pass the rest of the :meth:`get_db_prep_lookup` method of the parent class.
If you needed to implement ``get_db_prep_save()``, you will usually need to
implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be
called by the default implementation, to manage ``exact``, ``gt``, ``gte``,
``lt``, ``lte``, ``in`` and ``range`` lookups.
You may also want to implement this method to limit the lookup types that could
be used with your custom field type.
Note that, for ``range`` and ``in`` lookups, ``get_db_prep_lookup`` will receive
a list of objects (presumably of the right type) and will need to convert them
to a list of things of the right type for passing to the database. Most of the
time, you can reuse ``get_db_prep_value()``, or at least factor out some common
pieces.
For example, the following code implements ``get_db_prep_lookup`` to limit the
accepted lookup types to ``exact`` and ``in``::
class HandField(models.Field):
# ...
def get_db_prep_lookup(self, lookup_type, value):
# We only handle 'exact' and 'in'. All others are errors.
if lookup_type == 'exact':
return self.get_db_prep_value(value)
elif lookup_type == 'in':
return [self.get_db_prep_value(v) for v in value]
else:
raise TypeError('Lookup type %r not supported.' % lookup_type)
Specifying the form field for a model field
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: formfield(self, form_class=forms.CharField, **kwargs)
Returns the default form field to use when this field is displayed in a model.
This method is called by the :class:`~django.forms.ModelForm` helper.
All of the ``kwargs`` dictionary is passed directly to the form field's
:meth:`~django.forms.Field__init__` method. Normally, all you need to do is
set up a good default for the ``form_class`` argument and then delegate further
handling to the parent class. This might require you to write a custom form
field (and even a form widget). See the :ref:`forms documentation
<topics-forms-index>` for information about this, and take a look at the code in
:mod:`django.contrib.localflavor` for some examples of custom widgets.
Continuing our ongoing example, we can write the :meth:`formfield` method as::
class HandField(models.Field):
# ...
def formfield(self, **kwargs):
# This is a fairly standard way to set up some defaults
# while letting the caller override them.
defaults = {'form_class': MyFormField}
defaults.update(kwargs)
return super(HandField, self).formfield(**defaults)
This assumes we're imported a ``MyFormField`` field class (which has its own
default widget). This document doesn't cover the details of writing custom form
fields.
.. _helper functions: ../forms/#generating-forms-for-models
.. _forms documentation: ../forms/
Emulating built-in field types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: get_internal_type(self)
Returns a string giving the name of the :class:`~django.db.models.Field`
subclass we are emulating at the database level. This is used to determine the
type of database column for simple cases.
If you have created a :meth:`db_type` method, you don't need to worry about
:meth:`get_internal_type` -- it won't be used much. Sometimes, though, your
database storage is similar in type to some other field, so you can use that
other field's logic to create the right column.
For example::
class HandField(models.Field):
# ...
def get_internal_type(self):
return 'CharField'
No matter which database backend we are using, this will mean that ``syncdb``
and other SQL commands create the right column type for storing a string.
If :meth:`get_internal_type` returns a string that is not known to Django for
the database backend you are using -- that is, it doesn't appear in
``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be
used by the serializer, but the default :meth:`db_type` method will return
``None``. See the documentation of :meth:`db_type` for reasons why this might be
useful. Putting a descriptive string in as the type of the field for the
serializer is a useful idea if you're ever going to be using the serializer
output in some other place, outside of Django.
Converting field data for serialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: flatten_data(self, follow, obj=None)
.. admonition:: Subject to change
Although implementing this method is necessary to allow field
serialization, the API might change in the future.
Returns a dictionary, mapping the field's attribute name to a flattened string
version of the data. This method has some internal uses that aren't of interest
to use here (mostly having to do with forms). For our purposes, it's sufficient
to return a one item dictionary that maps the attribute name to a string.
This method is used by the serializers to convert the field into a string for
output. You can ignore the input parameters for serialization purposes, although
calling :meth:`Field._get_val_from_obj(obj)
<django.db.models.Field._get_val_from_obj>` is the best way to get the value to
serialize.
For example, since our ``HandField`` uses strings for its data storage anyway,
we can reuse some existing conversion code::
class HandField(models.Field):
# ...
def flatten_data(self, follow, obj=None):
value = self._get_val_from_obj(obj)
return {self.attname: self.get_db_prep_value(value)}
Some general advice
--------------------
Writing a custom field can be a tricky process, particularly if you're doing
complex conversions between your Python types and your database and
serialization formats. Here are a couple of tips to make things go more
smoothly:
1. Look at the existing Django fields (in
:file:`django/db/models/fields/__init__.py`) for inspiration. Try to find
a field that's similar to what you want and extend it a little bit,
instead of creating an entirely new field from scratch.
2. Put a :meth:`__str__` or :meth:`__unicode__` method on the class you're
wrapping up as a field. There are a lot of places where the default
behavior of the field code is to call
:func:`~django.utils.encoding.force_unicode` on the value. (In our
examples in this document, ``value`` would be a ``Hand`` instance, not a
``HandField``). So if your :meth:`__unicode__` method automatically
converts to the string form of your Python object, you can save yourself
a lot of work.
Writing a ``FileField`` subclass
=================================
In addition to the above methods, fields that deal with files have a few other
special requirements which must be taken into account. The majority of the
mechanics provided by ``FileField``, such as controlling database storage and
retrieval, can remain unchanged, leaving subclasses to deal with the challenge
of supporting a particular type of file.
Django provides a ``File`` class, which is used as a proxy to the file's
contents and operations. This can be subclassed to customize how the file is
accessed, and what methods are available. It lives at
``django.db.models.fields.files``, and its default behavior is explained in the
:ref:`file documentation <ref-files-file>`.
Once a subclass of ``File`` is created, the new ``FileField`` subclass must be
told to use it. To do so, simply assign the new ``File`` subclass to the special
``attr_class`` attribute of the ``FileField`` subclass.
A few suggestions
------------------
In addition to the above details, there are a few guidelines which can greatly
improve the efficiency and readability of the field's code.
1. The source for Django's own ``ImageField`` (in
``django/db/models/fields/files.py``) is a great example of how to
subclass ``FileField`` to support a particular type of file, as it
incorporates all of the techniques described above.
2. Cache file attributes wherever possible. Since files may be stored in
remote storage systems, retrieving them may cost extra time, or even
money, that isn't always necessary. Once a file is retrieved to obtain
some data about its content, cache as much of that data as possible to
reduce the number of times the file must be retrieved on subsequent
calls for that information.

View File

@@ -0,0 +1,877 @@
.. _howto-custom-template-tags:
================================
Custom template tags and filters
================================
Introduction
============
Django's template system comes a wide variety of :ref:`built-in tags and filters
<ref-templates-builtins>` designed to address the presentation logic needs of
your application. Nevertheless, you may find yourself needing functionality that
is not covered by the core set of template primitives. You can extend the
template engine by defining custom tags and filters using Python, and then make
them available to your templates using the ``{% load %}`` tag.
Code layout
-----------
Custom template tags and filters must live inside a Django app. If they relate
to an existing app it makes sense to bundle them there; otherwise, you should
create a new app to hold them.
The app should contain a ``templatetags`` directory, at the same level as
``models.py``, ``views.py``, etc. If this doesn't already exist, create it -
don't forget the ``__init__.py`` file to ensure the directory is treated as a
Python package.
Your custom tags and filters will live in a module inside the ``templatetags``
directory. The name of the module file is the name you'll use to load the tags
later, so be careful to pick a name that won't clash with custom tags and
filters in another app.
For example, if your custom tags/filters are in a file called
``poll_extras.py``, your app layout might look like this::
polls/
models.py
templatetags/
__init__.py
poll_extras.py
views.py
And in your template you would use the following:
.. code-block:: html+django
{% load poll_extras %}
The app that contains the custom tags must be in :setting:`INSTALLED_APPS` in
order for the ``{% load %}`` tag to work. This is a security feature: It allows
you to host Python code for many template libraries on a single host machine
without enabling access to all of them for every Django installation.
There's no limit on how many modules you put in the ``templatetags`` package.
Just keep in mind that a ``{% load %}`` statement will load tags/filters for
the given Python module name, not the name of the app.
To be a valid tag library, the module must contain a module-level variable
named ``register`` that is a ``template.Library`` instance, in which all the
tags and filters are registered. So, near the top of your module, put the
following::
from django import template
register = template.Library()
.. admonition:: Behind the scenes
For a ton of examples, read the source code for Django's default filters
and tags. They're in ``django/template/defaultfilters.py`` and
``django/template/defaulttags.py``, respectively.
Writing custom template filters
-------------------------------
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 argument -- this can have a default value, or be left
out altogether.
For example, in the filter ``{{ var|foo:"bar" }}``, the filter ``foo`` would be
passed the variable ``var`` and the argument ``"bar"``.
Filter functions should always return something. They shouldn't raise
exceptions. They should fail silently. In case of error, they should return
either the original input or an empty string -- whichever makes more sense.
Here's an example filter definition::
def cut(value, arg):
"Removes all values of arg from the given string"
return value.replace(arg, '')
And here's an example of how that filter would be used:
.. code-block:: html+django
{{ somevariable|cut:"0" }}
Most filters don't take arguments. In this case, just leave the argument out of
your function. Example::
def lower(value): # Only one argument.
"Converts a string into all lowercase"
return value.lower()
Template filters that expect strings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you're writing a template filter that only expects a string as the first
argument, you should use the decorator ``stringfilter``. This will
convert an object to its string value before being passed to your function::
from django.template.defaultfilters import stringfilter
@stringfilter
def lower(value):
return value.lower()
This way, you'll be able to pass, say, an integer to this filter, and it
won't cause an ``AttributeError`` (because integers don't have ``lower()``
methods).
Registering custom filters
~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you've written your filter definition, you need to register it with
your ``Library`` instance, to make it available to Django's template language::
register.filter('cut', cut)
register.filter('lower', lower)
The ``Library.filter()`` method takes two arguments:
1. The name of the filter -- a string.
2. The compilation function -- a Python function (not the name of the
function as a string).
If you're using Python 2.4 or above, you can use ``register.filter()`` as a
decorator instead::
@register.filter(name='cut')
@stringfilter
def cut(value, arg):
return value.replace(arg, '')
@register.filter
@stringfilter
def lower(value):
return value.lower()
If you leave off the ``name`` argument, as in the second example above, Django
will use the function's name as the filter name.
Filters and auto-escaping
~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
When writing a custom filter, give some thought to how the filter will interact
with Django's auto-escaping behavior. Note that three types of strings can be
passed around inside the template code:
* **Raw strings** are the native Python ``str`` or ``unicode`` types. On
output, they're escaped if auto-escaping is in effect and presented
unchanged, otherwise.
* **Safe strings** are strings that have been marked safe from further
escaping at output time. Any necessary escaping has already been done.
They're commonly used for output that contains raw HTML that is intended
to be interpreted as-is on the client side.
Internally, these strings are of type ``SafeString`` or ``SafeUnicode``.
They share a common base class of ``SafeData``, so you can test
for them using code like::
if isinstance(value, SafeData):
# Do something with the "safe" string.
* **Strings marked as "needing escaping"** are *always* escaped on
output, regardless of whether they are in an ``autoescape`` block or not.
These strings are only escaped once, however, even if auto-escaping
applies.
Internally, these strings are of type ``EscapeString`` or
``EscapeUnicode``. Generally you don't have to worry about these; they
exist for the implementation of the ``escape`` filter.
Template filter code falls into one of two situations:
1. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``,
``'``, ``"`` or ``&``) into the result that were not already present. In
this case, you can let Django take care of all the auto-escaping
handling for you. All you need to do is put the ``is_safe`` attribute on
your filter function and set it to ``True``, like so::
@register.filter
def myfilter(value):
return value
myfilter.is_safe = True
This attribute tells Django that if a "safe" string is passed into your
filter, the result will still be "safe" and if a non-safe string is
passed in, Django will automatically escape it, if necessary.
You can think of this as meaning "this filter is safe -- it doesn't
introduce any possibility of unsafe HTML."
The reason ``is_safe`` is necessary is because there are plenty of
normal string operations that will turn a ``SafeData`` object back into
a normal ``str`` or ``unicode`` object and, rather than try to catch
them all, which would be very difficult, Django repairs the damage after
the filter has completed.
For example, suppose you have a filter that adds the string ``xx`` to the
end of any input. Since this introduces no dangerous HTML characters to
the result (aside from any that were already present), you should mark
your filter with ``is_safe``::
@register.filter
def add_xx(value):
return '%sxx' % value
add_xx.is_safe = True
When this filter is used in a template where auto-escaping is enabled,
Django will escape the output whenever the input is not already marked as
"safe".
By default, ``is_safe`` defaults to ``False``, and you can omit it from
any filters where it isn't required.
Be careful when deciding if your filter really does leave safe strings
as safe. If you're *removing* characters, you might inadvertently leave
unbalanced HTML tags or entities in the result. For example, removing a
``>`` from the input might turn ``<a>`` into ``<a``, which would need to
be escaped on output to avoid causing problems. Similarly, removing a
semicolon (``;``) can turn ``&amp;`` into ``&amp``, which is no longer a
valid entity and thus needs further escaping. Most cases won't be nearly
this tricky, but keep an eye out for any problems like that when
reviewing your code.
2. Alternatively, your filter code can manually take care of any necessary
escaping. This is necessary when you're introducing new HTML markup into
the result. You want to mark the output as safe from further
escaping so that your HTML markup isn't escaped further, so you'll need
to handle the input yourself.
To mark the output as a safe string, use
:func:`django.utils.safestring.mark_safe`.
Be careful, though. You need to do more than just mark the output as
safe. You need to ensure it really *is* safe, and what you do depends on
whether auto-escaping is in effect. The idea is to write filters than
can operate in templates where auto-escaping is either on or off in
order to make things easier for your template authors.
In order for your filter to know the current auto-escaping state, set
the ``needs_autoescape`` attribute to ``True`` on your function. (If you
don't specify this attribute, it defaults to ``False``). This attribute
tells Django that your filter function wants to be passed an extra
keyword argument, called ``autoescape``, that is ``True`` if
auto-escaping is in effect and ``False`` otherwise.
For example, let's write a filter that emphasizes the first character of
a string::
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
def initial_letter_filter(text, autoescape=None):
first, other = text[0], text[1:]
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
result = '<strong>%s</strong>%s' % (esc(first), esc(other))
return mark_safe(result)
initial_letter_filter.needs_autoescape = True
The ``needs_autoescape`` attribute on the filter function and the
``autoescape`` keyword argument mean that our function will know whether
automatic escaping is in effect when the filter is called. We use
``autoescape`` to decide whether the input data needs to be passed
through ``django.utils.html.conditional_escape`` or not. (In the latter
case, we just use the identity function as the "escape" function.) The
``conditional_escape()`` function is like ``escape()`` except it only
escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
instance is passed to ``conditional_escape()``, the data is returned
unchanged.
Finally, in the above example, we remember to mark the result as safe
so that our HTML is inserted directly into the template without further
escaping.
There's no need to worry about the ``is_safe`` attribute in this case
(although including it wouldn't hurt anything). Whenever you manually
handle the auto-escaping issues and return a safe string, the
``is_safe`` attribute won't change anything either way.
Writing custom template tags
----------------------------
Tags are more complex than filters, because tags can do anything.
A quick overview
~~~~~~~~~~~~~~~~
Above, this document explained that the template system works in a two-step
process: compiling and rendering. To define a custom template tag, you specify
how the compilation works and how the rendering works.
When Django compiles a template, it splits the raw template text into
''nodes''. Each node is an instance of ``django.template.Node`` and has
a ``render()`` method. A compiled template is, simply, a list of ``Node``
objects. When you call ``render()`` on a compiled template object, the template
calls ``render()`` on each ``Node`` in its node list, with the given context.
The results are all concatenated together to form the output of the template.
Thus, to define a custom template tag, you specify how the raw template tag is
converted into a ``Node`` (the compilation function), and what the node's
``render()`` method does.
Writing the compilation function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For each template tag the template parser encounters, it calls a Python
function with the tag contents and the parser object itself. This function is
responsible for returning a ``Node`` instance based on the contents of the tag.
For example, let's write a template tag, ``{% current_time %}``, that displays
the current date/time, formatted according to a parameter given in the tag, in
`strftime syntax`_. It's a good idea to decide the tag syntax before anything
else. In our case, let's say the tag should be used like this:
.. code-block:: html+django
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
.. _`strftime syntax`: http://www.python.org/doc/current/lib/module-time.html#l2h-1941
The parser for this function should grab the parameter and create a ``Node``
object::
from django import template
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return CurrentTimeNode(format_string[1:-1])
Notes:
* ``parser`` is the template parser object. We don't need it in this
example.
* ``token.contents`` is a string of the raw contents of the tag. In our
example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``.
* The ``token.split_contents()`` method separates the arguments on spaces
while keeping quoted strings together. The more straightforward
``token.contents.split()`` wouldn't be as robust, as it would naively
split on *all* spaces, including those within quoted strings. It's a good
idea to always use ``token.split_contents()``.
* This function is responsible for raising
``django.template.TemplateSyntaxError``, with helpful messages, for
any syntax error.
* The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable.
Don't hard-code the tag's name in your error messages, because that
couples the tag's name to your function. ``token.contents.split()[0]``
will ''always'' be the name of your tag -- even when the tag has no
arguments.
* The function returns a ``CurrentTimeNode`` with everything the node needs
to know about this tag. In this case, it just passes the argument --
``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
template tag are removed in ``format_string[1:-1]``.
* The parsing is very low-level. The Django developers have experimented
with writing small frameworks on top of this parsing system, using
techniques such as EBNF grammars, but those experiments made the template
engine too slow. It's low-level because that's fastest.
Writing the renderer
~~~~~~~~~~~~~~~~~~~~
The second step in writing custom tags is to define a ``Node`` subclass that
has a ``render()`` method.
Continuing the above example, we need to define ``CurrentTimeNode``::
from django import template
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
return datetime.datetime.now().strftime(self.format_string)
Notes:
* ``__init__()`` gets the ``format_string`` from ``do_current_time()``.
Always pass any options/parameters/arguments to a ``Node`` via its
``__init__()``.
* The ``render()`` method is where the work actually happens.
* ``render()`` should never raise ``TemplateSyntaxError`` or any other
exception. It should fail silently, just as template filters should.
Ultimately, this decoupling of compilation and rendering results in an
efficient template system, because a template can render multiple contexts
without having to be parsed multiple times.
Auto-escaping considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
The output from template tags is **not** automatically run through the
auto-escaping filters. However, there are still a couple of things you should
keep in mind when writing a template tag.
If the ``render()`` function of your template stores the result in a context
variable (rather than returning the result in a string), it should take care
to call ``mark_safe()`` if appropriate. When the variable is ultimately
rendered, it will be affected by the auto-escape setting in effect at the
time, so content that should be safe from further escaping needs to be marked
as such.
Also, if your template tag creates a new context for performing some
sub-rendering, set the auto-escape attribute to the current context's value.
The ``__init__`` method for the ``Context`` class takes a parameter called
``autoescape`` that you can use for this purpose. For example::
def render(self, context):
# ...
new_context = Context({'var': obj}, autoescape=context.autoescape)
# ... Do something with new_context ...
This is not a very common situation, but it's useful if you're rendering a
template yourself. For example::
def render(self, context):
t = template.loader.get_template('small_fragment.html')
return t.render(Context({'var': obj}, autoescape=context.autoescape))
If we had neglected to pass in the current ``context.autoescape`` value to our
new ``Context`` in this example, the results would have *always* been
automatically escaped, which may not be the desired behavior if the template
tag is used inside a ``{% autoescape off %}`` block.
Registering the tag
~~~~~~~~~~~~~~~~~~~
Finally, register the tag with your module's ``Library`` instance, as explained
in "Writing custom template filters" above. Example::
register.tag('current_time', do_current_time)
The ``tag()`` method takes two arguments:
1. The name of the template tag -- a string. If this is left out, the
name of the compilation function will be used.
2. The compilation function -- a Python function (not the name of the
function as a string).
As with filter registration, it is also possible to use this as a decorator, in
Python 2.4 and above::
@register.tag(name="current_time")
def do_current_time(parser, token):
# ...
@register.tag
def shout(parser, token):
# ...
If you leave off the ``name`` argument, as in the second example above, Django
will use the function's name as the tag name.
Passing template variables to the tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Although you can pass any number of arguments to a template tag using
``token.split_contents()``, the arguments are all unpacked as
string literals. A little more work is required in order to pass dynamic
content (a template variable) to a template tag as an argument.
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a ``DateTimeField`` from an
object and have the template tag format that date-time:
.. code-block:: html+django
<p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>
Initially, ``token.split_contents()`` will return three values:
1. The tag name ``format_time``.
2. The string "blog_entry.date_updated" (without the surrounding quotes).
3. The formatting string "%Y-%m-%d %I:%M %p". The return value from
``split_contents()`` will include the leading and trailing quotes for
string literals like this.
Now your tag should begin to look like this::
from django import template
def do_format_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, date_to_be_formatted, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return FormatTimeNode(date_to_be_formatted, format_string[1:-1])
You also have to change the renderer to retrieve the actual contents of the
``date_updated`` property of the ``blog_entry`` object. This can be
accomplished by using the ``resolve_variable()`` function in
``django.template``. You pass ``resolve_variable()`` the variable name and the
current context, available in the ``render`` method::
from django import template
from django.template import resolve_variable
import datetime
class FormatTimeNode(template.Node):
def __init__(self, date_to_be_formatted, format_string):
self.date_to_be_formatted = date_to_be_formatted
self.format_string = format_string
def render(self, context):
try:
actual_date = resolve_variable(self.date_to_be_formatted, context)
return actual_date.strftime(self.format_string)
except template.VariableDoesNotExist:
return ''
``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then
format it accordingly.
.. admonition:: New in development version:
Variable resolution has changed in the development version of Django.
``template.resolve_variable()`` is still available, but has been deprecated
in favor of a new ``template.Variable`` class. Using this class will usually
be more efficient than calling ``template.resolve_variable``
To use the ``Variable`` class, simply instantiate it with the name of the
variable to be resolved, and then call ``variable.resolve(context)``. So,
in the development version, the above example would be more correctly
written as:
.. parsed-literal::
class FormatTimeNode(template.Node):
def __init__(self, date_to_be_formatted, format_string):
self.date_to_be_formatted = **Variable(date_to_be_formatted)**
self.format_string = format_string
def render(self, context):
try:
actual_date = **self.date_to_be_formatted.resolve(context)**
return actual_date.strftime(self.format_string)
except template.VariableDoesNotExist:
return ''
Changes are highlighted in bold.
Variable resolution will throw a ``VariableDoesNotExist`` exception if it cannot
resolve the string passed to it in the current context of the page.
Shortcut for simple tags
~~~~~~~~~~~~~~~~~~~~~~~~
Many template tags take a number of arguments -- strings or a template variables
-- and return a string after doing some processing based solely on
the input argument and some external information. For example, the
``current_time`` tag we wrote above is of this variety: we give it a format
string, it returns the time as a string.
To ease the creation of the types of tags, Django provides a helper function,
``simple_tag``. This function, which is a method of
``django.template.Library``, takes a function that accepts any number of
arguments, wraps it in a ``render`` function and the other necessary bits
mentioned above and registers it with the template system.
Our earlier ``current_time`` function could thus be written like this::
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
register.simple_tag(current_time)
In Python 2.4, the decorator syntax also works::
@register.simple_tag
def current_time(format_string):
...
A couple of things to note about the ``simple_tag`` helper function:
* Checking for the required number of arguments, etc., has already been
done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away,
so we just receive a plain string.
* If the argument was a template variable, our function is passed the
current value of the variable, not the variable itself.
When your template tag does not need access to the current context, writing a
function to work with the input values and using the ``simple_tag`` helper is
the easiest way to create a new tag.
Inclusion tags
~~~~~~~~~~~~~~
Another common type of template tag is the type that displays some data by
rendering *another* template. For example, Django's admin interface uses custom
template tags to display the buttons along the bottom of the "add/change" form
pages. Those buttons always look the same, but the link targets change depending
on the object being edited -- so they're a perfect case for using a small
template that is filled with details from the current object. (In the admin's
case, this is the ``submit_row`` tag.)
These sorts of tags are called "inclusion tags".
Writing inclusion tags is probably best demonstrated by example. Let's write a
tag that outputs a list of choices for a given ``Poll`` object, such as was
created in the :ref:`tutorials <creating-models>`. We'll use the tag like this:
.. code-block:: html+django
{% show_results poll %}
...and the output will be something like this:
.. code-block:: html
<ul>
<li>First choice</li>
<li>Second choice</li>
<li>Third choice</li>
</ul>
First, define the function that takes the argument and produces a dictionary of
data for the result. The important point here is we only need to return a
dictionary, not anything more complex. This will be used as a template context
for the template fragment. Example::
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}
Next, create the template used to render the tag's output. This template is a
fixed feature of the tag: the tag writer specifies it, not the template
designer. Following our example, the template is very simple:
.. code-block:: html+django
<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>
Now, create and register the inclusion tag by calling the ``inclusion_tag()``
method on a ``Library`` object. Following our example, if the above template is
in a file called ``results.html`` in a directory that's searched by the template
loader, we'd register the tag like this::
# Here, register is a django.template.Library instance, as before
register.inclusion_tag('results.html')(show_results)
As always, Python 2.4 decorator syntax works as well, so we could have
written::
@register.inclusion_tag('results.html')
def show_results(poll):
...
...when first creating the function.
Sometimes, your inclusion tags might require a large number of arguments,
making it a pain for template authors to pass in all the arguments and remember
their order. To solve this, Django provides a ``takes_context`` option for
inclusion tags. If you specify ``takes_context`` in creating a template tag,
the tag will have no required arguments, and the underlying Python function
will have one argument -- the template context as of when the tag was called.
For example, say you're writing an inclusion tag that will always be used in a
context that contains ``home_link`` and ``home_title`` variables that point
back to the main page. Here's what the Python function would look like::
# The first argument *must* be called "context" here.
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}
# Register the custom tag as an inclusion tag with takes_context=True.
register.inclusion_tag('link.html', takes_context=True)(jump_link)
(Note that the first parameter to the function *must* be called ``context``.)
In that ``register.inclusion_tag()`` line, we specified ``takes_context=True``
and the name of the template. Here's what the template ``link.html`` might look
like:
.. code-block:: html+django
Jump directly to <a href="{{ link }}">{{ title }}</a>.
Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so::
.. code-block:: html+django
{% jump_link %}
Note that when you're using ``takes_context=True``, there's no need to pass
arguments to the template tag. It automatically gets access to the context.
The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
the tag is passed the context object, as in this example. That's the only
difference between this case and the previous ``inclusion_tag`` example.
Setting a variable in the context
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The above example simply output a value. Generally, it's more flexible if your
template tags set template variables instead of outputting values. That way,
template authors can reuse the values that your template tags create.
To set a variable in the context, just use dictionary assignment on the context
object in the ``render()`` method. Here's an updated version of
``CurrentTimeNode`` that sets a template variable ``current_time`` instead of
outputting it::
class CurrentTimeNode2(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
context['current_time'] = datetime.datetime.now().strftime(self.format_string)
return ''
Note that ``render()`` returns the empty string. ``render()`` should always
return string output. If all the template tag does is set a variable,
``render()`` should return the empty string.
Here's how you'd use this new version of the tag:
.. code-block:: html+django
{% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>
But, there's a problem with ``CurrentTimeNode2``: The variable name
``current_time`` is hard-coded. This means you'll need to make sure your
template doesn't use ``{{ current_time }}`` anywhere else, because the
``{% current_time %}`` will blindly overwrite that variable's value. A cleaner
solution is to make the template tag specify the name of the output variable,
like so:
.. code-block:: html+django
{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>
To do that, you'll need to refactor both the compilation function and ``Node``
class, like so::
class CurrentTimeNode3(template.Node):
def __init__(self, format_string, var_name):
self.format_string = format_string
self.var_name = var_name
def render(self, context):
context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
return ''
import re
def do_current_time(parser, token):
# This version uses a regular expression to parse tag contents.
try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
m = re.search(r'(.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
format_string, var_name = m.groups()
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return CurrentTimeNode3(format_string[1:-1], var_name)
The difference here is that ``do_current_time()`` grabs the format string and
the variable name, passing both to ``CurrentTimeNode3``.
Parsing until another block tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Template tags can work in tandem. For instance, the standard ``{% comment %}``
tag hides everything until ``{% endcomment %}``. To create a template tag such
as this, use ``parser.parse()`` in your compilation function.
Here's how the standard ``{% comment %}`` tag is implemented::
def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()
class CommentNode(template.Node):
def render(self, context):
return ''
``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It
returns an instance of ``django.template.NodeList``, which is a list of
all ``Node`` objects that the parser encountered ''before'' it encountered
any of the tags named in the tuple.
In ``"nodelist = parser.parse(('endcomment',))"`` in the above example,
``nodelist`` is a list of all nodes between the ``{% comment %}`` and
``{% endcomment %}``, not counting ``{% comment %}`` and ``{% endcomment %}``
themselves.
After ``parser.parse()`` is called, the parser hasn't yet "consumed" the
``{% endcomment %}`` tag, so the code needs to explicitly call
``parser.delete_first_token()``.
``CommentNode.render()`` simply returns an empty string. Anything between
``{% comment %}`` and ``{% endcomment %}`` is ignored.
Parsing until another block tag, and saving contents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the previous example, ``do_comment()`` discarded everything between
``{% comment %}`` and ``{% endcomment %}``. Instead of doing that, it's
possible to do something with the code between block tags.
For example, here's a custom template tag, ``{% upper %}``, that capitalizes
everything between itself and ``{% endupper %}``.
Usage:
.. code-block:: html+django
{% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}
As in the previous example, we'll use ``parser.parse()``. But this time, we
pass the resulting ``nodelist`` to the ``Node``::
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()
The only new concept here is the ``self.nodelist.render(context)`` in
``UpperNode.render()``.
For more examples of complex rendering, see the source code for ``{% if %}``,
``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
``django/template/defaulttags.py``.

View File

@@ -0,0 +1,383 @@
.. _howto-deployment-fastcgi:
===========================================
How to use Django with FastCGI, SCGI or AJP
===========================================
.. highlight:: bash
Although the current preferred setup for running Django is :ref:`Apache with
mod_python <howto-deployment-modpython>`, many people use shared hosting, on
which protocols such as FastCGI, SCGI or AJP are the only viable options. In
some setups, these protocols also allow better security -- and, possibly, better
performance -- than mod_python_.
.. admonition:: Note
This document primarily focuses on FastCGI. Other protocols, such as SCGI
and AJP, are also supported, through the ``flup`` Python package. See the
Protocols_ section below for specifics about SCGI and AJP.
Essentially, FastCGI is an efficient way of letting an external application
serve pages to a Web server. The Web server delegates the incoming Web requests
(via a socket) to FastCGI, which executes the code and passes the response back
to the Web server, which, in turn, passes it back to the client's Web browser.
Like mod_python, FastCGI allows code to stay in memory, allowing requests to be
served with no startup time. Unlike mod_python_ (or `mod_perl`_), a FastCGI
process doesn't run inside the Web server process, but in a separate,
persistent process.
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
.. admonition:: Why run code in a separate process?
The traditional ``mod_*`` arrangements in Apache embed various scripting
languages (most notably PHP, Python and Perl) inside the process space of
your Web server. Although this lowers startup time -- because code doesn't
have to be read off disk for every request -- it comes at the cost of
memory use. For mod_python, for example, every Apache process gets its own
Python interpreter, which uses up a considerable amount of RAM.
Due to the nature of FastCGI, it's even possible to have processes that run
under a different user account than the Web server process. That's a nice
security benefit on shared systems, because it means you can secure your
code from other users.
Prerequisite: flup
==================
Before you can start using FastCGI with Django, you'll need to install flup_, a
Python library for dealing with FastCGI. Version 0.5 or newer should work fine.
.. _flup: http://www.saddi.com/software/flup/
Starting your FastCGI server
============================
FastCGI operates on a client-server model, and in most cases you'll be starting
the FastCGI process on your own. Your Web server (be it Apache, lighttpd, or
otherwise) only contacts your Django-FastCGI process when the server needs a
dynamic page to be loaded. Because the daemon is already running with the code
in memory, it's able to serve the response very quickly.
.. admonition:: Note
If you're on a shared hosting system, you'll probably be forced to use
Web server-managed FastCGI processes. See the section below on running
Django with Web server-managed processes for more information.
A Web server can connect to a FastCGI server in one of two ways: It can use
either a Unix domain socket (a "named pipe" on Win32 systems), or it can use a
TCP socket. What you choose is a manner of preference; a TCP socket is usually
easier due to permissions issues.
To start your server, first change into the directory of your project (wherever
your :ref:`manage.py <ref-django-admin>` is), and then run the
:djadmin:`runfcgi` command::
./manage.py runfcgi [options]
If you specify ``help`` as the only option after :djadmin:`runfcgi`, it'll
display a list of all the available options.
You'll need to specify either a ``socket``, a ``protocol`` or both ``host`` and
``port``. Then, when you set up your Web server, you'll just need to point it at
the host/port or socket you specified when starting the FastCGI server. See the
examples_, below.
Protocols
---------
Django supports all the protocols that flup_ does, namely fastcgi_, `SCGI`_ and
`AJP1.3`_ (the Apache JServ Protocol, version 1.3). Select your preferred
protocol by using the ``protocol=<protocol_name>`` option with ``./manage.py
runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi`` (the default),
``scgi`` or ``ajp``. For example::
./manage.py runfcgi protocol=scgi
.. _flup: http://www.saddi.com/software/flup/
.. _fastcgi: http://www.fastcgi.com/
.. _SCGI: http://python.ca/scgi/protocol.txt
.. _AJP1.3: http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
Examples
--------
Running a threaded server on a TCP port::
./manage.py runfcgi method=threaded host=127.0.0.1 port=3033
Running a preforked server on a Unix domain socket::
./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid
Run without daemonizing (backgrounding) the process (good for debugging)::
./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1
Stopping the FastCGI daemon
---------------------------
If you have the process running in the foreground, it's easy enough to stop it:
Simply hitting ``Ctrl-C`` will stop and quit the FastCGI server. However, when
you're dealing with background processes, you'll need to resort to the Unix
``kill`` command.
If you specify the ``pidfile`` option to :djadmin:`runfcgi`, you can kill the
running FastCGI daemon like this::
kill `cat $PIDFILE`
...where ``$PIDFILE`` is the ``pidfile`` you specified.
To easily restart your FastCGI daemon on Unix, try this small shell script::
#!/bin/bash
# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"
cd $PROJDIR
if [ -f $PIDFILE ]; then
kill `cat -- $PIDFILE`
rm -f -- $PIDFILE
fi
exec /usr/bin/env - \
PYTHONPATH="../python:.." \
./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE
Apache setup
============
To use Django with Apache and FastCGI, you'll need Apache installed and
configured, with `mod_fastcgi`_ installed and enabled. Consult the Apache
documentation for instructions.
Once you've got that set up, point Apache at your Django FastCGI instance by
editing the ``httpd.conf`` (Apache configuration) file. You'll need to do two
things:
* Use the ``FastCGIExternalServer`` directive to specify the location of
your FastCGI server.
* Use ``mod_rewrite`` to point URLs at FastCGI as appropriate.
.. _mod_fastcgi: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html
Specifying the location of the FastCGI server
---------------------------------------------
The ``FastCGIExternalServer`` directive tells Apache how to find your FastCGI
server. As the `FastCGIExternalServer docs`_ explain, you can specify either a
``socket`` or a ``host``. Here are examples of both:
.. code-block:: apache
# Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock
# Connect to FastCGI via a TCP host/port.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033
In either case, the file ``/home/user/public_html/mysite.fcgi`` doesn't
actually have to exist. It's just a URL used by the Web server internally -- a
hook for signifying which requests at a URL should be handled by FastCGI. (More
on this in the next section.)
.. _FastCGIExternalServer docs: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer
Using mod_rewrite to point URLs at FastCGI
------------------------------------------
The second step is telling Apache to use FastCGI for URLs that match a certain
pattern. To do this, use the `mod_rewrite`_ module and rewrite URLs to
``mysite.fcgi`` (or whatever you specified in the ``FastCGIExternalServer``
directive, as explained in the previous section).
In this example, we tell Apache to use FastCGI to handle any request that
doesn't represent a file on the filesystem and doesn't start with ``/media/``.
This is probably the most common case, if you're using Django's admin site:
.. code-block:: apache
<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>
.. _mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
Django will automatically use the pre-rewrite version of the URL when
constructing URLs with the ``{% url %}`` template tag (and similar methods).
lighttpd setup
==============
lighttpd_ is a lightweight Web server commonly used for serving static files. It
supports FastCGI natively and, thus, is a good choice for serving both static
and dynamic pages, if your site doesn't have any Apache-specific needs.
.. _lighttpd: http://www.lighttpd.net/
Make sure ``mod_fastcgi`` is in your modules list, somewhere after
``mod_rewrite`` and ``mod_access``, but not after ``mod_accesslog``. You'll
probably want ``mod_alias`` as well, for serving admin media.
Add the following to your lighttpd config file:
.. code-block:: lua
server.document-root = "/home/user/public_html"
fastcgi.server = (
"/mysite.fcgi" => (
"main" => (
# Use host / port instead of socket for TCP fastcgi
# "host" => "127.0.0.1",
# "port" => 3033,
"socket" => "/home/user/mysite.sock",
"check-local" => "disable",
)
),
)
alias.url = (
"/media/" => "/home/user/django/contrib/admin/media/",
)
url.rewrite-once = (
"^(/media.*)$" => "$1",
"^/favicon\.ico$" => "/media/favicon.ico",
"^(/.*)$" => "/mysite.fcgi$1",
)
Running multiple Django sites on one lighttpd
---------------------------------------------
lighttpd lets you use "conditional configuration" to allow configuration to be
customized per host. To specify multiple FastCGI sites, just add a conditional
block around your FastCGI config for each site::
# If the hostname is 'www.example1.com'...
$HTTP["host"] == "www.example1.com" {
server.document-root = "/foo/site1"
fastcgi.server = (
...
)
...
}
# If the hostname is 'www.example2.com'...
$HTTP["host"] == "www.example2.com" {
server.document-root = "/foo/site2"
fastcgi.server = (
...
)
...
}
You can also run multiple Django installations on the same site simply by
specifying multiple entries in the ``fastcgi.server`` directive. Add one
FastCGI host for each.
Running Django on a shared-hosting provider with Apache
=======================================================
Many shared-hosting providers don't allow you to run your own server daemons or
edit the ``httpd.conf`` file. In these cases, it's still possible to run Django
using Web server-spawned processes.
.. admonition:: Note
If you're using Web server-spawned processes, as explained in this section,
there's no need for you to start the FastCGI server on your own. Apache
will spawn a number of processes, scaling as it needs to.
In your Web root directory, add this to a file named ``.htaccess``:
.. code-block:: apache
AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]
Then, create a small script that tells Apache how to spawn your FastCGI
program. Create a file ``mysite.fcgi`` and place it in your Web directory, and
be sure to make it executable:
.. code-block:: python
#!/usr/bin/python
import sys, os
# Add a custom Python path.
sys.path.insert(0, "/home/user/python")
# Switch to the directory of your project. (Optional.)
# os.chdir("/home/user/myproject")
# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
Restarting the spawned server
-----------------------------
If you change any Python code on your site, you'll need to tell FastCGI the
code has changed. But there's no need to restart Apache in this case. Rather,
just reupload ``mysite.fcgi``, or edit the file, so that the timestamp on the
file will change. When Apache sees the file has been updated, it will restart
your Django application for you.
If you have access to a command shell on a Unix system, you can accomplish this
easily by using the ``touch`` command::
touch mysite.fcgi
Serving admin media files
=========================
Regardless of the server and configuration you eventually decide to use, you
will also need to give some thought to how to serve the admin media files. The
advice given in the :ref:`modpython <serving-the-admin-files>` documentation
is also applicable in the setups detailed above.
Forcing the URL prefix to a particular value
============================================
Because many of these fastcgi-based solutions require rewriting the URL at
some point inside the webserver, the path information that Django sees may not
resemble the original URL that was passed in. This is a problem if the Django
application is being served from under a particular prefix and you want your
URLs from the ``{% url %}`` tag to look like the prefix, rather than the
rewritten version, which might contain, for example, ``mysite.fcgi``.
Django makes a good attempt to work out what the real script name prefix
should be. In particular, if the webserver sets the ``SCRIPT_URL`` (specific
to Apache's mod_rewrite), or ``REDIRECT_URL`` (set by a few servers, including
Apache + mod_rewrite in some situations), Django will work out the original
prefix automatically.
In the cases where Django cannot work out the prefix correctly and where you
want the original value to be used in URLs, you can set the
``FORCE_SCRIPT_NAME`` setting in your main ``settings`` file. This sets the
script name uniformly for every URL served via that settings file. Thus you'll
need to use different settings files if you want different sets of URLs to
have different script names in this case, but that is a rare situation.
As an example of how to use it, if your Django configuration is serving all of
the URLs under ``'/'`` and you wanted to use this setting, you would set
``FORCE_SCRIPT_NAME = ''`` in your settings file.

View File

@@ -0,0 +1,33 @@
.. _howto-deployment-index:
Deploying Django
================
Django's chock-full of shortcuts to make web developer's lives easier, but all
those tools are of no use if you can't easily deploy your sites. Since Django's
inception, ease of deployment has been a major goal. There's a number of good
ways to easily deploy Django:
.. toctree::
:maxdepth: 1
modpython
fastcgi
:ref:`Deploying under mod_python <howto-deployment-modpython>` is the
recommended deployment method; start there if you're not sure which path you'd
like to go down.
.. seealso::
* `Chapter 20 of The Django Book`_ discusses deployment and especially
scaling in more detail.
* `mod_wsgi`_ is a newcomer to the Python deployment world, but it's rapidly
gaining traction. Currently there's a few hoops you have to jump through to
`use mod_wsgi with Django`_, but mod_wsgi tends to get rave reviews from
those who use it.
.. _chapter 20 of the django book: http://djangobook.com/en/1.0/chapter20/
.. _mod_wsgi: http://code.google.com/p/modwsgi/
.. _use mod_wsgi with Django: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango

View File

@@ -0,0 +1,361 @@
.. _howto-deployment-modpython:
============================================
How to use Django with Apache and mod_python
============================================
.. highlight:: apache
Apache_ with `mod_python`_ currently is the preferred setup for using Django
on a production server.
mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
Apache and loads Python code into memory when the server starts. Code stays in
memory throughout the life of an Apache process, which leads to significant
performance gains over other server arrangements.
Django requires Apache 2.x and mod_python 3.x, and you should use Apache's
`prefork MPM`_, as opposed to the `worker MPM`_.
You may also be interested in :ref:`How to use Django with FastCGI, SCGI or AJP
<howto-deployment-fastcgi>` (which also covers SCGI and AJP).
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
.. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html
.. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html
Basic configuration
===================
To configure Django with mod_python, first make sure you have Apache installed,
with the mod_python module activated.
Then edit your ``httpd.conf`` file and add the following::
<Location "/mysite/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite
PythonDebug On
</Location>
...and replace ``mysite.settings`` with the Python import path to your Django
project's settings file.
This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
Django mod_python handler." It passes the value of :ref:`DJANGO_SETTINGS_MODULE
<django-settings-module>` so mod_python knows which settings to use.
**New in Django development version:** Because mod_python does not know we are
serving this site from underneath the ``/mysite/`` prefix, this value needs to
be passed through to the mod_python handler in Django, via the ``PythonOption
django.root ...`` line. The value set on that line (the last item) should
match the string given in the ``<Location ...>`` directive. The effect of this
is that Django will automatically strip the ``/mysite`` string from the front
of any URLs before matching them against your ``URLConf`` patterns. If you
later move your site to live under ``/mysite2``, you will not have to change
anything except the ``django.root`` option in the config file.
When using ``django.root`` you should make sure that what's left, after the
prefix has been removed, begins with a slash. Your URLConf patterns that are
expecting an initial slash will then work correctly. In the above example,
since we want to send things like ``/mysite/admin/`` to ``/admin/``, we need
to remove the string ``/mysite`` from the beginning, so that is the
``django.root`` value. It would be an error to use ``/mysite/`` (with a
trailing slash) in this case.
Note that we're using the ``<Location>`` directive, not the ``<Directory>``
directive. The latter is used for pointing at places on your filesystem,
whereas ``<Location>`` points at places in the URL structure of a Web site.
``<Directory>`` would be meaningless here.
Also, if your Django project is not on the default ``PYTHONPATH`` for your
computer, you'll have to tell mod_python where your project can be found:
.. parsed-literal::
<Location "/mysite/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite
PythonDebug On
**PythonPath "['/path/to/project'] + sys.path"**
</Location>
The value you use for ``PythonPath`` should include the parent directories of
all the modules you are going to import in your application. It should also
include the parent directory of the :ref:`DJANGO_SETTINGS_MODULE
<django-settings-module>` location. This is exactly the same situation as
setting the Python path for interactive usage. Whenever you try to import
something, Python will run through all the directories in ``sys.path`` in turn,
from first to last, and try to import from each directory until one succeeds.
An example might make this clearer. Suppose you have some applications under
``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/weblog/`` and
so forth), your settings file is at ``/var/www/mysite/settings.py`` and you have
specified :ref:`DJANGO_SETTINGS_MODULE <django-settings-module>` as in the above
example. In this case, you would need to write your ``PythonPath`` directive
as::
PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"
With this path, ``import weblog`` and ``import mysite.settings`` will both
work. If you had ``import blogroll`` in your code somewhere and ``blogroll``
lived under the ``weblog/`` directory, you would *also* need to add
``/usr/local/django-apps/weblog/`` to your ``PythonPath``. Remember: the
**parent directories** of anything you import directly must be on the Python
path.
.. note::
If you're using Windows, we still recommended that you use forward
slashes in the pathnames, even though Windows normally uses the backslash
character as its native separator. Apache knows how to convert from the
forward slash format to the native format, so this approach is portable and
easier to read. (It avoids tricky problems with having to double-escape
backslashes.)
This is valid even on a Windows system::
PythonPath "['c:/path/to/project'] + sys.path"
You can also add directives such as ``PythonAutoReload Off`` for performance.
See the `mod_python documentation`_ for a full list of options.
Note that you should set ``PythonDebug Off`` on a production server. If you
leave ``PythonDebug On``, your users would see ugly (and revealing) Python
tracebacks if something goes wrong within mod_python.
Restart Apache, and any request to ``/mysite/`` or below will be served by
Django. Note that Django's URLconfs won't trim the "/mysite/" -- they get passed
the full URL.
When deploying Django sites on mod_python, you'll need to restart Apache each
time you make changes to your Python code.
Multiple Django installations on the same Apache
================================================
It's entirely possible to run multiple Django installations on the same Apache
instance. Just use ``VirtualHost`` for that, like so::
NameVirtualHost *
<VirtualHost *>
ServerName www.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</VirtualHost>
<VirtualHost *>
ServerName www2.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
</VirtualHost>
If you need to put two Django installations within the same ``VirtualHost``,
you'll need to take a special precaution to ensure mod_python's cache doesn't
mess things up. Use the ``PythonInterpreter`` directive to give different
``<Location>`` directives separate interpreters::
<VirtualHost *>
ServerName www.example.com
# ...
<Location "/something">
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonInterpreter mysite
</Location>
<Location "/otherthing">
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
PythonInterpreter othersite
</Location>
</VirtualHost>
The values of ``PythonInterpreter`` don't really matter, as long as they're
different between the two ``Location`` blocks.
Running a development server with mod_python
============================================
If you use mod_python for your development server, you can avoid the hassle of
having to restart the server each time you make code changes. Just set
``MaxRequestsPerChild 1`` in your ``httpd.conf`` file to force Apache to reload
everything for each request. But don't do that on a production server, or we'll
revoke your Django privileges.
If you're the type of programmer who debugs using scattered ``print``
statements, note that ``print`` statements have no effect in mod_python; they
don't appear in the Apache log, as one might expect. If you have the need to
print debugging information in a mod_python setup, either do this::
assert False, the_value_i_want_to_see
Or add the debugging information to the template of your page.
.. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html
.. _serving-media-files:
Serving media files
===================
Django doesn't serve media files itself; it leaves that job to whichever Web
server you choose.
We recommend using a separate Web server -- i.e., one that's not also running
Django -- for serving media. Here are some good choices:
* lighttpd_
* TUX_
* A stripped-down version of Apache_
If, however, you have no option but to serve media files on the same Apache
``VirtualHost`` as Django, here's how you can turn off mod_python for a
particular part of the site::
<Location "/media">
SetHandler None
</Location>
Just change ``Location`` to the root URL of your media files. You can also use
``<LocationMatch>`` to match a regular expression.
This example sets up Django at the site root but explicitly disables Django for
the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif`` or
``.png``::
<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</Location>
<Location "/media">
SetHandler None
</Location>
<LocationMatch "\.(jpg|gif|png)$">
SetHandler None
</LocationMatch>
.. _lighttpd: http://www.lighttpd.net/
.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
.. _Apache: http://httpd.apache.org/
.. _howto-deployment-modpython-serving-the-admin-files:
.. _serving-the-admin-files:
Serving the admin files
=======================
Note that the Django development server automagically serves admin media files,
but this is not the case when you use any other server arrangement. You're
responsible for setting up Apache, or whichever media server you're using, to
serve the admin files.
The admin files live in (:file:`django/contrib/admin/media`) of the Django
distribution.
Here are two recommended approaches:
1. Create a symbolic link to the admin media files from within your
document root. This way, all of your Django-related files -- code **and**
templates -- stay in one place, and you'll still be able to ``svn
update`` your code to get the latest admin templates, if they change.
2. Or, copy the admin media files so that they live within your Apache
document root.
Using "eggs" with mod_python
============================
If you installed Django from a Python egg_ or are using eggs in your Django
project, some extra configuration is required. Create an extra file in your
project (or somewhere else) that contains something like the following:
.. code-block:: python
import os
os.environ['PYTHON_EGG_CACHE'] = '/some/directory'
Here, ``/some/directory`` is a directory that the Apache webserver process can
write to. It will be used as the location for any unpacking of code the eggs
need to do.
Then you have to tell mod_python to import this file before doing anything
else. This is done using the PythonImport_ directive to mod_python. You need
to ensure that you have specified the ``PythonInterpreter`` directive to
mod_python as described above__ (you need to do this even if you aren't
serving multiple installations in this case). Then add the ``PythonImport``
line in the main server configuration (i.e., outside the ``Location`` or
``VirtualHost`` sections). For example::
PythonInterpreter my_django
PythonImport /path/to/my/project/file.py my_django
Note that you can use an absolute path here (or a normal dotted import path),
as described in the `mod_python manual`_. We use an absolute path in the
above example because if any Python path modifications are required to access
your project, they will not have been done at the time the ``PythonImport``
line is processed.
.. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs
.. _PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html
.. _mod_python manual: PythonImport_
__ `Multiple Django installations on the same Apache`_
Error handling
==============
When you use Apache/mod_python, errors will be caught by Django -- in other
words, they won't propagate to the Apache level and won't appear in the Apache
``error_log``.
The exception for this is if something is really wonky in your Django setup. In
that case, you'll see an "Internal Server Error" page in your browser and the
full Python traceback in your Apache ``error_log`` file. The ``error_log``
traceback is spread over multiple lines. (Yes, this is ugly and rather hard to
read, but it's how mod_python does things.)
If you get a segmentation fault
===============================
If Apache causes a segmentation fault, there are two probable causes, neither
of which has to do with Django itself.
1. It may be because your Python code is importing the "pyexpat" module,
which may conflict with the version embedded in Apache. For full
information, see `Expat Causing Apache Crash`_.
2. It may be because you're running mod_python and mod_php in the same
Apache instance, with MySQL as your database backend. In some cases,
this causes a known mod_python issue due to version conflicts in PHP and
the Python MySQL backend. There's full information in the
`mod_python FAQ entry`_.
If you continue to have problems setting up mod_python, a good thing to do is
get a barebones mod_python site working, without the Django framework. This is
an easy way to isolate mod_python-specific problems. `Getting mod_python Working`_
details this procedure.
The next step should be to edit your test code and add an import of any
Django-specific code you're using -- your views, your models, your URLconf,
your RSS configuration, etc. Put these imports in your test handler function
and access your test URL in a browser. If this causes a crash, you've confirmed
it's the importing of Django code that causes the problem. Gradually reduce the
set of imports until it stops crashing, so as to find the specific module that
causes the problem. Drop down further into modules and look into their imports,
as necessary.
.. _Expat Causing Apache Crash: http://www.dscpl.com.au/articles/modpython-006.html
.. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp
.. _Getting mod_python Working: http://www.dscpl.com.au/articles/modpython-001.html

View File

@@ -0,0 +1,65 @@
.. _howto-error-reporting:
Error reporting via e-mail
==========================
When you're running a public site you should always turn off the
:setting:`DEBUG` setting. That will make your server run much faster, and will
also prevent malicious users from seeing details of your application that can be
revealed by the error pages.
However, running with :setting:`DEBUG` set to ``False`` means you'll never see
errors generated by your site -- everyone will just see your public error pages.
You need to keep track of errors that occur in deployed sites, so Django can be
configured to email you details of those errors.
Server errors
-------------
When :setting:`DEBUG` is ``False``, Django will e-mail the users listed in the
:setting:`ADMIN` setting whenever your code raises an unhandled exception and
results in an internal server error (HTTP status code 500). This gives the
administrators immediate notification of any errors. The :setting:`ADMINS` will
get a description of the error, a complete Python traceback, and details about
the HTTP request that caused the error.
To disable this behavior, just remove all entries from the :setting:`ADMINS`
setting.
404 errors
----------
Django can also be configured to email errors about broken links (404 "page
not found" errors). Django sends emails about 404 errors when:
* :setting:`DEBUG` is ``False``
* :setting:`SEND_BROKEN_LINK_EMAILS` is ``True``
* Your :setting:`MIDDLEWARE_CLASSES` setting includes ``CommonMiddleware``
(which it does by default).
If those conditions are met, Django will e-mail the users listed in the
:setting:`MANAGERS` setting whenever your code raises a 404 and the request has
a referer. (It doesn't bother to e-mail for 404s that don't have a referer --
those are usually just people typing in broken URLs or broken web 'bots).
You can tell Django to stop reporting particular 404s by tweaking the
:setting:`IGNORABLE_404_ENDS` and :setting:`IGNORABLE_404_STARTS` settings. Both
should be a tuple of strings. For example::
IGNORABLE_404_ENDS = ('.php', '.cgi')
IGNORABLE_404_STARTS = ('/phpmyadmin/',)
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* be
reported. Neither will any URL starting with ``/phpmyadmin/``.
The best way to disable this behavior is to set
:setting:`SEND_BROKEN_LINK_EMAILS` to ``False``.
.. seealso::
You can also set up custom error reporting by writing a custom piece of
:ref:`exception middleware <exception-middleware>`. If you do write custom
error handling, it's a good idea to emulate Django's built-in error handling
and only report/log errors if :setting:`DEBUG` is ``False``.

33
docs/howto/index.txt Normal file
View File

@@ -0,0 +1,33 @@
.. _howto-index:
"How-to" guides
===============
Here you'll find short answers to "How do I....?" types of questions. These
how-to guides don't cover topics in depth -- you'll find that material in the
:ref:`topics-index` and the :ref:`ref-index`. However, these guides will help
you quickly accomplish common tasks.
.. toctree::
:maxdepth: 1
apache-auth
custom-management-commands
custom-model-fields
custom-template-tags
custom-file-storage
deployment/index
error-reporting
initial-data
legacy-databases
outputting-csv
outputting-pdf
static-files
.. seealso::
The `Django community aggregator`_, where we aggregate content from the
global Django community. Many writers in the aggregator write this sort of
how-to material.
.. _django community aggregator: http://www.djangoproject.com/community/

140
docs/howto/initial-data.txt Normal file
View File

@@ -0,0 +1,140 @@
.. _howto-initial-data:
=================================
Providing initial data for models
=================================
It's sometimes useful to pre-populate your database with hard-coded data when
you're first setting up an app. There's a couple of ways you can have Django
automatically create this data: you can provide `initial data via fixtures`_, or
you can provide `initial data as SQL`_.
In general, using a fixture is a cleaner method since it's database-agnostic,
but initial SQL is also quite a bit more flexible.
.. _initial data as sql: `providing initial sql data`_
.. _initial data via fixtures: `providing initial data with fixtures`_
Providing initial data with fixtures
====================================
A fixture is a collection of data that Django knows how to import into a
database. The most straightforward way of creating a fixture if you've already
got some data is to use the :djadmin:`manage.py dumpdata` command. Or, you can
write fixtures by hand; fixtures can be written as XML, YAML, or JSON documents.
The :ref:`serialization documentation <topics-serialization>` has more details
about each of these supported :ref:`serialization formats
<serialization-formats>`.
As an example, though, here's what a fixture for a simple ``Person`` model might
look like in JSON:
.. code-block:: js
[
{
"model": "myapp.person",
"pk": 1,
"fields": {
"first_name": "John",
"last_name": "Lennon",
}
},
{
"model": "myapp.person",
"pk": 2,
"fields": {
"first_name": "Paul",
"last_name": "McCartney",
}
},
]
And here's that same fixture as YAML:
.. code-block:: none
- model: myapp.person
pk: 1
fields:
first_name: John
last_name: Lennon
- model: myapp.person
pk: 1
fields:
first_name: Paul
last_name: McCartney
You'll store this data in a ``fixtures`` directory inside you app.
Loading data is easy: just call :djadmin:`manage.py loaddata fixturename
<loaddata>`, where *fixturename* is the name of the fixture file you've created.
Every time you run :djadmin:`loaddata` the data will be read from the fixture
and re-loaded into the database. Note that this means that if you change one of
the rows created by a fixture and the run :djadmin:`loaddata` again you'll wipe
out any changes you've made.
Automatically loading initial data fixtures
-------------------------------------------
If you create a fixture named ``initial_data.[xml/yml/json]``, that fixture will
be loaded every time you run :djadmin:`syncdb`. This is extremely convenient,
but be careful: remember that the data will be refreshed *every time* you run
:djadmin:`syncdb`. So don't use ``initial_data`` for data you'll want to edit.
.. seealso::
Fixtures are also used by the :ref:`testing framework
<topics-testing-fixtures>` to help set up a consistent test environment.
.. _initial-sql:
Providing initial SQL data
==========================
Django provides a hook for passing the database arbitrary SQL that's executed
just after the CREATE TABLE statements when you run :djadmin:`syncdb`. You can
use this hook to populate default records, or you could also create SQL
functions, views, triggers, etc.
The hook is simple: Django just looks for a file called ``sql/<modelname>.sql``,
in your app directory, where ``<modelname>`` is the model's name in lowercase.
So, if you had a ``Person`` model in an app called ``myapp``, you could add
arbitrary SQL to the file ``sql/person.sql`` inside your ``myapp`` directory.
Here's an example of what the file might contain:
.. code-block:: sql
INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon');
INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney');
Each SQL file, if given, is expected to contain valid SQL statements
which will insert the desired data (e.g., properly-formatted
``INSERT`` statements separated by semicolons).
The SQL files are read by the :djadmin:`sqlcustom`, :djadmin:`sqlreset`,
:djadmin:`sqlall` and :djadmin:`reset` commands in :ref:`manage.py
<ref-django-admin>`. Refer to the :ref:`manage.py documentation
<ref-django-admin>` for more information.
Note that if you have multiple SQL data files, there's no guarantee of the order
in which they're executed. The only thing you can assume is that, by the time
your custom data files are executed, all the database tables already will have
been created.
Database-backend-specific SQL data
----------------------------------
There's also a hook for backend-specific SQL data. For example, you can have
separate initial-data files for PostgreSQL and MySQL. For each app, Django
looks for a file called ``<appname>/sql/<modelname>.<backend>.sql``, where
``<appname>`` is your app directory, ``<modelname>`` is the model's name in
lowercase and ``<backend>`` is the value of :setting:`DATABASE_ENGINE` in your
settings file (e.g., ``postgresql``, ``mysql``).
Backend-specific SQL data is executed before non-backend-specific SQL data. For
example, if your app contains the files ``sql/person.sql`` and
``sql/person.postgresql.sql`` and you're installing the app on PostgreSQL,
Django will execute the contents of ``sql/person.postgresql.sql`` first, then
``sql/person.sql``.

View File

@@ -0,0 +1,67 @@
.. _howto-legacy-databases:
=========================================
Integrating Django with a legacy database
=========================================
While Django is best suited for developing new applications, it's quite
possible to integrate it into legacy databases. Django includes a couple of
utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the
:ref:`tutorial <intro-tutorial01>`.
Once you've got Django set up, you'll follow this general process to integrate
with an existing database.
Give Django your database parameters
====================================
You'll need to tell Django what your database connection parameters are, and
what the name of the database is. Do that by editing these settings in your
:ref:`settings file <topics-settings>`:
* :setting:`DATABASE_NAME`
* :setting:`DATABASE_ENGINE`
* :setting:`DATABASE_USER`
* :setting:`DATABASE_PASSWORD`
* :setting:`DATABASE_HOST`
* :setting:`DATABASE_PORT`
Auto-generate the models
========================
.. highlight:: bash
Django comes with a utility called :djadmin:`inspectdb` that can create models
by introspecting an existing database. You can view the output by running this
command::
python manage.py inspectdb
Save this as a file by using standard Unix output redirection::
python manage.py inspectdb > models.py
This feature is meant as a shortcut, not as definitive model generation. See the
:djadmin:`documentation of inspectdb <inspectdb>` for more information.
Once you've cleaned up your models, name the file ``models.py`` and put it in
the Python package that holds your app. Then add the app to your
:setting:`INSTALLED_APPS` setting.
Install the core Django tables
==============================
Next, run the :djadmin:`syncdb` command to install any extra needed database
records such as admin permissions and content types::
python manage.py syncdb
Test and tweak
==============
Those are the basic steps -- from here you'll want to tweak the models Django
generated until they work the way you'd like. Try accessing your data via the
Django database API, and try editing objects via Django's admin site, and edit
the models file accordingly.

View File

@@ -0,0 +1,116 @@
.. _howto-outputting-csv:
==========================
Outputting CSV with Django
==========================
This document explains how to output CSV (Comma Separated Values) dynamically
using Django views. To do this, you can either use the `Python CSV library`_ or
the Django template system.
.. _Python CSV library: http://www.python.org/doc/current/lib/module-csv.html
Using the Python CSV library
============================
Python comes with a CSV library, ``csv``. The key to using it with Django is
that the ``csv`` module's CSV-creation capability acts on file-like objects, and
Django's :class:`~django.http.HttpResponse` objects are file-like objects.
Here's an example::
import csv
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
writer = csv.writer(response)
writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
return response
The code and comments should be self-explanatory, but a few things deserve a
mention:
* The response gets a special MIME type, ``text/csv``. This tells
browsers that the document is a CSV file, rather than an HTML file. If
you leave this off, browsers will probably interpret the output as HTML,
which will result in ugly, scary gobbledygook in the browser window.
* The response gets an additional ``Content-Disposition`` header, which
contains the name of the CSV file. This filename is arbitrary; call it
whatever you want. It'll be used by browsers in the "Save as..."
dialogue, etc.
* Hooking into the CSV-generation API is easy: Just pass ``response`` as the
first argument to ``csv.writer``. The ``csv.writer`` function expects a
file-like object, and :class:`~django.http.HttpResponse` objects fit the
bill.
* For each row in your CSV file, call ``writer.writerow``, passing it an
iterable object such as a list or tuple.
* The CSV module takes care of quoting for you, so you don't have to worry
about escaping strings with quotes or commas in them. Just pass
``writerow()`` your raw strings, and it'll do the right thing.
Using the template system
=========================
Alternatively, you can use the :ref:`Django template system <topics-templates>`
to generate CSV. This is lower-level than using the convenient CSV, but the
solution is presented here for completeness.
The idea here is to pass a list of items to your template, and have the
template output the commas in a :ttag:`for` loop.
Here's an example, which generates the same CSV file as above::
from django.http import HttpResponse
from django.template import loader, Context
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
# The data is hard-coded here, but you could load it from a database or
# some other source.
csv_data = (
('First row', 'Foo', 'Bar', 'Baz'),
('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
)
t = loader.get_template('my_template_name.txt')
c = Context({
'data': csv_data,
})
response.write(t.render(c))
return response
The only difference between this example and the previous example is that this
one uses template loading instead of the CSV module. The rest of the code --
such as the ``mimetype='text/csv'`` -- is the same.
Then, create the template ``my_template_name.txt``, with this template code:
.. code-block:: html+django
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
This template is quite basic. It just iterates over the given data and displays
a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
ensure there aren't any problems with quotes.
Other text-based formats
========================
Notice that there isn't very much specific to CSV here -- just the specific
output format. You can use either of these techniques to output any text-based
format you can dream of. You can also use a similar technique to generate
arbitrary binary data; see :ref:`howto-outputting-pdf` for an example.

View File

@@ -0,0 +1,160 @@
.. _howto-outputting-pdf:
===========================
Outputting PDFs with Django
===========================
This document explains how to output PDF files dynamically using Django views.
This is made possible by the excellent, open-source ReportLab_ Python PDF
library.
The advantage of generating PDF files dynamically is that you can create
customized PDFs for different purposes -- say, for different users or different
pieces of content.
For example, Django was used at kusports.com_ to generate customized,
printer-friendly NCAA tournament brackets, as PDF files, for people
participating in a March Madness contest.
.. _ReportLab: http://www.reportlab.org/rl_toolkit.html
.. _kusports.com: http://www.kusports.com/
Install ReportLab
=================
Download and install the ReportLab library from http://www.reportlab.org/downloads.html.
The `user guide`_ (not coincidentally, a PDF file) explains how to install it.
Test your installation by importing it in the Python interactive interpreter::
>>> import reportlab
If that command doesn't raise any errors, the installation worked.
.. _user guide: http://www.reportlab.com/docs/userguide.pdf
Write your view
===============
The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django's :class:`~django.http.HttpResponse`
objects are file-like objects.
Here's a "Hello World" example::
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
The code and comments should be self-explanatory, but a few things deserve a
mention:
* The response gets a special MIME type, ``application/pdf``. This tells
browsers that the document is a PDF file, rather than an HTML file. If
you leave this off, browsers will probably interpret the output as HTML,
which would result in ugly, scary gobbledygook in the browser window.
* The response gets an additional ``Content-Disposition`` header, which
contains the name of the PDF file. This filename is arbitrary: Call it
whatever you want. It'll be used by browsers in the "Save as..."
dialogue, etc.
* The ``Content-Disposition`` header starts with ``'attachment; '`` in this
example. This forces Web browsers to pop-up a dialog box
prompting/confirming how to handle the document even if a default is set
on the machine. If you leave off ``'attachment;'``, browsers will handle
the PDF using whatever program/plugin they've been configured to use for
PDFs. Here's what that code would look like::
response['Content-Disposition'] = 'filename=somefilename.pdf'
* Hooking into the ReportLab API is easy: Just pass ``response`` as the
first argument to ``canvas.Canvas``. The ``Canvas`` class expects a
file-like object, and :class:`~django.http.HttpResponse` objects fit the
bill.
* Note that all subsequent PDF-generation methods are called on the PDF
object (in this case, ``p``) -- not on ``response``.
* Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
file.
Complex PDFs
============
If you're creating a complex PDF document with ReportLab, consider using the
cStringIO_ library as a temporary holding place for your PDF file. The cStringIO
library provides a file-like object interface that is particularly efficient.
Here's the above "Hello World" example rewritten to use ``cStringIO``::
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
buffer = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(buffer)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
.. _cStringIO: http://www.python.org/doc/current/lib/module-cStringIO.html
Further resources
=================
* PDFlib_ is another PDF-generation library that has Python bindings. To
use it with Django, just use the same concepts explained in this article.
* `Pisa HTML2PDF`_ is yet another PDF-generation library. Pisa ships with
an example of how to integrate Pisa with Django.
* HTMLdoc_ is a command-line script that can convert HTML to PDF. It
doesn't have a Python interface, but you can escape out to the shell
using ``system`` or ``popen`` and retrieve the output in Python.
* `forge_fdf in Python`_ is a library that fills in PDF forms.
.. _PDFlib: http://www.pdflib.org/
.. _`Pisa HTML2PDF`: http://www.htmltopdf.org/
.. _HTMLdoc: http://www.htmldoc.org/
.. _forge_fdf in Python: http://www.accesspdf.com/article.php/20050421092951834
Other formats
=============
Notice that there isn't a lot in these examples that's PDF-specific -- just the
bits using ``reportlab``. You can use a similar technique to generate any
arbitrary format that you can find a Python library for. Also see
:ref:`howto-outputting-csv` for another example and some techniques you can use
when generated text-based formats.

131
docs/howto/static-files.txt Normal file
View File

@@ -0,0 +1,131 @@
.. _howto-static-files:
=========================
How to serve static files
=========================
.. module:: django.views.static
:synopsis: Serving of static files during development.
Django itself doesn't serve static (media) files, such as images, style sheets,
or video. It leaves that job to whichever Web server you choose.
The reasoning here is that standard Web servers, such as Apache_ and lighttpd_,
are much more fine-tuned at serving static files than a Web application
framework.
With that said, Django does support static files **during development**. You can
use the :func:`django.views.static.serve` view to serve media files.
.. _Apache: http://httpd.apache.org/
.. _lighttpd: http://www.lighttpd.net/
The big, fat disclaimer
=======================
Using this method is **inefficient** and **insecure**. Do not use this in a
production setting. Use this only for development.
For information on serving static files in an Apache production environment,
see the :ref:`Django mod_python documentation <serving-media-files>`.
How to do it
============
Here's the formal definition of the :func:`~django.views.static.serve` view:
.. function:: def serve(request, path, document_root, show_indexes=False):
To use it, just put this in your :ref:`URLconf <topics-http-urls>`::
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
...where ``site_media`` is the URL where your media will be rooted, and
``/path/to/media`` is the filesystem root for your media. This will call the
:func:`~django.views.static.serve` view, passing in the path from the URLconf
and the (required) ``document_root`` parameter.
Given the above URLconf:
* The file ``/path/to/media/foo.jpg`` will be made available at the URL
``/site_media/foo.jpg``.
* The file ``/path/to/media/css/mystyles.css`` will be made available
at the URL ``/site_media/css/mystyles.css``.
* The file ``/path/bar.jpg`` will not be accessible, because it doesn't
fall under the document root.
Directory listings
==================
Optionally, you can pass the ``show_indexes`` parameter to the
:func:`~django.views.static.serve` view. This is ``False`` by default. If it's
``True``, Django will display file listings for directories.
For example::
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
You can customize the index view by creating a template called
``static/directory_index.html``. That template gets two objects in its context:
* ``directory`` -- the directory name (a string)
* ``file_list`` -- a list of file names (as strings) in the directory
Here's the default ``static/directory_index`` template:
.. code-block:: html+django
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<meta name="robots" content="NONE,NOARCHIVE" />
<title>Index of {{ directory }}</title>
</head>
<body>
<h1>Index of {{ directory }}</h1>
<ul>
{% for f in file_list %}
<li><a href="{{ f }}">{{ f }}</a></li>
{% endfor %}
</ul>
</body>
</html>
Limiting use to DEBUG=True
==========================
Because URLconfs are just plain Python modules, you can use Python logic to
make the static-media view available only in development mode. This is a handy
trick to make sure the static-serving view doesn't slip into a production
setting by mistake.
Do this by wrapping an ``if DEBUG`` statement around the
:func:`django.views.static.serve` inclusion. Here's a full example URLconf::
from django.conf.urls.defaults import *
from django.conf import settings
urlpatterns = patterns('',
(r'^articles/2003/$', 'news.views.special_case_2003'),
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
)
if settings.DEBUG:
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
)
This code is straightforward. It imports the settings and checks the value of
the :setting:`DEBUG` setting. If it evaluates to ``True``, then ``site_media``
will be associated with the ``django.views.static.serve`` view. If not, then the
view won't be made available.
Of course, the catch here is that you'll have to remember to set ``DEBUG=False``
in your production settings file. But you should be doing that anyway.