diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/add_ons.txt | 45 | ||||
| -rw-r--r-- | docs/authentication.txt | 54 | ||||
| -rw-r--r-- | docs/db-api.txt | 2 | ||||
| -rw-r--r-- | docs/django-admin.txt | 49 | ||||
| -rw-r--r-- | docs/generic_views.txt | 97 | ||||
| -rw-r--r-- | docs/i18n.txt | 11 | ||||
| -rw-r--r-- | docs/install.txt | 14 | ||||
| -rw-r--r-- | docs/middleware.txt | 8 | ||||
| -rw-r--r-- | docs/model-api.txt | 106 | ||||
| -rw-r--r-- | docs/settings.txt | 78 | ||||
| -rw-r--r-- | docs/sites.txt | 311 | ||||
| -rw-r--r-- | docs/templates_python.txt | 196 | ||||
| -rw-r--r-- | docs/tutorial01.txt | 32 |
13 files changed, 915 insertions, 88 deletions
diff --git a/docs/add_ons.txt b/docs/add_ons.txt index 28df4f55b6..f7b3056ef0 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -16,11 +16,35 @@ The automatic Django administrative interface. For more information, see .. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/ +auth +==== + +Django's authentication framework. + +See the `authentication documentation`_. + +.. _authentication documentation: http://www.djangoproject.com/documentation/authentication/ + comments ======== A simple yet flexible comments system. This is not yet documented. +contenttypes +============ + +A light framework for hooking into "types" of content, where each installed +Django model is a separate content type. This is not yet documented. + +csrf +==== + +A middleware for preventing Cross Site Request Forgeries + +See the `csrf documentation`_. + +.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/ + flatpages ========= @@ -48,6 +72,17 @@ See the `redirects documentation`_. .. _redirects documentation: http://www.djangoproject.com/documentation/redirects/ +sites +===== + +A light framework that lets you operate multiple Web sites off of the same +database and Django installation. It gives you hooks for associating objects to +one or more sites. + +See the `sites documentation`_. + +.. _sites documentation: http://www.djangoproject.com/documentation/sites/ + syndication =========== @@ -57,16 +92,6 @@ See the `syndication documentation`_. .. _syndication documentation: http://www.djangoproject.com/documentation/syndication/ -csrf -==== - -A middleware for preventing Cross Site Request Forgeries - -See the `csrf documentation`_. - -.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/ - - Other add-ons ============= diff --git a/docs/authentication.txt b/docs/authentication.txt index 8e416c3e9e..1be64c045a 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -338,6 +338,60 @@ introduced in Python 2.4:: * If the user is logged in, execute the view normally. The view code is free to assume the user is logged in. +Note that you'll need to map the appropriate Django view to ``/accounts/login/``. +To do this, add the following line to your URLconf:: + + (r'^accounts/login/$', 'django.contrib.auth.views.login'), + +Here's what ``django.contrib.auth.views.login`` does:: + + * If called via ``GET``, it displays a login form that POSTs to the same + URL. More on this in a bit. + + * If called via ``POST``, it tries to log the user in. If login is + successful, the view redirects to the URL specified in ``next``. If + ``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is + currently hard-coded). If login isn't successful, it redisplays the login + form. + +It's your responsibility to provide the login form in a template called +``registration/login.html``. This template gets passed three template context +variables: + + * ``form``: A ``FormWrapper`` object representing the login form. See the + `forms documentation`_ for more on ``FormWrapper`` objects. + * ``next``: The URL to redirect to after successful login. This may contain + a query string, too. + * ``site_name``: The name of the current ``Site``, according to the + ``SITE_ID`` setting. See the `site framework docs`_. + +Here's a sample ``registration/login.html`` template you can use as a starting +point. It assumes you have a ``base.html`` template that defines a ``content`` +block:: + + {% extends "base.html" %} + + {% block content %} + + {% if form.has_errors %} + <p>Your username and password didn't match. Please try again.</p> + {% endif %} + + <form method="post" action="."> + <table> + <tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr> + <tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr> + </table> + + <input type="submit" value="login" /> + <input type="hidden" name="next" value="{{ next }}" /> + </form> + + {% endblock %} + +.. _forms documentation: http://www.djangoproject.com/documentation/forms/ +.. _site framework docs: http://www.djangoproject.com/documentation/sites/ + Limiting access to logged-in users that pass a test --------------------------------------------------- diff --git a/docs/db-api.txt b/docs/db-api.txt index e2173afe16..4442a75125 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -345,7 +345,7 @@ This is roughly equivalent to:: Entry.objects.order_by('headline')[0:1].get() -Note, however, that the first of these will raise ``IndexError`` while the +Note, however, that the first of these will raise ``IndexError`` while the second will raise ``DoesNotExist`` if no objects match the given criteria. QuerySet methods that return new QuerySets diff --git a/docs/django-admin.txt b/docs/django-admin.txt index b314366fee..90f5f5e4ed 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -177,6 +177,16 @@ Port 7000 on IP address 1.2.3.4:: django-admin.py runserver 1.2.3.4:7000 +Serving static files with the development server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, the development server doesn't serve any static files for your site +(such as CSS files, images, things under ``MEDIA_ROOT_URL`` and so forth). If +you want to configure Django to serve static media, read the `serving static files`_ +documentation. + +.. _serving static files: http://www.djangoproject.com/documentation/static_files/ + shell ----- @@ -200,6 +210,9 @@ sqlall [appname appname ...] Prints the CREATE TABLE and initial-data SQL statements for the given appnames. +Refer to the description of ``sqlinitialdata`` for an explanation of how to +specify initial data. + sqlclear [appname appname ...] -------------------------------------- @@ -215,6 +228,18 @@ sqlinitialdata [appname appname ...] Prints the initial INSERT SQL statements for the given appnames. +For each model in each specified app, this command looks for the file +``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and +``<modelname>`` is the model's name in lowercase. For example, if you have an +app ``news`` that includes a ``Story`` model, ``sqlinitialdata`` will attempt +to read a file ``news/sql/story.sql`` and append it to the output of this +command. + +Each of the SQL files, if given, is expected to contain valid SQL. The SQL +files are piped directly into the database after all of the models' +table-creation statements have been executed. Use this SQL hook to populate +tables with any necessary initial records, SQL functions or test data. + sqlreset [appname appname ...] -------------------------------------- @@ -240,6 +265,20 @@ startproject [projectname] Creates a Django project directory structure for the given project name in the current directory. +syncdb +------ + +Creates the database tables for all apps in ``INSTALLED_APPS`` whose tables +have not already been created. + +Use this command when you've added new applications to your project and want to +install them in the database. This includes any apps shipped with Django that +might be in ``INSTALLED_APPS`` by default. When you start a new project, run +this command to install the default apps. + +If you're installing the ``django.contrib.auth`` application, ``syncdb`` will +give you the option of creating a superuser immediately. + validate -------- @@ -286,6 +325,16 @@ setting the Python path for you. Displays a help message that includes a terse list of all available actions and options. +--version +--------- + +Displays the current Django version. + +Example output:: + + 0.9.1 + 0.9.1 (SVN) + Extra niceties ============== diff --git a/docs/generic_views.txt b/docs/generic_views.txt index 597ef96104..5b978af1de 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -62,6 +62,15 @@ Most generic views require the ``queryset`` key, which is a ``QuerySet`` instance; see the `database API docs`_ for more information about ``Queryset`` objects. +Most views also take an optional ``extra_context`` dictionary that you can use +to pass any auxiliary information you wish to the view. The values in the +``extra_context`` dictionary can be either functions (or other callables) or +other objects. Functions are evaluated just before they are passed to the +template. However, note that QuerySets retrieve and cache their data when they +are first evaluated, so if you want to pass in a QuerySet via +``extra_context`` that is always fresh you need to wrap it in a function or +lambda that returns the QuerySet. + .. _database API docs: http://www.djangoproject.com/documentation/db_api/ "Simple" generic views @@ -160,10 +169,10 @@ a date in the *future* are not included. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -225,10 +234,10 @@ with a date in the *future* are not displayed. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -287,10 +296,10 @@ date in the *future* are not displayed. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -360,10 +369,10 @@ in the *future* are not displayed. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -436,10 +445,10 @@ a 404 error, regardless of whether any objects exist for future days. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -543,10 +552,10 @@ A page representing an individual object. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``context_processors``: A list of template-context processors to apply to the view's template. See the `RequestContext docs`_. @@ -600,10 +609,10 @@ A page representing a list of objects. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``allow_empty``: A boolean specifying whether to display the page if no objects are available. If this is ``False`` and no objects are available, @@ -697,10 +706,10 @@ A page representing an individual object. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``context_processors``: A list of template-context processors to apply to the view's template. See the `RequestContext docs`_. @@ -764,10 +773,10 @@ automatic manipulators that come with Django models. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``context_processors``: A list of template-context processors to apply to the view's template. See the `RequestContext docs`_. @@ -843,10 +852,10 @@ object. This uses the automatic manipulators that come with Django models. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``context_processors``: A list of template-context processors to apply to the view's template. See the `RequestContext docs`_. @@ -924,10 +933,10 @@ contain a form that POSTs to the same URL. * ``template_loader``: The template loader to use when loading the template. By default, it's ``django.template.loader``. - * ``extra_context``: A dictionary of values to add to the template context. - If a value in the dictionary is callable, the generic view will call it - just before rendering the template. By default, this is an empty - dictionary. + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. * ``context_processors``: A list of template-context processors to apply to the view's template. See the `RequestContext docs`_. diff --git a/docs/i18n.txt b/docs/i18n.txt index 9199a74295..e6660f939d 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -540,6 +540,17 @@ 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 the + `settings documentation`_, 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.) + +.. _settings documentation: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable + All message file repositories are structured the same way. They are: * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` diff --git a/docs/install.txt b/docs/install.txt index 51746e001d..800c49b596 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -77,9 +77,9 @@ It's easy either way. Installing the official version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. Download Django-0.92.tar.gz from our `download page`_. -2. ``tar xzvf Django-0.92.tar.gz`` -3. ``cd Django-0.92`` +1. Download Django-0.91.tar.gz from our `download page`_. +2. ``tar xzvf Django-0.91.tar.gz`` +3. ``cd Django-0.91`` 4. ``sudo python setup.py install`` Note that the last command will automatically download and install setuptools_ @@ -89,6 +89,14 @@ connection. This will install Django in your Python installation's ``site-packages`` directory. +.. note:: + + Due to recent backwards-incompatible changes, it is strongly recommended + that you use the development version (below) for any new applications or + if you are just starting to work with Django. The 0.91 release is a + dead-end branch that is primarily of use for supporting legacy Django + applications. + .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools Installing the development version diff --git a/docs/middleware.txt b/docs/middleware.txt index 7dfa0f3af7..f3dbcb82d1 100644 --- a/docs/middleware.txt +++ b/docs/middleware.txt @@ -59,8 +59,12 @@ Adds a few conveniences for perfectionists: * Performs URL rewriting based on the ``APPEND_SLASH`` and ``PREPEND_WWW`` settings. If ``APPEND_SLASH`` is ``True``, URLs that lack a trailing - slash will be redirected to the same URL with a trailing slash. If - ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be + slash will be redirected to the same URL with a trailing slash, unless the + last component in the path contains a period. So ``foo.com/bar`` is + redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed + through unchanged. + + If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be redirected to the same URL with a leading "www." Both of these options are meant to normalize URLs. The philosophy is that diff --git a/docs/model-api.txt b/docs/model-api.txt index 6d6249ee88..3e40a6f63f 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -202,22 +202,22 @@ Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few steps: 1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the - full path to a directory where you'd like Django to store uploaded - files. (For performance, these files are not stored in the database.) - Define ``MEDIA_URL`` as the base public URL of that directory. Make - sure that this directory is writable by the Web server's user - account. + full path to a directory where you'd like Django to store uploaded + files. (For performance, these files are not stored in the database.) + Define ``MEDIA_URL`` as the base public URL of that directory. Make + sure that this directory is writable by the Web server's user + account. 2. Add the ``FileField`` or ``ImageField`` to your model, making sure - to define the ``upload_to`` option to tell Django to which - subdirectory of ``MEDIA_ROOT`` it should upload files. + to define the ``upload_to`` option to tell Django to which + subdirectory of ``MEDIA_ROOT`` it should upload files. 3. All that will be stored in your database is a path to the file - (relative to ``MEDIA_ROOT``). You'll must likely want to use the - convenience ``get_<fieldname>_url`` function provided by Django. For - example, if your ``ImageField`` is called ``mug_shot``, you can get - the absolute URL to your image in a template with ``{{ - object.get_mug_shot_url }}``. + (relative to ``MEDIA_ROOT``). You'll must likely want to use the + convenience ``get_<fieldname>_url`` function provided by Django. For + example, if your ``ImageField`` is called ``mug_shot``, you can get + the absolute URL to your image in a template with ``{{ + object.get_mug_shot_url }}``. .. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 @@ -1599,6 +1599,39 @@ API. See `Other lookup options`_. .. _Python DB-API: http://www.python.org/peps/pep-0249.html .. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables +Overriding default model methods +-------------------------------- + +As explained in the `database API docs`_, each model gets a few methods +automatically -- most notably, ``save()`` and ``delete()``. You can override +these methods to alter behavior. + +A classic use-case for overriding the built-in methods is if you want something +to happen whenever you save an object. For example:: + + class Blog(models.Model): + name = models.CharField(maxlength=100) + tagline = models.TextField() + + def save(self): + do_something() + super(Blog, self).save() # Call the "real" save() method. + do_something_else() + +You can also prevent saving:: + + class Blog(models.Model): + name = models.CharField(maxlength=100) + tagline = models.TextField() + + def save(self): + if self.name == "Yoko Ono's blog": + return # Yoko shall never have her own blog! + else: + super(Blog, self).save() # Call the "real" save() method. + +.. _database API docs: http://www.djangoproject.com/documentation/db_api/ + Models across files =================== @@ -1631,3 +1664,52 @@ read, in part:: 'mysite.myapp', #... ) + +Providing initial SQL data +========================== + +Django provides a hook for passing the database arbitrary SQL that's executed +just after the CREATE TABLE statements. Use this hook, for example, if you want +to populate default records, or create SQL functions, automatically. + +The hook is simple: Django just looks for a file called +``<appname>/sql/<modelname>.sql``, where ``<appname>`` is your app directory and +``<modelname>`` is the model's name in lowercase. + +In the ``Person`` example model at the top of this document, assuming it lives +in an app called ``myapp``, you could add arbitrary SQL to the file +``myapp/sql/person.sql``. Here's an example of what the file might contain:: + + 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. The SQL files are +piped directly into the database after all of the models' table-creation +statements have been executed. + +The SQL files are read by the ``sqlinitialdata``, ``sqlreset``, ``sqlall`` and +``reset`` commands in ``manage.py``. Refer to the `manage.py documentation`_ +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. + +.. _`manage.py documentation`: http://www.djangoproject.com/documentation/django_admin/#sqlinitialdata-appname-appname + +Database-backend-specific SQL data +---------------------------------- + +There's also a hook for backend-specific SQL data. For example, you can have +separate initial-data files for PostgreSQL and MySQL. For each app, Django +looks for a file called ``<appname>/sql/<modelname>.<backend>.sql``, where +``<appname>`` is your app directory, ``<modelname>`` is the model's name in +lowercase and ``<backend>`` is the value of ``DATABASE_ENGINE`` in your +settings file (e.g., ``postgresql``, ``mysql``). + +Backend-specific SQL data is executed before non-backend-specific SQL data. For +example, if your app contains the files ``sql/person.sql`` and +``sql/person.postgresql.sql`` and you're installing the app on PostgreSQL, +Django will execute the contents of ``sql/person.postgresql.sql`` first, then +``sql/person.sql``. diff --git a/docs/settings.txt b/docs/settings.txt index d4666468fc..80000fad5b 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -619,6 +619,10 @@ The ID, as an integer, of the current site in the ``django_site`` database table. This is used so that application data can hook into specific site(s) and a single database can manage content for multiple sites. +See the `site framework docs`_. + +.. _site framework docs: http://www.djangoproject.com/documentation/sites/ + TEMPLATE_CONTEXT_PROCESSORS --------------------------- @@ -724,3 +728,77 @@ Django apps. Just follow these conventions: * For settings that are sequences, use tuples instead of lists. This is purely for performance. * Don't reinvent an already-existing setting. + +Using settings without setting DJANGO_SETTINGS_MODULE +===================================================== + +In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE`` +environment variable. For example, if you're using the template system by +itself, you likely don't want to have to set up an environment variable +pointing to a settings module. + +In these cases, you can configure Django's settings manually. Do this by +calling ``django.conf.settings.configure()``. + +Example:: + + from django.conf import settings + + settings.configure(DEBUG=True, TEMPLATE_DEBUG=True, + TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base')) + +Pass ``configure()`` as many keyword arguments as you'd like, with each keyword +argument representing a setting and its value. Each argument name should be all +uppercase, with the same name as the settings described above. If a particular +setting is not passed to ``configure()`` and is needed at some later point, +Django will use the default setting value. + +Custom default settings +----------------------- + +If you'd like default values to come from somewhere other than +``django.conf.global_settings``, you can pass in a module or class that +provides the default settings as the ``default_settings`` argument (or as the +first positional argument) in the call to ``configure()``. + +In this example, default settings are taken from ``myapp_defaults``, and the +``DEBUG`` setting is set to ``True``, regardless of its value in +``myapp_defaults``:: + + from django.conf import settings + from myapp import myapp_defaults + + settings.configure(default_settings=myapp_defaults, DEBUG=True) + +The following example, which uses ``myapp_defaults`` as a positional argument, +is equivalent:: + + settings.configure(myapp_defaults, DEBUG = True) + +Normally, you will not need to override the defaults in this fashion. The +Django defaults are sufficiently tame that you can safely use them. Be aware +that if you do pass in a new default module, it entirely *replaces* the Django +defaults, so you must specify a value for every possible setting that might be +used in that code you are importing. Check in +``django.conf.settings.global_settings`` for the full list. + +Either configure() or DJANGO_SETTINGS_MODULE is required +-------------------------------------------------------- + +If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you +*must* call ``configure()`` at some point before using any code that reads +settings. + +If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``, +Django will raise an ``EnvironmentError`` exception the first time a setting +is accessed. + +If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then* +call ``configure()``, Django will raise an ``EnvironmentError`` saying settings +have already been configured. + +Also, it's an error to call ``configure()`` more than once, or to call +``configure()`` after any setting has been accessed. + +It boils down to this: Use exactly one of either ``configure()`` or +``DJANGO_SETTINGS_MODULE``. Not both, and not neither. diff --git a/docs/sites.txt b/docs/sites.txt new file mode 100644 index 0000000000..51f57afe4f --- /dev/null +++ b/docs/sites.txt @@ -0,0 +1,311 @@ +===================== +The "sites" framework +===================== + +Django comes with an optional "sites" framework. It's a hook for associating +objects and functionality to particular Web sites, and it's a holding place for +the domain names and "verbose" names of your Django-powered sites. + +Use it if your single Django installation powers more than one site and you +need to differentiate between those sites in some way. + +The whole sites framework is based on two simple concepts: + + * The ``Site`` model, found in ``django.contrib.sites``, has ``domain`` and + ``name`` fields. + * The ``SITE_ID`` setting specifies the database ID of the ``Site`` object + associated with that particular settings file. + +How you use this is up to you, but Django uses it in a couple of ways +automatically via simple conventions. + +Example usage +============= + +Why would you use sites? It's best explained through examples. + +Associating content with multiple sites +--------------------------------------- + +The Django-powered sites LJWorld.com_ and Lawrence.com_ are operated by the +same news organization -- the Lawrence Journal-World newspaper in Lawrence, +Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local +entertainment. But sometimes editors want to publish an article on *both* +sites. + +The brain-dead way of solving the problem would be to require site producers to +publish the same story twice: once for LJWorld.com and again for Lawrence.com. +But that's inefficient for site producers, and it's redundant to store +multiple copies of the same story in the database. + +The better solution is simple: Both sites use the same article database, and an +article is associated with one or more sites. In Django model terminology, +that's represented by a ``ManyToManyField`` in the ``Article`` model:: + + from django.db import models + from django.contrib.sites.models import Site + + class Article(models.Model): + headline = models.CharField(maxlength=200) + # ... + sites = models.ManyToManyField(Site) + +This accomplishes several things quite nicely: + + * It lets the site producers edit all content -- on both sites -- in a + single interface (the Django admin). + + * It means the same story doesn't have to be published twice in the + database; it only has a single record in the database. + + * It lets the site developers use the same Django view code for both sites. + The view code that displays a given story just checks to make sure the + requested story is on the current site. It looks something like this:: + + from django.conf import settings + + def article_detail(request, article_id): + try: + a = Article.objects.get(id=article_id, sites__id__exact=settings.SITE_ID) + except Article.DoesNotExist: + raise Http404 + # ... + +.. _ljworld.com: http://www.ljworld.com/ +.. _lawrence.com: http://www.lawrence.com/ + +Associating content with a single site +-------------------------------------- + +Similarly, you can associate a model to the ``Site`` model in a many-to-one +relationship, using ``ForeignKey``. + +For example, if an article is only allowed on a single site, you'd use a model +like this:: + + from django.db import models + from django.contrib.sites.models import Site + + class Article(models.Model): + headline = models.CharField(maxlength=200) + # ... + site = models.ForeignKey(Site) + +This has the same benefits as described in the last section. + +Hooking into the current site from views +---------------------------------------- + +On a lower level, you can use the sites framework in your Django views to do +particular things based on what site in which the view is being called. +For example:: + + from django.conf import settings + + def my_view(request): + if settings.SITE_ID == 3: + # Do something. + else: + # Do something else. + +Of course, it's ugly to hard-code the site IDs like that. This sort of +hard-coding is best for hackish fixes that you need done quickly. A slightly +cleaner way of accomplishing the same thing is to check the current site's +domain:: + + from django.conf import settings + from django.contrib.sites.models import Site + + def my_view(request): + current_site = Site.objects.get(id=settings.SITE_ID) + if current_site.domain == 'foo.com': + # Do something + else: + # Do something else. + +The idiom of retrieving the ``Site`` object for the value of +``settings.SITE_ID`` is quite common, so the ``Site`` model's manager has a +``get_current()`` method. This example is equivalent to the previous one:: + + from django.contrib.sites.models import Site + + def my_view(request): + current_site = Site.objects.get_current() + if current_site.domain == 'foo.com': + # Do something + else: + # Do something else. + +Getting the current domain for display +-------------------------------------- + +LJWorld.com and Lawrence.com both have e-mail alert functionality, which lets +readers sign up to get notifications when news happens. It's pretty basic: A +reader signs up on a Web form, and he immediately gets an e-mail saying, +"Thanks for your subscription." + +It'd be inefficient and redundant to implement this signup-processing code +twice, so the sites use the same code behind the scenes. But the "thank you for +signing up" notice needs to be different for each site. By using ``Site`` +objects, we can abstract the "thank you" notice to use the values of the +current site's ``name`` and ``domain``. + +Here's an example of what the form-handling view looks like:: + + from django.contrib.sites.models import Site + from django.core.mail import send_mail + + def register_for_newsletter(request): + # Check form values, etc., and subscribe the user. + # ... + + current_site = Site.objects.get_current() + send_mail('Thanks for subscribing to %s alerts' % current_site.name, + 'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name, + 'editor@%s' % current_site.domain, + [user.email]) + + # ... + +On Lawrence.com, this e-mail has the subject line "Thanks for subscribing to +lawrence.com alerts." On LJWorld.com, the e-mail has the subject "Thanks for +subscribing to LJWorld.com alerts." Same goes for the e-mail's message body. + +Note that an even more flexible (but more heavyweight) way of doing this would +be to use Django's template system. Assuming Lawrence.com and LJWorld.com have +different template directories (``TEMPLATE_DIRS``), you could simply farm out +to the template system like so:: + + from django.core.mail import send_mail + from django.template import loader, Context + + def register_for_newsletter(request): + # Check form values, etc., and subscribe the user. + # ... + + subject = loader.get_template('alerts/subject.txt').render(Context({})) + message = loader.get_template('alerts/message.txt').render(Context({})) + send_mail(subject, message, 'editor@ljworld.com', [user.email]) + + # ... + +In this case, you'd have to create ``subject.txt`` and ``message.txt`` template +files for both the LJWorld.com and Lawrence.com template directories. That +gives you more flexibility, but it's also more complex. + +It's a good idea to exploit the ``Site`` objects as much as possible, to remove +unneeded complexity and redundancy. + +Getting the current domain for full URLs +---------------------------------------- + +Django's ``get_absolute_url()`` convention is nice for getting your objects' +URL without the domain name, but in some cases you might want to display the +full URL -- with ``http://`` and the domain and everything -- for an object. +To do this, you can use the sites framework. A simple example:: + + >>> from django.contrib.sites.models import Site + >>> obj = MyModel.objects.get(id=3) + >>> obj.get_absolute_url() + '/mymodel/objects/3/' + >>> Site.objects.get_current().domain + 'example.com' + >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) + 'http://example.com/mymodel/objects/3/' + +The ``CurrentSiteManager`` +========================== + +If ``Site``\s play a key role in your application, consider using the helpful +``CurrentSiteManager`` in your model(s). It's a model manager_ that +automatically filters its queries to include only objects associated with the +current ``Site``. + +Use ``CurrentSiteManager`` by adding it to your model explicitly. For example:: + + from django.db import models + from django.contrib.sites.models import Site + from django.contrib.sites.managers import CurrentSiteManager + + class Photo(models.Model): + photo = models.FileField(upload_to='/home/photos') + photographer_name = models.CharField(maxlength=100) + pub_date = models.DateField() + site = models.ForeignKey(Site) + objects = models.Manager() + on_site = CurrentSiteManager() + +With this model, ``Photo.objects.all()`` will return all ``Photo`` objects in +the database, but ``Photo.on_site.all()`` will return only the ``Photo`` +objects associated with the current site, according to the ``SITE_ID`` setting. + +Put another way, these two statements are equivalent:: + + Photo.objects.filter(site=settings.SITE_ID) + Photo.on_site.all() + +How did ``CurrentSiteManager`` know which field of ``Photo`` was the ``Site``? +It defaults to looking for a field called ``site``. If your model has a +``ForeignKey`` or ``ManyToManyField`` called something *other* than ``site``, +you need to explicitly pass that as the parameter to ``CurrentSiteManager``. +The following model, which has a field called ``publish_on``, demonstrates +this:: + + from django.db import models + from django.contrib.sites.models import Site + from django.contrib.sites.managers import CurrentSiteManager + + class Photo(models.Model): + photo = models.FileField(upload_to='/home/photos') + photographer_name = models.CharField(maxlength=100) + pub_date = models.DateField() + publish_on = models.ForeignKey(Site) + objects = models.Manager() + on_site = CurrentSiteManager('publish_on') + +If you attempt to use ``CurrentSiteManager`` and pass a field name that doesn't +exist, Django will raise a ``ValueError``. + +.. _manager: http://www.djangoproject.com/documentation/model_api/#managers + +How Django uses the sites framework +=================================== + +Although it's not required that you use the sites framework, it's strongly +encouraged, because Django takes advantage of it in a few places. Even if your +Django installation is powering only a single site, you should take the two +seconds to create the site object with your ``domain`` and ``name``, and point +to its ID in your ``SITE_ID`` setting. + +Here's how Django uses the sites framework: + + * In the `redirects framework`_, each redirect object is associated with a + particular site. When Django searches for a redirect, it takes into + account the current ``SITE_ID``. + + * In the comments framework, each comment is associated with a particular + site. When a comment is posted, its ``site`` is set to the current + ``SITE_ID``, and when comments are listed via the appropriate template + tag, only the comments for the current site are displayed. + + * In the `flatpages framework`_, each flatpage is associated with a + particular site. When a flatpage is created, you specify its ``site``, + and the ``FlatpageFallbackMiddleware`` checks the current ``SITE_ID`` in + retrieving flatpages to display. + + * In the `syndication framework`_, the templates for ``title`` and + ``description`` automatically have access to a variable ``{{{ site }}}``, + which is the ``Site`` object representing the current site. Also, the + hook for providing item URLs will use the ``domain`` from the current + ``Site`` object if you don't specify a fully-qualified domain. + + * In the `authentication framework`_, the ``django.contrib.auth.views.login`` + view passes the current ``Site`` name to the template as ``{{{ site_name }}}``. + + * The shortcut view (``django.views.defaults.shortcut``) uses the domain of + the current ``Site`` object when calculating an object's URL. + +.. _redirects framework: http://www.djangoproject.com/documentation/redirects/ +.. _flatpages framework: http://www.djangoproject.com/documentation/flatpages/ +.. _syndication framework: http://www.djangoproject.com/documentation/syndication/ +.. _authentication framework: http://www.djangoproject.com/documentation/syndication/ diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 21ae595624..8ac2effd45 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -7,6 +7,10 @@ perspective -- how it works and how to extend it. If you're just looking for reference on the language syntax, see `The Django template language: For template authors`_. +If you're looking to use the Django template system as part of another +application -- i.e., without the rest of the framework -- make sure to read +the `configuration`_ section later in this document. + .. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/ Basics @@ -739,6 +743,164 @@ Python 2.4 and above:: If you leave off the ``name`` argument, as in the second example above, Django will use the function's name as the tag name. +Shortcut for simple tags +~~~~~~~~~~~~~~~~~~~~~~~~ + +Many template tags take a single argument -- a string or a template variable +reference -- 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 one argument, 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:: + + # This version of do_current_time takes only a single argument and returns + # a string. + + def do_current_time(token): + try: + # Splitting by None == splitting by spaces. + tag_name, format_string = token.contents.split(None, 1) + except ValueError: + raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[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 datetime.datetime.now().strftime(self.format_string[1:-1]) + + register.simple_tag(do_current_time) + +In Python 2.4, the decorator syntax also works:: + + @simple_tag + def do_current_time(token): + ... + +Inclusion tags +~~~~~~~~~~~~~~ + +Another type of template tag that is sometimes useful is when you want to +display some data that is computed at render time in a template fragment. For +example, in Django's admin interface, there is a line of buttons along the +bottom of the `create/edit record` screen. These buttons always look the same, +but the link targets change depending upon the object being edited. So they +are a perfect example for using a small template that is filled in with +details from the current object. To save typing, it would also be nice if we +could wrap this whole display up in a single tag (in the admin templates this +is the ``submit_row`` tag). + +We call these sorts of tags `inclusion tags`. In your template, you pass in +any appropriate arguments and the tag uses those arguments, together with the +current context to render a template and include the result in the output. + +Writing inclusion tags is probably best demonstrated by example. We will write +a tag that outputs a list of choices for a Poll object, such as was created in +the tutorials_. We will use this tag like this:: + + {{ show_results poll }} + +and the output will be something like this:: + + <ul> + <li>First choice</li> + <li>Second choice</li> + <li>Third choice</li> + </ul> + +First, we define the function which 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 to substitue +for values in the template fragment, just as when templates are used +elsewhere. + +:: + + def show_results(poll): + choices = poll.choice_set.all() + return {'choices': choices} + +We also need to create the template that is used to render the output. This +template is a fixed feature of the tag: the tag writer specifies it, not the +template designer. In our case, the template is very simple:: + + <ul> + {% for choice in choices %} + <li> {{ choice }} </li> + {% endfor %} + </ul> + +Now we can create the inclusion tag. Suppose the above template is in a file +called ``results.html`` in a directory that is searched by the template +loader. We register our new tag similarly to a normal tag. + +:: + + # Here, register is a django.template.Library instance, as before + register.inclusion_tag('results.html')(show_results) + +As always, Python 2.4 decorator syntax works as well, so we could have +written + +:: + + @inclusion_tag('results.html') + def show_results(poll): + ... + +when first creating the function. + +In some cases, an inclusion tag might require a large number of arguments to +display itself properly. In essence, it would depend largely on the current +context it was being rendered with. We can make these sorts of tags easier to +write by telling the ``inclusion_tag`` function that the whole context +should be passed in as an argument to the function. This will be done +invisibly as far as the template tag user is concerned: they will not need to +do anything to pass in the context. + +For example, suppose we are 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. We can write a tag that is used like this:: + + {{ jump_link }} + +and renders this:: + + Jump directly to <a href="http://example.com/home">Home</a> + +The tag function is almost as simple as before. This time it takes no +arguments except the ``context`` (and the parameter `must` be called +``context`` in this case; the special parameter named is used internally by +Django to fill in the values correctly). + +:: + + # The first argument *must* be called "context" here. + def jump_link(context): + return { + 'link': context['home_link'], + 'title': context['home_title'], + } + +Our template is very simple again:: + + Jump directly to <a href="{{ link }}">{{ title }}</a>. + +Assuming the template is in a file called ``link.html``, we register this new +tag as follows:: + + register.inclusion_tag('link.html', takes_context = True)(jump_link) + +The ``takes_context`` parameter here defaults to *False*. When it is set to +*True*, our tag is passed the implicit context as in this example. That is the +only difference between this case and our previous use of ``inclusion_tag``. + +.. _tutorials: http://www.djangoproject.com/documentation/tutorial1/#creating-models + Setting a variable in the context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -876,3 +1038,37 @@ The only new concept here is the ``self.nodelist.render(context)`` in For more examples of complex rendering, see the source code for ``{% if %}``, ``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in ``django/template/defaulttags.py``. + +.. _configuration: + +Configuring the template system in standalone mode +================================================== + +.. note:: + + This section is only of interest to people trying to use the template + system as an output component in another application. If you are using the + template system as part of a Django application, nothing here applies to + you. + +Normally, Django will load all the configuration information it needs from its +own default configuration file, combined with the settings in the module given +in the ``DJANGO_SETTINGS_MODULE`` environment variable. But if you're using the +template system independently of the rest of Django, the environment variable +approach isn't very convenient, because you probably want to configure the +template system in line with the rest of your application rather than dealing +with settings files and pointing to them via environment variables. + +To solve this problem, you need to use the manual configuration option +described in the `settings file`_ documentation. Simply import the appropriate +pieces of the templating system and then, *before* you call any of the +templating functions, call ``django.conf.settings.configure()`` with any +settings you wish to specify. You might want to consider setting at least +``TEMPLATE_DIRS`` (if you are going to use template loaders), +``DEFAULT_CHARSET`` (although the default of ``utf-8`` is probably fine) and +``TEMPLATE_DEBUG``. All available settings are described in the +`settings documentation`_, and any setting starting with *TEMPLATE_* +is of obvious interest. + +.. _settings file: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable +.. _settings documentation: http://www.djangoproject.com/documentation/settings/ diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 03d4eac635..c353e1ab4b 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -445,13 +445,13 @@ Once you're in the shell, explore the database API:: # objects.all() displays all the polls in the database. >>> Poll.objects.all() - [<Poll object>] + [<Poll: Poll object>] -Wait a minute. ``<Poll object>`` is, utterly, an unhelpful representation of -this object. Let's fix that by editing the polls model -(in the ``polls/models.py`` file) and adding a ``__str__()`` method to -both ``Poll`` and ``Choice``:: +Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful +representation of this object. Let's fix that by editing the polls model (in +the ``polls/models.py`` file) and adding a ``__str__()`` method to both +``Poll`` and ``Choice``:: class Poll(models.Model): # ... @@ -487,30 +487,30 @@ Let's jump back into the Python interactive shell by running # Make sure our __str__() addition worked. >>> Poll.objects.all() - [What's up?] + [<Poll: What's up?>] # Django provides a rich database lookup API that's entirely driven by # keyword arguments. >>> Poll.objects.filter(id=1) - [What's up?] + [<Poll: What's up?>] >>> Poll.objects.filter(question__startswith='What') - [What's up?] + [<Poll: What's up?>] # Get the poll whose year is 2005. Of course, if you're going through this # tutorial in another year, change as appropriate. >>> Poll.objects.get(pub_date__year=2005) - What's up? + <Poll: What's up?> >>> Poll.objects.get(id=2) Traceback (most recent call last): ... - DoesNotExist: Poll does not exist for {'id': 2} + DoesNotExist: Poll matching query does not exist. # Lookup by a primary key is the most common case, so Django provides a # shortcut for primary-key exact lookups. # The following is identical to Poll.objects.get(id=1). >>> Poll.objects.get(pk=1) - What's up? + <Poll: What's up?> # Make sure our custom method worked. >>> p = Poll.objects.get(pk=1) @@ -522,18 +522,18 @@ Let's jump back into the Python interactive shell by running # of available choices and returns the new Choice object. >>> p = Poll.objects.get(pk=1) >>> p.choice_set.create(choice='Not much', votes=0) - Not much + <Choice: Not much> >>> p.choice_set.create(choice='The sky', votes=0) - The sky + <Choice: The sky> >>> c = p.choice_set.create(choice='Just hacking again', votes=0) # Choice objects have API access to their related Poll objects. >>> c.poll - What's up? + <Poll: What's up?> # And vice versa: Poll objects get access to Choice objects. >>> p.choice_set.all() - [Not much, The sky, Just hacking again] + [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] >>> p.choice_set.count() 3 @@ -542,7 +542,7 @@ Let's jump back into the Python interactive shell by running # This works as many levels deep as you want. There's no limit. # Find all Choices for any poll whose pub_date is in 2005. >>> Choice.objects.filter(poll__pub_date__year=2005) - [Not much, The sky, Just hacking again] + [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] # Let's delete one of the choices. Use delete() for that. >>> c = p.choice_set.filter(choice__startswith='Just hacking') |
