diff options
author | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
---|---|---|
committer | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
commit | b03203c8cb991c16ac8a3d74c8c4078182d0bb48 (patch) | |
tree | 7cf13b2deacbfaaec99edb431b83ddd5ea734a52 /parts/django/docs/howto | |
parent | 0c50203cd9eb94b819883c3110922e873f003138 (diff) | |
download | pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.gz pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.bz2 pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.zip |
removed all the buildout files
Diffstat (limited to 'parts/django/docs/howto')
19 files changed, 0 insertions, 4163 deletions
diff --git a/parts/django/docs/howto/apache-auth.txt b/parts/django/docs/howto/apache-auth.txt deleted file mode 100644 index 2ebae0b..0000000 --- a/parts/django/docs/howto/apache-auth.txt +++ /dev/null @@ -1,120 +0,0 @@ -========================================================= -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 -:doc:`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 diff --git a/parts/django/docs/howto/auth-remote-user.txt b/parts/django/docs/howto/auth-remote-user.txt deleted file mode 100644 index deab794..0000000 --- a/parts/django/docs/howto/auth-remote-user.txt +++ /dev/null @@ -1,100 +0,0 @@ -==================================== -Authentication using ``REMOTE_USER`` -==================================== - -.. currentmodule:: django.contrib.auth.backends - -This document describes how to make use of external authentication sources -(where the Web server sets the ``REMOTE_USER`` environment variable) in your -Django applications. This type of authentication solution is typically seen on -intranet sites, with single sign-on solutions such as IIS and Integrated -Windows Authentication or Apache and `mod_authnz_ldap`_, `CAS`_, `Cosign`_, -`WebAuth`_, `mod_auth_sspi`_, etc. - -.. _mod_authnz_ldap: http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html -.. _CAS: http://www.jasig.org/cas -.. _Cosign: http://weblogin.org -.. _WebAuth: http://www.stanford.edu/services/webauth/ -.. _mod_auth_sspi: http://sourceforge.net/projects/mod-auth-sspi - -When the Web server takes care of authentication it typically sets the -``REMOTE_USER`` environment variable for use in the underlying application. In -Django, ``REMOTE_USER`` is made available in the :attr:`request.META -<django.http.HttpRequest.META>` attribute. Django can be configured to make -use of the ``REMOTE_USER`` value using the ``RemoteUserMiddleware`` and -``RemoteUserBackend`` classes found in :mod:`django.contrib.auth`. - -Configuration -============= - -First, you must add the -:class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the -:setting:`MIDDLEWARE_CLASSES` setting **after** the -:class:`django.contrib.auth.middleware.AuthenticationMiddleware`:: - - MIDDLEWARE_CLASSES = ( - ... - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.RemoteUserMiddleware', - ... - ) - -Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend` -with ``RemoteUserBackend`` in the :setting:`AUTHENTICATION_BACKENDS` setting:: - - AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.RemoteUserBackend', - ) - -With this setup, ``RemoteUserMiddleware`` will detect the username in -``request.META['REMOTE_USER']`` and will authenticate and auto-login that user -using the ``RemoteUserBackend``. - -.. note:: - Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will - still have all of the same permissions checking that is implemented in - ``ModelBackend``. - -If your authentication mechanism uses a custom HTTP header and not -``REMOTE_USER``, you can subclass ``RemoteUserMiddleware`` and set the -``header`` attribute to the desired ``request.META`` key. For example:: - - from django.contrib.auth.middleware import RemoteUserMiddleware - - class CustomHeaderMiddleware(RemoteUserMiddleware): - header = 'HTTP_AUTHUSER' - - -``RemoteUserBackend`` -===================== - -.. class:: django.contrib.auth.backends.RemoteUserBackend - -If you need more control, you can create your own authentication backend -that inherits from ``RemoteUserBackend`` and overrides certain parts: - -Attributes -~~~~~~~~~~ - -.. attribute:: RemoteUserBackend.create_unknown_user - - ``True`` or ``False``. Determines whether or not a - :class:`~django.contrib.auth.models.User` object is created if not already - in the database. Defaults to ``True``. - -Methods -~~~~~~~ - -.. method:: RemoteUserBackend.clean_username(username) - - Performs any cleaning on the ``username`` (e.g. stripping LDAP DN - information) prior to using it to get or create a - :class:`~django.contrib.auth.models.User` object. Returns the cleaned - username. - -.. method:: RemoteUserBackend.configure_user(user) - - Configures a newly created user. This method is called immediately after a - new user is created, and can be used to perform custom setup actions, such - as setting the user's groups based on attributes in an LDAP directory. - Returns the user object. diff --git a/parts/django/docs/howto/custom-file-storage.txt b/parts/django/docs/howto/custom-file-storage.txt deleted file mode 100644 index 1b0f32f..0000000 --- a/parts/django/docs/howto/custom-file-storage.txt +++ /dev/null @@ -1,90 +0,0 @@ -Writing a custom storage system -=============================== - -.. currentmodule:: django.core.files.storage - -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 -:doc:`/ref/files/storage`, but you **must** implement the following methods: - - * :meth:`Storage.delete` - * :meth:`Storage.exists` - * :meth:`Storage.listdir` - * :meth:`Storage.size` - * :meth:`Storage.url` - -You'll also usually want to use 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. - -Should return the actual name of name of the file saved (usually the ``name`` -passed in, but if the storage needs to change the file name return the new name -instead). - -``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 ``"_1"``, ``"_2"``, etc. to the -filename until it finds one that's available in the destination directory. diff --git a/parts/django/docs/howto/custom-management-commands.txt b/parts/django/docs/howto/custom-management-commands.txt deleted file mode 100644 index 4a1747f..0000000 --- a/parts/django/docs/howto/custom-management-commands.txt +++ /dev/null @@ -1,253 +0,0 @@ -==================================== -Writing custom django-admin commands -==================================== - -.. versionadded:: 1.0 - -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. In this document, we will be building a custom ``closepoll`` -command for the ``polls`` application from the -:doc:`tutorial</intro/tutorial01>`. - -To do this, just add a ``management/commands`` directory to the 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``:: - - polls/ - __init__.py - models.py - management/ - __init__.py - commands/ - __init__.py - closepoll.py - tests.py - views.py - -In this example, the ``closepoll`` command will be made available to any project -that includes the ``polls`` application in :setting:`INSTALLED_APPS`. - -The ``closepoll.py`` module has only one requirement -- it must define a class -``Command`` that extends :class:`BaseCommand` or one of its -:ref:`subclasses<ref-basecommand-subclasses>`. - -.. admonition:: Standalone scripts - - Custom management commands are especially useful for running standalone - scripts or for scripts that are periodically executed from the UNIX crontab - or from Windows scheduled tasks control panel. - -To implement the command, edit ``polls/management/commands/closepoll.py`` to -look like this: - -.. code-block:: python - - from django.core.management.base import BaseCommand, CommandError - from example.polls.models import Poll - - class Command(BaseCommand): - args = '<poll_id poll_id ...>' - help = 'Closes the specified poll for voting' - - def handle(self, *args, **options): - for poll_id in args: - try: - poll = Poll.objects.get(pk=int(poll_id)) - except Poll.DoesNotExist: - raise CommandError('Poll "%s" does not exist' % poll_id) - - poll.opened = False - poll.save() - - print 'Successfully closed poll "%s"' % poll_id - -The new custom command can be called using ``python manage.py closepoll -<poll_id>``. - -The ``handle()`` method takes zero or more ``poll_ids`` and sets ``poll.opened`` -to ``False`` for each one. If the user referenced any nonexistant polls, a -:class:`CommandError` is raised. The ``poll.opened`` attribute does not exist -in the :doc:`tutorial</intro/tutorial01>` and was added to -``polls.models.Poll`` for this example. - -The same ``closepoll`` could be easily modified to delete a given poll instead -of closing it by accepting additional command line options. These custom options -must be added to :attr:`~BaseCommand.option_list` like this: - -.. code-block:: python - - from optparse import make_option - - class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--delete', - action='store_true', - dest='delete', - default=False, - help='Delete poll instead of closing it'), - ) - # ... - -In addition to being able to add custom command line options, all -:doc:`management commands</ref/django-admin>` can accept some -default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`. - -Command objects -=============== - -.. class:: BaseCommand - -The base class from which all management commands ultimately derive. - -Use this class if you want access to all of the mechanisms which -parse the command-line arguments and work out what code to call in -response; if you don't need to change any of that behavior, -consider using one of its :ref:`subclasses<ref-basecommand-subclasses>`. - -Subclassing the :class:`BaseCommand` class requires that you implement the -:meth:`~BaseCommand.handle` method. - -Attributes ----------- - -All attributes can be set in your derived class and can be used in -:class:`BaseCommand`'s :ref:`subclasses<ref-basecommand-subclasses>`. - -.. attribute:: BaseCommand.args - - A string listing the arguments accepted by the command, - suitable for use in help messages; e.g., a command which takes - a list of application names might set this to '<appname - appname ...>'. - -.. attribute:: BaseCommand.can_import_settings - - A boolean indicating whether the command needs to be able to - import Django settings; if ``True``, ``execute()`` will verify - that this is possible before proceeding. Default value is - ``True``. - -.. attribute:: BaseCommand.help - - A short description of the command, which will be printed in the - help message when the user runs the command - ``python manage.py help <command>``. - -.. attribute:: BaseCommand.option_list - - This is the list of ``optparse`` options which will be fed - into the command's ``OptionParser`` for parsing arguments. - -.. attribute:: BaseCommand.output_transaction - - A boolean indicating whether the command outputs SQL - statements; if ``True``, the output will automatically be - wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is - ``False``. - -.. attribute:: BaseCommand.requires_model_validation - - A boolean; if ``True``, validation of installed models will be - performed prior to executing the command. Default value is - ``True``. To validate an individual application's models - rather than all applications' models, call - :meth:`~BaseCommand.validate` from :meth:`~BaseCommand.handle`. - -Methods -------- - -:class:`BaseCommand` has a few methods that can be overridden but only -the :meth:`~BaseCommand.handle` method must be implemented. - -.. admonition:: Implementing a constructor in a subclass - - If you implement ``__init__`` in your subclass of :class:`BaseCommand`, - you must call :class:`BaseCommand`'s ``__init__``. - - .. code-block:: python - - class Command(BaseCommand): - def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) - # ... - -.. method:: BaseCommand.get_version() - - Return the Django version, which should be correct for all - built-in Django commands. User-supplied commands can - override this method to return their own version. - -.. method:: BaseCommand.execute(*args, **options) - - Try to execute this command, performing model validation if - needed (as controlled by the attribute - :attr:`requires_model_validation`). If the command raises a - :class:`CommandError`, intercept it and print it sensibly to - stderr. - -.. method:: BaseCommand.handle(*args, **options) - - The actual logic of the command. Subclasses must implement this method. - -.. _ref-basecommand-subclasses: - -BaseCommand subclasses ----------------------- - -.. class:: AppCommand - -A management command which takes one or more installed application -names as arguments, and does something with each of them. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~AppCommand.handle_app`, which will be called once for each application. - -.. method:: AppCommand.handle_app(app, **options) - - Perform the command's actions for ``app``, which will be the - Python module corresponding to an application name given on - the command line. - -.. class:: LabelCommand - -A management command which takes one or more arbitrary arguments -(labels) on the command line, and does something with each of -them. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~LabelCommand.handle_label`, which will be called once for each label. - -.. method:: LabelCommand.handle_label(label, **options) - - Perform the command's actions for ``label``, which will be the - string as given on the command line. - -.. class:: NoArgsCommand - -A command which takes no arguments on the command line. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is -overridden to ensure no arguments are passed to the command. - -.. method:: NoArgsCommand.handle_noargs(**options) - - Perform this command's actions - -.. _ref-command-exceptions: - -Command exceptions ------------------- - -.. class:: CommandError - -Exception class indicating a problem while executing a management -command. - -If this exception is raised during the execution of a management -command, it will be caught and turned into a nicely-printed error -message to the appropriate output stream (i.e., stderr); as a -result, raising this exception (with a sensible description of the -error) is the preferred way to indicate that something has gone -wrong in the execution of a command. diff --git a/parts/django/docs/howto/custom-model-fields.txt b/parts/django/docs/howto/custom-model-fields.txt deleted file mode 100644 index 1840c5b..0000000 --- a/parts/django/docs/howto/custom-model-fields.txt +++ /dev/null @@ -1,745 +0,0 @@ -=========================== -Writing custom model fields -=========================== - -.. versionadded:: 1.0 -.. currentmodule:: django.db.models - -Introduction -============ - -The :doc:`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: -wrapping a Python object representing the deal of cards in a hand of Bridge_. -Don't worry, you don't have 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): - """A hand of cards (bridge style)""" - - 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 :doc:`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, 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 :doc:`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): - - description = "A hand of cards (bridge style)" - - def __init__(self, *args, **kwargs): - kwargs['max_length'] = 104 - super(HandField, self).__init__(*args, **kwargs) - -Our ``HandField`` accepts 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.rel`: Used for related fields (like - :class:`ForeignKey`). For advanced use only. - * :attr:`~django.db.models.Field.default` - * :attr:`~django.db.models.Field.editable` - * :attr:`~django.db.models.Field.serialize`: If ``False``, the field will - not be serialized when the model is passed to Django's :doc:`serializers - </topics/serialization>`. Defaults to ``True``. - * :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.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. - * :attr:`~django.db.models.Field.auto_created`: True if the field was - automatically created, as for the `OneToOneField` used by model - inheritance. For advanced use only. - -All of the options without an explanation in the above list have the same -meaning they do for normal Django fields. See the :doc:`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): - - description = "A hand of cards (bridge style)" - - __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. - -ModelForms and custom fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you use :class:`~django.db.models.SubfieldBase`, :meth:`to_python` -will be called every time an instance of the field is assigned a -value. This means that whenever a value may be assigned to the field, -you need to ensure that it will be of the correct datatype, or that -you handle any exceptions. - -This is especially important if you use :doc:`ModelForms -</topics/forms/modelforms>`. When saving a ModelForm, Django will use -form values to instantiate model instances. However, if the cleaned -form data can't be used as valid input to the field, the normal form -validation process will break. - -Therefore, you must ensure that the form field used to represent your -custom field performs whatever input validation and data cleaning is -necessary to convert user-provided form input into a -`to_python()`-compatible model field value. This may require writing a -custom form field, and/or implementing the :meth:`formfield` method on -your field to return a form field class whose `to_python()` returns the -correct datatype. - -Documenting your Custom Field ------------------------------ - -.. class:: django.db.models.Field - -.. attribute:: description - -As always, you should document your field type, so users will know what it is. -In addition to providing a docstring for it, which is useful for developers, -you can also allow users of the admin app to see a short description of the -field type via the :doc:`django.contrib.admindocs -</ref/contrib/admin/admindocs>` application. To do this simply provide -descriptive text in a ``description`` class attribute of your custom field. In -the above example, the type description displayed by the ``admindocs`` -application for a ``HandField`` will be 'A hand of cards (bridge style)'. - -Useful methods --------------- - -Once you've created your :class:`~django.db.models.Field` subclass and set 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, connection) - -.. versionadded:: 1.2 - The ``connection`` argument was added to support multiple databases. - -Returns the database column data type for the :class:`~django.db.models.Field`, -taking into account the connection object, and the settings associated with it. - -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, connection): - 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 -check the ``connection.settings_dict['ENGINE']`` attribute. - -For example:: - - class MyDateField(models.Field): - def db_type(self, connection): - if connection.settings_dict['ENGINE'] == 'django.db.backends.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 ``connection.settings_dict`` -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, connection): - 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, connection): - 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 query values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: get_prep_value(self, value) - -.. versionadded:: 1.2 - This method was factored out of ``get_db_prep_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 has been -prepared for use as a parameter in a query. - -This conversion should *not* include any database-specific -conversions. If database-specific conversions are required, they -should be made in the call to :meth:`get_db_prep_value`. - -For example:: - - class HandField(models.Field): - # ... - - def get_prep_value(self, value): - return ''.join([''.join(l) for l in (value.north, - value.east, value.south, value.west)]) - -Converting query values to database values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: get_db_prep_value(self, value, connection, prepared=False) - -.. versionadded:: 1.2 - The ``connection`` and ``prepared`` arguments were added to support multiple databases. - -Some data types (for example, dates) need to be in a specific format -before they can be used by a database backend. -:meth:`get_db_prep_value` is the method where those conversions should -be made. The specific connection that will be used for the query is -passed as the ``connection`` parameter. This allows you to use -backend-specific conversion logic if it is required. - -The ``prepared`` argument describes whether or not the value has -already been passed through :meth:`get_prep_value` conversions. When -``prepared`` is False, the default implementation of -:meth:`get_db_prep_value` will call :meth:`get_prep_value` to do -initial data conversions before performing any database-specific -processing. - -.. method:: get_db_prep_save(self, value, connection) - -.. versionadded:: 1.2 - The ``connection`` argument was added to support multiple databases. - -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 needs a special conversion when being saved -that is not the same as the conversion 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 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As with value conversions, preparing a value for database lookups is a -two phase process. - -.. method:: get_prep_lookup(self, lookup_type, value) - -.. versionadded:: 1.2 - This method was factored out of ``get_db_prep_lookup()`` - -:meth:`get_prep_lookup` performs the first phase of lookup preparation, -performing generic data validity checks - -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 to 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_prep_lookup()``. If you don't, ``get_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_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_prep_value()``, or at least factor out some common -pieces. - -For example, the following code implements ``get_prep_lookup`` to limit the -accepted lookup types to ``exact`` and ``in``:: - - class HandField(models.Field): - # ... - - def get_prep_lookup(self, lookup_type, value): - # We only handle 'exact' and 'in'. All others are errors. - if lookup_type == 'exact': - return self.get_prep_value(value) - elif lookup_type == 'in': - return [self.get_prep_value(v) for v in value] - else: - raise TypeError('Lookup type %r not supported.' % lookup_type) - -.. method:: get_db_prep_lookup(self, lookup_type, value, connection, prepared=False) - -.. versionadded:: 1.2 - The ``connection`` and ``prepared`` arguments were added to support multiple databases. - -Performs any database-specific data conversions required by a lookup. -As with :meth:`get_db_prep_value`, the specific connection that will -be used for the query is passed as the ``connection`` parameter. -The ``prepared`` argument describes whether the value has already been -prepared with :meth:`get_prep_lookup`. - -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 :doc:`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've 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:: value_to_string(self, obj) - -This method is used by the serializers to convert the field into a string for -output. Calling :meth:`Field._get_val_from_obj(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 value_to_string(self, obj): - value = self._get_val_from_obj(obj) - return 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 -:doc:`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. diff --git a/parts/django/docs/howto/custom-template-tags.txt b/parts/django/docs/howto/custom-template-tags.txt deleted file mode 100644 index 95ce274..0000000 --- a/parts/django/docs/howto/custom-template-tags.txt +++ /dev/null @@ -1,939 +0,0 @@ -================================ -Custom template tags and filters -================================ - -Introduction -============ - -Django's template system comes with a wide variety of :doc:`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). - -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 -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -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 ``&`` into ``&``, 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. - - Marking a filter ``is_safe`` will coerce the filter's return value to - a string. If your filter should return a boolean or other non-string - value, marking it ``is_safe`` will probably have unintended - consequences (such as converting a boolean False to the string - 'False'). - - 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://docs.python.org/library/time.html#time.strftime - -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 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -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. - -.. _template_tag_thread_safety: - -Thread-safety considerations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -Once a node is parsed, its ``render`` method may be called any number of times. -Since Django is sometimes run in multi-threaded environments, a single node may -be simultaneously rendering with different contexts in response to two separate -requests. Therefore, it's important to make sure your template tags are thread -safe. - -To make sure your template tags are thread safe, you should never store state -information on the node itself. For example, Django provides a builtin ``cycle`` -template tag that cycles among a list of given strings each time it's rendered:: - - {% for o in some_list %} - <tr class="{% cycle 'row1' 'row2' %}> - ... - </tr> - {% endfor %} - -A naive implementation of ``CycleNode`` might look something like this:: - - class CycleNode(Node): - def __init__(self, cyclevars): - self.cycle_iter = itertools.cycle(cyclevars) - def render(self, context): - return self.cycle_iter.next() - -But, suppose we have two templates rendering the template snippet from above at -the same time: - - 1. Thread 1 performs its first loop iteration, ``CycleNode.render()`` - returns 'row1' - 2. Thread 2 performs its first loop iteration, ``CycleNode.render()`` - returns 'row2' - 3. Thread 1 performs its second loop iteration, ``CycleNode.render()`` - returns 'row1' - 4. Thread 2 performs its second loop iteration, ``CycleNode.render()`` - returns 'row2' - -The CycleNode is iterating, but it's iterating globally. As far as Thread 1 -and Thread 2 are concerned, it's always returning the same value. This is -obviously not what we want! - -To address this problem, Django provides a ``render_context`` that's associated -with the ``context`` of the template that is currently being rendered. The -``render_context`` behaves like a Python dictionary, and should be used to store -``Node`` state between invocations of the ``render`` method. - -Let's refactor our ``CycleNode`` implementation to use the ``render_context``:: - - class CycleNode(Node): - def __init__(self, cyclevars): - self.cyclevars = cyclevars - def render(self, context): - if self not in context.render_context: - context.render_context[self] = itertools.cycle(self.cyclevars) - cycle_iter = context.render_context[self] - return cycle_iter.next() - -Note that it's perfectly safe to store global information that will not change -throughout the life of the ``Node`` as an attribute. In the case of -``CycleNode``, the ``cyclevars`` argument doesn't change after the ``Node`` is -instantiated, so we don't need to put it in the ``render_context``. But state -information that is specific to the template that is currently being rendered, -like the current iteration of the ``CycleNode``, should be stored in the -``render_context``. - -.. note:: - Notice how we used ``self`` to scope the ``CycleNode`` specific information - within the ``render_context``. There may be multiple ``CycleNodes`` in a - given template, so we need to be careful not to clobber another node's state - information. The easiest way to do this is to always use ``self`` as the key - into ``render_context``. If you're keeping track of several state variables, - make ``render_context[self]`` a dictionary. - -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:: - - @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]) - -.. versionchanged:: 1.0 - Variable resolution has changed in the 1.0 release of Django. ``template.resolve_variable()`` - has been deprecated in favor of a new ``template.Variable`` class. - -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 ``Variable()`` class in ``django.template``. - -To use the ``Variable`` class, simply instantiate it with the name of the -variable to be resolved, and then call ``variable.resolve(context)``. So, -for example:: - - class FormatTimeNode(template.Node): - def __init__(self, date_to_be_formatted, format_string): - self.date_to_be_formatted = template.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 '' - -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) - -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. - -.. _howto-custom-template-tags-inclusion-tags: - -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, 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 examples 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> - -.. admonition:: Variable scope in context - - Any variable set in the context will only be available in the same ``block`` - of the template in which it was assigned. This behaviour is intentional; - it provides a scope for variables so that they don't conflict with - context in other blocks. - -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 - - {% 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``. diff --git a/parts/django/docs/howto/deployment/fastcgi.txt b/parts/django/docs/howto/deployment/fastcgi.txt deleted file mode 100644 index ea14b97..0000000 --- a/parts/django/docs/howto/deployment/fastcgi.txt +++ /dev/null @@ -1,400 +0,0 @@ -============================================ -How to use Django with FastCGI, SCGI, or AJP -============================================ - -.. highlight:: bash - -Although the current preferred setup for running Django is :doc:`Apache with -mod_wsgi </howto/deployment/modwsgi>`, many people use shared hosting, on -which protocols such as FastCGI, SCGI or AJP are the only viable options. In -some setups, these protocols may provide better performance than mod_wsgi_. - -.. 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_wsgi: http://code.google.com/p/modwsgi/ -.. _mod_perl: http://perl.apache.org/ -.. _mod_python: http://www.modpython.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 :doc:`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 :djadminopt:`socket`, a :djadminopt:`protocol` -or both :djadminopt:`host` and :djadminopt:`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 :djadminopt:`protocol=\<protocol_name\> <protocol>` 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 - -.. admonition:: Socket security - - Django's default umask requires that the webserver and the Django fastcgi - process be run with the same group **and** user. For increased security, - you can run them under the same group but as different users. If you do - this, you will need to set the umask to 0002 using the ``umask`` argument - to ``runfcgi``. - -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 :djadminopt:`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. - -Cherokee setup -============== - -Cherokee is a very fast, flexible and easy to configure Web Server. It -supports the widespread technologies nowadays: FastCGI, SCGI, PHP, CGI, SSI, -TLS and SSL encrypted connections, Virtual hosts, Authentication, on the fly -encoding, Load Balancing, Apache compatible log files, Data Base Balancer, -Reverse HTTP Proxy and much more. - -The Cherokee project provides a documentation to `setting up Django`_ with Cherokee. - -.. _setting up Django: http://www.cherokee-project.com/doc/cookbook_django.html - -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 Web server, 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 Web server 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 -:setting:`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. diff --git a/parts/django/docs/howto/deployment/index.txt b/parts/django/docs/howto/deployment/index.txt deleted file mode 100644 index 740f9bc..0000000 --- a/parts/django/docs/howto/deployment/index.txt +++ /dev/null @@ -1,25 +0,0 @@ -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 - - modwsgi - modpython - fastcgi - -If you're new to deploying Django and/or Python, we'd recommend you try -:doc:`mod_wsgi </howto/deployment/modwsgi>` first. In most cases it'll be the easiest, -fastest, and most stable deployment choice. - -.. seealso:: - - * `Chapter 12 of The Django Book`_ discusses deployment and especially - scaling in more detail. - -.. _chapter 12 of the django book: http://djangobook.com/en/2.0/chapter12/ diff --git a/parts/django/docs/howto/deployment/modpython.txt b/parts/django/docs/howto/deployment/modpython.txt deleted file mode 100644 index ba55335..0000000 --- a/parts/django/docs/howto/deployment/modpython.txt +++ /dev/null @@ -1,418 +0,0 @@ -.. _howto-deployment-modpython: - -============================================ -How to use Django with Apache and mod_python -============================================ - -.. warning:: - - Support for mod_python will be deprecated in a future release of Django. If - you are configuring a new deployment, you are strongly encouraged to - consider using :doc:`mod_wsgi </howto/deployment/modwsgi>` or any of the - other :doc:`supported backends </howto/deployment/index>`. - -.. highlight:: apache - -The `mod_python`_ module for Apache_ can be used to deploy Django to a -production server, although it has been mostly superseded by the simpler -:doc:`mod_wsgi deployment option </howto/deployment/modwsgi>`. - -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`_. - -.. seealso:: - - * Apache is a big, complex animal, and this document only scratches the - surface of what Apache can do. If you need more advanced information about - Apache, there's no better source than `Apache's own official - documentation`_ - - * You may also be interested in :doc:`How to use Django with FastCGI, SCGI, - or AJP </howto/deployment/fastcgi>`. - -.. _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 -.. _apache's own official documentation: http://httpd.apache.org/docs/ - -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. - -.. versionadded:: 1.0 - The ``PythonOption django.root ...`` is new in this 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. - -Make sure that your Python source files' permissions are set such that the -Apache user (usually named ``apache`` or ``httpd`` on most systems) will have -read access to the files. - -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. - -.. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html - -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`` -(or in different ``VirtualHost`` blocks that share the same server name), -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 output to ``stdout`` will not appear in the Apache -log and can even `cause response errors`_. - -.. _cause response errors: http://blog.dscpl.com.au/2009/04/wsgi-and-printing-to-standard-output.html - -If you have the need to print debugging information in a mod_python setup, you -have a few options. You can print to ``stderr`` explicitly, like so:: - - print >> sys.stderr, 'debug text' - sys.stderr.flush() - -(note that ``stderr`` is buffered, so calling ``flush`` is necessary if you wish -debugging information to be displayed promptly.) - -A more compact approach is to use an assertion:: - - assert False, 'debug text' - -Another alternative is to add debugging information to the template of your page. - -.. _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_ - * Nginx_ - * TUX_ - * A stripped-down version of Apache_ - * Cherokee_ - -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/ -.. _Nginx: http://wiki.nginx.org/Main -.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server -.. _Apache: http://httpd.apache.org/ -.. _Cherokee: http://www.cherokee-project.com/ - -.. _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 Web server 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/wiki/ModPython/Articles/ExpatCausingApacheCrash -.. _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/wiki/ModPython/Articles/GettingModPythonWorking - -If you get a UnicodeEncodeError -=============================== - -If you're taking advantage of the internationalization features of Django (see -:doc:`/topics/i18n/index`) and you intend to allow users to upload files, you must -ensure that the environment used to start Apache is configured to accept -non-ASCII file names. If your environment is not correctly configured, you -will trigger ``UnicodeEncodeError`` exceptions when calling functions like -``os.path()`` on filenames that contain non-ASCII characters. - -To avoid these problems, the environment used to start Apache should contain -settings analogous to the following:: - - export LANG='en_US.UTF-8' - export LC_ALL='en_US.UTF-8' - -Consult the documentation for your operating system for the appropriate syntax -and location to put these configuration items; ``/etc/apache2/envvars`` is a -common location on Unix platforms. Once you have added these statements -to your environment, restart Apache. diff --git a/parts/django/docs/howto/deployment/modwsgi.txt b/parts/django/docs/howto/deployment/modwsgi.txt deleted file mode 100644 index 17ba0e3..0000000 --- a/parts/django/docs/howto/deployment/modwsgi.txt +++ /dev/null @@ -1,118 +0,0 @@ -========================================== -How to use Django with Apache and mod_wsgi -========================================== - -Deploying Django with Apache_ and `mod_wsgi`_ is the recommended way to get -Django into production. - -.. _Apache: http://httpd.apache.org/ -.. _mod_wsgi: http://code.google.com/p/modwsgi/ - -mod_wsgi is an Apache module which can be used to host any Python application -which supports the `Python WSGI interface`_, including Django. Django will work -with any version of Apache which supports mod_wsgi. - -.. _python wsgi interface: http://www.python.org/dev/peps/pep-0333/ - -The `official mod_wsgi documentation`_ is fantastic; it's your source for all -the details about how to use mod_wsgi. You'll probably want to start with the -`installation and configuration documentation`_. - -.. _official mod_wsgi documentation: http://code.google.com/p/modwsgi/ -.. _installation and configuration documentation: http://code.google.com/p/modwsgi/wiki/InstallationInstructions - -Basic Configuration -=================== - -Once you've got mod_wsgi installed and activated, edit your ``httpd.conf`` file -and add:: - - WSGIScriptAlias / /path/to/mysite/apache/django.wsgi - -The first bit above is the url you want to be serving your application at (``/`` -indicates the root url), and the second is the location of a "WSGI file" -- see -below -- on your system, usually inside of your project. This tells Apache -to serve any request below the given URL using the WSGI application defined by that file. - -Next we'll need to actually create this WSGI application, so create the file -mentioned in the second part of ``WSGIScriptAlias`` and add:: - - import os - import sys - - os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' - - import django.core.handlers.wsgi - application = django.core.handlers.wsgi.WSGIHandler() - -If your project is not on your ``PYTHONPATH`` by default you can add:: - - path = '/usr/local/django' - if path not in sys.path: - sys.path.append(path) - -just above the final ``import`` line to place your project on the path. Remember to -replace 'mysite.settings' with your correct settings file, and '/usr/local/django' -with your own project's location. - -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_ - * Nginx_ - * TUX_ - * A stripped-down version of Apache_ - * Cherokee_ - -If, however, you have no option but to serve media files on the same Apache -``VirtualHost`` as Django, you can set up Apache to serve some URLs as -static media, and others using the mod_wsgi interface to Django. - -This example sets up Django at the site root, but explicitly serves ``robots.txt``, -``favicon.ico``, any CSS file, and anything in the ``/media/`` URL space as a static -file. All other URLs will be served using mod_wsgi:: - - Alias /robots.txt /usr/local/wsgi/static/robots.txt - Alias /favicon.ico /usr/local/wsgi/static/favicon.ico - - AliasMatch /([^/]*\.css) /usr/local/wsgi/static/styles/$1 - - Alias /media/ /usr/local/wsgi/static/media/ - - <Directory /usr/local/wsgi/static> - Order deny,allow - Allow from all - </Directory> - - WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi - - <Directory /usr/local/wsgi/scripts> - Order allow,deny - Allow from all - </Directory> - -.. _lighttpd: http://www.lighttpd.net/ -.. _Nginx: http://wiki.nginx.org/Main -.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server -.. _Apache: http://httpd.apache.org/ -.. _Cherokee: http://www.cherokee-project.com/ - -More details on configuring a mod_wsgi site to serve static files can be found -in the mod_wsgi documentation on `hosting static files`_. - -.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files - -Details -======= - -For more details, see the `mod_wsgi documentation on Django integration`_, -which explains the above in more detail, and walks through all the various -options you've got when deploying under mod_wsgi. - -.. _mod_wsgi documentation on Django integration: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango diff --git a/parts/django/docs/howto/error-reporting.txt b/parts/django/docs/howto/error-reporting.txt deleted file mode 100644 index 9c61c97..0000000 --- a/parts/django/docs/howto/error-reporting.txt +++ /dev/null @@ -1,78 +0,0 @@ -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 e-mail you details of those errors. - -Server errors -------------- - -When :setting:`DEBUG` is ``False``, Django will e-mail the users listed in the -:setting:`ADMINS` 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. - -.. note:: - - In order to send e-mail, Django requires a few settings telling it - how to connect to your mail server. At the very least, you'll need - to specify :setting:`EMAIL_HOST` and possibly - :setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD`, - though other settings may be also required depending on your mail - server's configuration. Consult :doc:`the Django settings - documentation </ref/settings>` for a full list of email-related - settings. - -By default, Django will send e-mail from root@localhost. However, some mail -providers reject all e-mail from this address. To use a different sender -address, modify the :setting:`SERVER_EMAIL` setting. - -To disable this behavior, just remove all entries from the :setting:`ADMINS` -setting. - -404 errors ----------- - -Django can also be configured to e-mail errors about broken links (404 "page -not found" errors). Django sends e-mails 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``. diff --git a/parts/django/docs/howto/i18n.txt b/parts/django/docs/howto/i18n.txt deleted file mode 100644 index 64b33d7..0000000 --- a/parts/django/docs/howto/i18n.txt +++ /dev/null @@ -1,103 +0,0 @@ -.. _using-translations-in-your-own-projects: - -=============================================== -Using internationalization in your own projects -=============================================== - -At runtime, Django looks for translations by following this algorithm: - - * First, it looks for a ``locale`` directory in the directory containing - your settings file. - * Second, it looks for a ``locale`` directory in the project directory. - * Third, it looks for a ``locale`` directory in each of the installed apps. - It does this in the reverse order of INSTALLED_APPS - * Finally, it checks the Django-provided base translation in - ``django/conf/locale``. - -In all cases the name of the directory containing the translation is expected to -be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, -etc. - -This way, you can write applications that include their own translations, and -you can override base translations in your project path. Or, you can just build -a big project out of several apps and put all translations into one big project -message file. The choice is yours. - -.. note:: - - If you're using manually configured settings, as described in - :ref:`settings-without-django-settings-module`, the ``locale`` directory in - the project directory will not be examined, since Django loses the ability - to work out the location of the project directory. (Django normally uses the - location of the settings file to determine this, and a settings file doesn't - exist if you're manually configuring your settings.) - -All message file repositories are structured the same way. They are: - - * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` - * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` - * All paths listed in ``LOCALE_PATHS`` in your settings file are - searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` - * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` - -To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>` -tool. You only need to be in the same directory where the ``locale/`` directory -is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>` -to produce the binary ``.mo`` files that are used by ``gettext``. Read the -:doc:`/topics/i18n/localization` document for more details. - -You can also run ``django-admin.py compilemessages --settings=path.to.settings`` -to make the compiler process all the directories in your :setting:`LOCALE_PATHS` -setting. - -Application message files are a bit complicated to discover -- they need the -:class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the -middleware, only the Django message files and project message files will be -installed and available at runtime. - -Finally, you should give some thought to the structure of your translation -files. If your applications need to be delivered to other users and will -be used in other projects, you might want to use app-specific translations. -But using app-specific translations and project translations could produce -weird problems with ``makemessages``: It will traverse all directories below -the current path and so might put message IDs into the project message file -that are already in application message files. - -The easiest way out is to store applications that are not part of the project -(and so carry their own translations) outside the project tree. That way, -``django-admin.py makemessages`` on the project level will only translate -strings that are connected to your explicit project and not strings that are -distributed independently. - -Using translations outside views and templates -============================================== - -While Django provides a rich set of i18n tools for use in views and templates, -it does not restrict the usage to Django-specific code. The Django translation -mechanisms can be used to translate arbitrary texts to any language that is -supported by Django (as long as an appropriate translation catalog exists, of -course). You can load a translation catalog, activate it and translate text to -language of your choice, but remember to switch back to original language, as -activating a translation catalog is done on per-thread basis and such change -will affect code running in the same thread. - -For example:: - - from django.utils import translation - def welcome_translated(language): - cur_language = translation.get_language() - try: - translation.activate(language) - text = translation.ugettext('welcome') - finally: - translation.activate(cur_language) - return text - -Calling this function with the value 'de' will give you ``"Willkommen"``, -regardless of :setting:`LANGUAGE_CODE` and language set by middleware. - -Functions of particular interest are ``django.utils.translation.get_language()`` -which returns the language used in the current thread, -``django.utils.translation.activate()`` which activates a translation catalog -for the current thread, and ``django.utils.translation.check_for_language()`` -which checks if the given language is supported by Django. diff --git a/parts/django/docs/howto/index.txt b/parts/django/docs/howto/index.txt deleted file mode 100644 index 49d0644..0000000 --- a/parts/django/docs/howto/index.txt +++ /dev/null @@ -1,34 +0,0 @@ -"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 -:doc:`/topics/index` and the :doc:`/ref/index`. However, these guides will help -you quickly accomplish common tasks. - -.. toctree:: - :maxdepth: 1 - - apache-auth - auth-remote-user - custom-management-commands - custom-model-fields - custom-template-tags - custom-file-storage - deployment/index - error-reporting - initial-data - i18n - jython - 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/ diff --git a/parts/django/docs/howto/initial-data.txt b/parts/django/docs/howto/initial-data.txt deleted file mode 100644 index cf3f65d..0000000 --- a/parts/django/docs/howto/initial-data.txt +++ /dev/null @@ -1,142 +0,0 @@ -================================= -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 <dumpdata>` command. -Or, you can write fixtures by hand; fixtures can be written as XML, YAML, or -JSON documents. The :doc:`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: 2 - fields: - first_name: Paul - last_name: McCartney - -You'll store this data in a ``fixtures`` directory inside your 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 then 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/yaml/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 :doc:`manage.py -</ref/django-admin>`. Refer to the :doc:`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 last part of the module name provided for the -:setting:`ENGINE` in your settings file (e.g., if you have defined a -database with an :setting:`ENGINE` value of -``django.db.backends.postgresql``, Django will look for -``<appname>/sql/<modelname>.postgresql.sql``). - -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``. diff --git a/parts/django/docs/howto/jython.txt b/parts/django/docs/howto/jython.txt deleted file mode 100644 index 1bf8d6c..0000000 --- a/parts/django/docs/howto/jython.txt +++ /dev/null @@ -1,73 +0,0 @@ -======================== -Running Django on Jython -======================== - -.. index:: Jython, Java, JVM - -Jython_ is an implementation of Python that runs on the Java platform (JVM). -Django runs cleanly on Jython version 2.5 or later, which means you can deploy -Django on any Java platform. - -This document will get you up and running with Django on top of Jython. - -.. _jython: http://www.jython.org/ - -Installing Jython -================= - -Django works with Jython versions 2.5b3 and higher. Download Jython at -http://www.jython.org/. - -Creating a servlet container -============================ - -If you just want to experiment with Django, skip ahead to the next section; -Django includes a lightweight Web server you can use for testing, so you won't -need to set up anything else until you're ready to deploy Django in production. - -If you want to use Django on a production site, use a Java servlet container, -such as `Apache Tomcat`_. Full JavaEE applications servers such as `GlassFish`_ -or `JBoss`_ are also OK, if you need the extra features they include. - -.. _`Apache Tomcat`: http://tomcat.apache.org/ -.. _GlassFish: https://glassfish.dev.java.net/ -.. _JBoss: http://www.jboss.org/ - -Installing Django -================= - -The next step is to install Django itself. This is exactly the same as -installing Django on standard Python, so see -:ref:`removing-old-versions-of-django` and :ref:`install-django-code` for -instructions. - -Installing Jython platform support libraries -============================================ - -The `django-jython`_ project contains database backends and management commands -for Django/Jython development. Note that the builtin Django backends won't work -on top of Jython. - -.. _`django-jython`: http://code.google.com/p/django-jython/ - -To install it, follow the `installation instructions`_ detailed on the project -Web site. Also, read the `database backends`_ documentation there. - -.. _`installation instructions`: http://code.google.com/p/django-jython/wiki/Install -.. _`database backends`: http://code.google.com/p/django-jython/wiki/DatabaseBackends - -Differences with Django on Jython -================================= - -.. index:: JYTHONPATH - -At this point, Django on Jython should behave nearly identically to Django -running on standard Python. However, are a few differences to keep in mind: - - * Remember to use the ``jython`` command instead of ``python``. The - documentation uses ``python`` for consistancy, but if you're using Jython - you'll want to mentally replace ``python`` with ``jython`` every time it - occurs. - - * Similarly, you'll need to use the ``JYTHONPATH`` environment variable - instead of ``PYTHONPATH``. diff --git a/parts/django/docs/howto/legacy-databases.txt b/parts/django/docs/howto/legacy-databases.txt deleted file mode 100644 index 2121871..0000000 --- a/parts/django/docs/howto/legacy-databases.txt +++ /dev/null @@ -1,66 +0,0 @@ -========================================= -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 -:doc:`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 the :setting:`DATABASES` -setting and assigning values to the following keys for the ``'default'`` -connection: - - * :setting:`NAME` - * :setting:`ENGINE` - * :setting:`USER` - * :setting:`PASSWORD` - * :setting:`HOST` - * :setting:`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. diff --git a/parts/django/docs/howto/outputting-csv.txt b/parts/django/docs/howto/outputting-csv.txt deleted file mode 100644 index 46e111d..0000000 --- a/parts/django/docs/howto/outputting-csv.txt +++ /dev/null @@ -1,137 +0,0 @@ -========================== -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://docs.python.org/library/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. - -Handling Unicode -~~~~~~~~~~~~~~~~ - -Python's ``csv`` module does not support Unicode input. Since Django uses -Unicode internally this means strings read from sources such as -:class:`~django.http.HttpRequest` are potentially problematic. There are a few -options for handling this: - - * Manually encode all Unicode objects to a compatible encoding. - - * Use the ``UnicodeWriter`` class provided in the `csv module's examples - section`_. - - * Use the `python-unicodecsv module`_, which aims to be a drop-in - replacement for ``csv`` that gracefully handles Unicode. - -For more information, see the Python `CSV File Reading and Writing`_ -documentation. - -.. _`csv module's examples section`: http://docs.python.org/library/csv.html#examples -.. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv -.. _`CSV File Reading and Writing`: http://docs.python.org/library/csv.html - -Using the template system -========================= - -Alternatively, you can use the :doc:`Django template system </topics/templates>` -to generate CSV. This is lower-level than using the convenient Python ``csv`` -module, 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 :doc:`/howto/outputting-pdf` for an example. diff --git a/parts/django/docs/howto/outputting-pdf.txt b/parts/django/docs/howto/outputting-pdf.txt deleted file mode 100644 index 67950d0..0000000 --- a/parts/django/docs/howto/outputting-pdf.txt +++ /dev/null @@ -1,160 +0,0 @@ -=========================== -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/oss/rl-toolkit/ -.. _kusports.com: http://www.kusports.com/ - -Install ReportLab -================= - -Download and install the ReportLab library from http://www.reportlab.org/oss/rl-toolkit/download/. -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/reportlab-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``:: - - # Fall back to StringIO in environments where cStringIO is not available - try: - from cStringIO import StringIO - except ImportError: - from StringIO 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://docs.python.org/library/stringio.html#module-cStringIO - -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 XHTML2PDF`_ 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. - -.. _PDFlib: http://www.pdflib.org/ -.. _`Pisa XHTML2PDF`: http://www.xhtml2pdf.com/ -.. _HTMLdoc: http://www.htmldoc.org/ - -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 -:doc:`/howto/outputting-csv` for another example and some techniques you can use -when generated text-based formats. diff --git a/parts/django/docs/howto/static-files.txt b/parts/django/docs/howto/static-files.txt deleted file mode 100644 index c3692d5..0000000 --- a/parts/django/docs/howto/static-files.txt +++ /dev/null @@ -1,162 +0,0 @@ -========================= -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_, lighttpd_ and -Cherokee_, 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/ -.. _Cherokee: http://www.cherokee-project.com/ - -.. seealso:: - - If you just need to serve the admin media from a nonstandard location, see - the :djadminopt:`--adminmedia` parameter to :djadmin:`runserver`. - -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 :doc:`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. - -Of course, it's not compulsory to use a fixed string for the -``'document_root'`` value. You might wish to make that an entry in your -settings file and use the setting value there. That will allow you and -other developers working on the code to easily change the value as -required. For example, if we have a line in ``settings.py`` that says:: - - STATIC_DOC_ROOT = '/path/to/media' - -...we could write the above :doc:`URLconf </topics/http/urls>` entry as:: - - from django.conf import settings - ... - (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', - {'document_root': settings.STATIC_DOC_ROOT}), - -Be careful not to use the same path as your :setting:`ADMIN_MEDIA_PREFIX` (which defaults -to ``/media/``) as this will overwrite your URLconf entry. - -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.html`` 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> - -.. versionchanged:: 1.0.3 - Prior to Django 1.0.3, there was a bug in the view that provided directory - listings. The template that was loaded had to be called - ``static/directory_listing`` (with no ``.html`` extension). For backwards - compatibility with earlier versions, Django will still load templates with - the older (no extension) name, but it will prefer the - ``directory_index.html`` version. - -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. |