diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-23 22:25:40 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-23 22:25:40 +0000 |
| commit | 97cb07c3a10ff0e584a260a7ee1001614691eb1d (patch) | |
| tree | 204f4382c51e1c288dbf547875161731661733f5 /docs/ref | |
| parent | b3688e81943d6d059d3f3c95095498a5aab84852 (diff) | |
Massive reorganization of the docs. See the new docs online at http://docs.djangoproject.com/.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/ref')
44 files changed, 16210 insertions, 0 deletions
diff --git a/docs/ref/contrib/_images/flatfiles_admin.png b/docs/ref/contrib/_images/flatfiles_admin.png Binary files differnew file mode 100644 index 0000000000..391a629348 --- /dev/null +++ b/docs/ref/contrib/_images/flatfiles_admin.png diff --git a/docs/ref/contrib/_images/users_changelist.png b/docs/ref/contrib/_images/users_changelist.png Binary files differnew file mode 100644 index 0000000000..d5f9c016cc --- /dev/null +++ b/docs/ref/contrib/_images/users_changelist.png diff --git a/docs/ref/contrib/admin.txt b/docs/ref/contrib/admin.txt new file mode 100644 index 0000000000..e7e55fbc82 --- /dev/null +++ b/docs/ref/contrib/admin.txt @@ -0,0 +1,913 @@ +.. _ref-contrib-admin: + +===================== +The Django admin site +===================== + +One of the most powerful parts of Django is the automatic admin interface. It +reads metadata in your model to provide a powerful and production-ready +interface that content producers can immediately use to start adding content to +the site. In this document, we discuss how to activate, use and customize +Django's admin interface. + +.. admonition:: Note + + The admin site has been refactored significantly since Django 0.96. This + document describes the newest version of the admin site, which allows for + much richer customization. If you follow the development of Django itself, + you may have heard this described as "newforms-admin." + +Overview +======== + +There are five steps in activating the Django admin site: + + 1. Add ``django.contrib.admin`` to your ``INSTALLED_APPS`` setting. + + 2. Determine which of your application's models should be editable in the + admin interface. + + 3. For each of those models, optionally create a ``ModelAdmin`` class that + encapsulates the customized admin functionality and options for that + particular model. + + 4. Instantiate an ``AdminSite`` and tell it about each of your models and + ``ModelAdmin`` classes. + + 5. Hook the ``AdminSite`` instance into your URLconf. + +``ModelAdmin`` objects +====================== + +The ``ModelAdmin`` class is the representation of a model in the admin +interface. These are stored in a file named ``admin.py`` in your application. +Let's take a look at a very simple example the ``ModelAdmin``:: + + from django.contrib import admin + from myproject.myapp.models import Author + + class AuthorAdmin(admin.ModelAdmin): + pass + admin.site.register(Author, AuthorAdmin) + +``ModelAdmin`` Options +---------------------- + +The ``ModelAdmin`` is very flexible. It has several options for dealing with +customizing the interface. All options are defined on the ``ModelAdmin`` +subclass:: + + class AuthorAdmin(admin.ModelAdmin): + date_hierarchy = 'pub_date' + +``date_hierarchy`` +~~~~~~~~~~~~~~~~~~ + +Set ``date_hierarchy`` to the name of a ``DateField`` or ``DateTimeField`` in +your model, and the change list page will include a date-based drilldown +navigation by that field. + +Example:: + + date_hierarchy = 'pub_date' + +``form`` +~~~~~~~~ + +By default a ``ModelForm`` is dynamically created for your model. It is used +to create the form presented on both the add/change pages. You can easily +provide your own ``ModelForm`` to override any default form behavior on the +add/change pages. + +For an example see the section `Adding custom validation to the admin`_. + +``fieldsets`` +~~~~~~~~~~~~~ + +Set ``fieldsets`` to control the layout of admin "add" and "change" pages. + +``fieldsets`` is a list of two-tuples, in which each two-tuple represents a +``<fieldset>`` on the admin form page. (A ``<fieldset>`` is a "section" of the +form.) + +The two-tuples are in the format ``(name, field_options)``, where ``name`` is a +string representing the title of the fieldset and ``field_options`` is a +dictionary of information about the fieldset, including a list of fields to be +displayed in it. + +A full example, taken from the ``django.contrib.flatpages.FlatPage`` model:: + + class FlatPageAdmin(admin.ModelAdmin): + fieldsets = ( + (None, { + 'fields': ('url', 'title', 'content', 'sites') + }), + ('Advanced options', { + 'classes': ('collapse',), + 'fields': ('enable_comments', 'registration_required', 'template_name') + }), + ) + +This results in an admin page that looks like: + + .. image:: _images/flatfiles_admin.png + +If ``fieldsets`` isn't given, Django will default to displaying each field +that isn't an ``AutoField`` and has ``editable=True``, in a single fieldset, +in the same order as the fields are defined in the model. + +The ``field_options`` dictionary can have the following keys: + +``fields`` + A tuple of field names to display in this fieldset. This key is required. + + Example:: + + { + 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), + } + + To display multiple fields on the same line, wrap those fields in their own + tuple. In this example, the ``first_name`` and ``last_name`` fields will + display on the same line:: + + { + 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), + } + +``classes`` + A list containing extra CSS classes to apply to the fieldset. + + Example:: + + { + 'classes': ['wide', 'extrapretty'], + } + + Two useful classes defined by the default admin-site stylesheet are + ``collapse`` and ``wide``. Fieldsets with the ``collapse`` style will be + initially collapsed in the admin and replaced with a small "click to expand" + link. Fieldsets with the ``wide`` style will be given extra horizontal space. + +``description`` + A string of optional extra text to be displayed at the top of each fieldset, + under the heading of the fieldset. + + Note that this value is *not* HTML-escaped when it's displayed in + the admin interface. This lets you include HTML if you so desire. + Alternatively you can use plain text and + ``django.utils.html.escape()`` to escape any HTML special + characters. + +``fields`` +~~~~~~~~~~ + +Use this option as an alternative to ``fieldsets`` if the layout does not +matter and if you want to only show a subset of the available fields in the +form. For example, you could define a simpler version of the admin form for +the ``django.contrib.flatpages.FlatPage`` model as follows:: + + class FlatPageAdmin(admin.ModelAdmin): + fields = ('url', 'title', 'content') + +In the above example, only the fields 'url', 'title' and 'content' will be +displayed, sequentially, in the form. + +.. admonition:: Note + + This ``fields`` option should not be confused with the ``fields`` + dictionary key that is within the ``fieldsets`` option, as described in + the previous section. + +``filter_horizontal`` +~~~~~~~~~~~~~~~~~~~~~ + +Use a nifty unobtrusive JavaScript "filter" interface instead of the +usability-challenged ``<select multiple>`` in the admin form. The value is a +list of fields that should be displayed as a horizontal filter interface. See +``filter_vertical`` to use a vertical interface. + +``filter_vertical`` +~~~~~~~~~~~~~~~~~~~ + +Same as ``filter_horizontal``, but is a vertical display of the filter +interface. + +``list_display`` +~~~~~~~~~~~~~~~~ + +Set ``list_display`` to control which fields are displayed on the change list +page of the admin. + +Example:: + + list_display = ('first_name', 'last_name') + +If you don't set ``list_display``, the admin site will display a single column +that displays the ``__unicode__()`` representation of each object. + +You have four possible values that can be used in ``list_display``: + + * A field of the model. For example:: + + class PersonAdmin(admin.ModelAdmin): + list_display = ('first_name', 'last_name') + + * A callable that accepts one parameter for the model instance. For + example:: + + def upper_case_name(obj): + return "%s %s" % (obj.first_name, obj.last_name).upper() + upper_case_name.short_description = 'Name' + + class PersonAdmin(admin.ModelAdmin): + list_display = (upper_case_name,) + + * A string representing an attribute on the ``ModelAdmin``. This behaves + the same as the callable. For example:: + + class PersonAdmin(admin.ModelAdmin): + list_display = ('upper_case_name',) + + def upper_case_name(self, obj): + return "%s %s" % (obj.first_name, obj.last_name).upper() + upper_case_name.short_description = 'Name' + + * A string representing an attribute on the model. This behaves almost + the same as the callable, but ``self`` in this context is the model + instance. Here's a full model example:: + + class Person(models.Model): + name = models.CharField(max_length=50) + birthday = models.DateField() + + def decade_born_in(self): + return self.birthday.strftime('%Y')[:3] + "0's" + decade_born_in.short_description = 'Birth decade' + + class PersonAdmin(admin.ModelAdmin): + list_display = ('name', 'decade_born_in') + +A few special cases to note about ``list_display``: + + * If the field is a ``ForeignKey``, Django will display the + ``__unicode__()`` of the related object. + + * ``ManyToManyField`` fields aren't supported, because that would entail + executing a separate SQL statement for each row in the table. If you + want to do this nonetheless, give your model a custom method, and add + that method's name to ``list_display``. (See below for more on custom + methods in ``list_display``.) + + * If the field is a ``BooleanField`` or ``NullBooleanField``, Django will + display a pretty "on" or "off" icon instead of ``True`` or ``False``. + + * If the string given is a method of the model, ``ModelAdmin`` or a + callable, Django will HTML-escape the output by default. If you'd rather + not escape the output of the method, give the method an ``allow_tags`` + attribute whose value is ``True``. + + Here's a full example model:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + color_code = models.CharField(max_length=6) + + def colored_name(self): + return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name) + colored_name.allow_tags = True + + class PersonAdmin(admin.ModelAdmin): + list_display = ('first_name', 'last_name', 'colored_name') + + * If the string given is a method of the model, ``ModelAdmin`` or a + callable that returns True or False Django will display a pretty "on" or + "off" icon if you give the method a ``boolean`` attribute whose value is + ``True``. + + Here's a full example model:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + birthday = models.DateField() + + def born_in_fifties(self): + return self.birthday.strftime('%Y')[:3] == 5 + born_in_fifties.boolean = True + + class PersonAdmin(admin.ModelAdmin): + list_display = ('name', 'born_in_fifties') + + + * The ``__str__()`` and ``__unicode__()`` methods are just as valid in + ``list_display`` as any other model method, so it's perfectly OK to do + this:: + + list_display = ('__unicode__', 'some_other_field') + + * Usually, elements of ``list_display`` that aren't actual database fields + can't be used in sorting (because Django does all the sorting at the + database level). + + However, if an element of ``list_display`` represents a certain database + field, you can indicate this fact by setting the ``admin_order_field`` + attribute of the item. + + For example:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + color_code = models.CharField(max_length=6) + + def colored_first_name(self): + return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name) + colored_first_name.allow_tags = True + colored_first_name.admin_order_field = 'first_name' + + class PersonAdmin(admin.ModelAdmin): + list_display = ('first_name', 'colored_first_name') + + The above will tell Django to order by the ``first_name`` field when + trying to sort by ``colored_first_name`` in the admin. + +``list_display_links`` +~~~~~~~~~~~~~~~~~~~~~~ + +Set ``list_display_links`` to control which fields in ``list_display`` should +be linked to the "change" page for an object. + +By default, the change list page will link the first column -- the first field +specified in ``list_display`` -- to the change page for each item. But +``list_display_links`` lets you change which columns are linked. Set +``list_display_links`` to a list or tuple of field names (in the same format as +``list_display``) to link. + +``list_display_links`` can specify one or many field names. As long as the +field names appear in ``list_display``, Django doesn't care how many (or how +few) fields are linked. The only requirement is: If you want to use +``list_display_links``, you must define ``list_display``. + +In this example, the ``first_name`` and ``last_name`` fields will be linked on +the change list page:: + + class PersonAdmin(admin.ModelAdmin): + list_display = ('first_name', 'last_name', 'birthday') + list_display_links = ('first_name', 'last_name') + +Finally, note that in order to use ``list_display_links``, you must define +``list_display``, too. + +``list_filter`` +~~~~~~~~~~~~~~~ + +Set ``list_filter`` to activate filters in the right sidebar of the change list +page of the admin. This should be a list of field names, and each specified +field should be either a ``BooleanField``, ``CharField``, ``DateField``, +``DateTimeField``, ``IntegerField`` or ``ForeignKey``. + +This example, taken from the ``django.contrib.auth.models.User`` model, shows +how both ``list_display`` and ``list_filter`` work:: + + class UserAdmin(admin.ModelAdmin): + list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') + list_filter = ('is_staff', 'is_superuser') + +The above code results in an admin change list page that looks like this: + + .. image:: _images/users_changelist.png + +(This example also has ``search_fields`` defined. See below.) + +``list_per_page`` +~~~~~~~~~~~~~~~~~ + +Set ``list_per_page`` to control how many items appear on each paginated admin +change list page. By default, this is set to ``100``. + +``list_select_related`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Set ``list_select_related`` to tell Django to use ``select_related()`` in +retrieving the list of objects on the admin change list page. This can save you +a bunch of database queries. + +The value should be either ``True`` or ``False``. Default is ``False``. + +Note that Django will use ``select_related()``, regardless of this setting, +if one of the ``list_display`` fields is a ``ForeignKey``. + +For more on ``select_related()``, see +:ref:`the select_related() docs <select-related>`. + +``inlines`` +~~~~~~~~~~~ + +See ``InlineModelAdmin`` objects below. + +``ordering`` +~~~~~~~~~~~~ + +Set ``ordering`` to specify how objects on the admin change list page should be +ordered. This should be a list or tuple in the same format as a model's +``ordering`` parameter. + +If this isn't provided, the Django admin will use the model's default ordering. + +.. admonition:: Note + + Django will only honor the first element in the list/tuple; any others + will be ignored. + +``prepopulated_fields`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Set ``prepopulated_fields`` to a dictionary mapping field names to the fields +it should prepopulate from:: + + class ArticleAdmin(admin.ModelAdmin): + prepopulated_fields = {"slug": ("title",)} + +When set, the given fields will use a bit of JavaScript to populate from the +fields assigned. The main use for this functionality is to automatically +generate the value for ``SlugField`` fields from one or more other fields. The +generated value is produced by concatenating the values of the source fields, +and then by transforming that result into a valid slug (e.g. substituting +dashes for spaces). + +``prepopulated_fields`` doesn't accept ``DateTimeField``, ``ForeignKey``, nor +``ManyToManyField`` fields. + +``radio_fields`` +~~~~~~~~~~~~~~~~ + +By default, Django's admin uses a select-box interface (<select>) for +fields that are ``ForeignKey`` or have ``choices`` set. If a field is present +in ``radio_fields``, Django will use a radio-button interface instead. +Assuming ``group`` is a ``ForeignKey`` on the ``Person`` model:: + + class PersonAdmin(admin.ModelAdmin): + radio_fields = {"group": admin.VERTICAL} + +You have the choice of using ``HORIZONTAL`` or ``VERTICAL`` from the +``django.contrib.admin`` module. + +Don't include a field in ``radio_fields`` unless it's a ``ForeignKey`` or has +``choices`` set. + +``raw_id_fields`` +~~~~~~~~~~~~~~~~~ + +By default, Django's admin uses a select-box interface (<select>) for +fields that are ``ForeignKey``. Sometimes you don't want to incur the +overhead of having to select all the related instances to display in the +drop-down. + +``raw_id_fields`` is a list of fields you would like to change +into a ``Input`` widget for either a ``ForeignKey`` or ``ManyToManyField``:: + + class ArticleAdmin(admin.ModelAdmin): + raw_id_fields = ("newspaper",) + +``save_as`` +~~~~~~~~~~~ + +Set ``save_as`` to enable a "save as" feature on admin change forms. + +Normally, objects have three save options: "Save", "Save and continue editing" +and "Save and add another". If ``save_as`` is ``True``, "Save and add another" +will be replaced by a "Save as" button. + +"Save as" means the object will be saved as a new object (with a new ID), +rather than the old object. + +By default, ``save_as`` is set to ``False``. + +``save_on_top`` +~~~~~~~~~~~~~~~ + +Set ``save_on_top`` to add save buttons across the top of your admin change +forms. + +Normally, the save buttons appear only at the bottom of the forms. If you set +``save_on_top``, the buttons will appear both on the top and the bottom. + +By default, ``save_on_top`` is set to ``False``. + +``search_fields`` +~~~~~~~~~~~~~~~~~ + +Set ``search_fields`` to enable a search box on the admin change list page. +This should be set to a list of field names that will be searched whenever +somebody submits a search query in that text box. + +These fields should be some kind of text field, such as ``CharField`` or +``TextField``. You can also perform a related lookup on a ``ForeignKey`` with +the lookup API "follow" notation:: + + search_fields = ['foreign_key__related_fieldname'] + +When somebody does a search in the admin search box, Django splits the search +query into words and returns all objects that contain each of the words, case +insensitive, where each word must be in at least one of ``search_fields``. For +example, if ``search_fields`` is set to ``['first_name', 'last_name']`` and a +user searches for ``john lennon``, Django will do the equivalent of this SQL +``WHERE`` clause:: + + WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') + AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%') + +For faster and/or more restrictive searches, prefix the field name +with an operator: + +``^`` + Matches the beginning of the field. For example, if ``search_fields`` is + set to ``['^first_name', '^last_name']`` and a user searches for + ``john lennon``, Django will do the equivalent of this SQL ``WHERE`` + clause:: + + WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') + AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%') + + This query is more efficient than the normal ``'%john%'`` query, because + the database only needs to check the beginning of a column's data, rather + than seeking through the entire column's data. Plus, if the column has an + index on it, some databases may be able to use the index for this query, + even though it's a ``LIKE`` query. + +``=`` + Matches exactly, case-insensitive. For example, if + ``search_fields`` is set to ``['=first_name', '=last_name']`` and + a user searches for ``john lennon``, Django will do the equivalent + of this SQL ``WHERE`` clause:: + + WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') + AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon') + + Note that the query input is split by spaces, so, following this example, + it's currently not possible to search for all records in which + ``first_name`` is exactly ``'john winston'`` (containing a space). + +``@`` + Performs a full-text match. This is like the default search method but uses + an index. Currently this is only available for MySQL. + +``ModelAdmin`` methods +---------------------- + +``save_model(self, request, obj, form, change)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``save_model`` method is given the ``HttpRequest``, a model instance, +a ``ModelForm`` instance and a boolean value based on whether it is adding or +changing the object. Here you can do any pre- or post-save operations. + +For example to attach ``request.user`` to the object prior to saving:: + + class ArticleAdmin(admin.ModelAdmin): + def save_model(self, request, obj, form, change): + obj.user = request.user + obj.save() + +``save_formset(self, request, form, formset, change)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``save_formset`` method is given the ``HttpRequest``, the parent +``ModelForm`` instance and a boolean value based on whether it is adding or +changing the parent object. + +For example to attach ``request.user`` to each changed formset +model instance:: + + class ArticleAdmin(admin.ModelAdmin): + def save_formset(self, request, form, formset, change): + instances = formset.save(commit=False) + for instance in instances: + instance.user = request.user + instance.save() + formset.save_m2m() + +``ModelAdmin`` media definitions +-------------------------------- + +There are times where you would like add a bit of CSS and/or JavaScript to +the add/change views. This can be accomplished by using a Media inner class +on your ``ModelAdmin``:: + + class ArticleAdmin(admin.ModelAdmin): + class Media: + css = { + "all": ("my_styles.css",) + } + js = ("my_code.js",) + +Keep in mind that this will be prepended with ``MEDIA_URL``. The same rules +apply as :ref:`regular media definitions on forms <topics-forms-media>`. + +Adding custom validation to the admin +------------------------------------- + +Adding custom validation of data in the admin is quite easy. The automatic admin +interfaces reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives you +the ability define your own form:: + + class ArticleAdmin(admin.ModelAdmin): + form = MyArticleAdminForm + +``MyArticleAdminForm`` can be defined anywhere as long as you import where +needed. Now within your form you can add your own custom validation for +any field:: + + class MyArticleAdminForm(forms.ModelForm): + class Meta: + model = Article + + def clean_name(self): + # do something that validates your data + return self.cleaned_data["name"] + +It is important you use a ``ModelForm`` here otherwise things can break. See the +:ref:`forms <ref-forms-index>` documentation on :ref:`custom validation +<ref-forms-validation>` for more information. + +``InlineModelAdmin`` objects +============================ + +The admin interface has the ability to edit models on the same page as a +parent model. These are called inlines. You can add them to a model by +specifying them in a ``ModelAdmin.inlines`` attribute:: + + class BookInline(admin.TabularInline): + model = Book + + class AuthorAdmin(admin.ModelAdmin): + inlines = [ + BookInline, + ] + +Django provides two subclasses of ``InlineModelAdmin`` and they are: + + * ``TabularInline`` + * ``StackedInline`` + +The difference between these two is merely the template used to render them. + +``InlineModelAdmin`` options +----------------------------- + +The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits +all the same functionality as well as some of its own: + +``model`` +~~~~~~~~~ + +The model in which the inline is using. This is required. + +``fk_name`` +~~~~~~~~~~~ + +The name of the foreign key on the model. In most cases this will be dealt +with automatically, but ``fk_name`` must be specified explicitly if there are +more than one foreign key to the same parent model. + +``formset`` +~~~~~~~~~~~ + +This defaults to ``BaseInlineFormSet``. Using your own formset can give you +many possibilities of customization. Inlines are built around +:ref:`model formsets <model-formsets>`. + +``form`` +~~~~~~~~ + +The value for ``form`` is inherited from ``ModelAdmin``. This is what is +passed through to ``formset_factory`` when creating the formset for this +inline. + +``extra`` +~~~~~~~~~ + +This controls the number of extra forms the formset will display in addition +to the initial forms. See the +:ref:`formsets documentation <topics-forms-formsets>` for more information. + +``max_num`` +~~~~~~~~~~~ + +This controls the maximum number of forms to show in the inline. This doesn't +directly correlate to the number of objects, but can if the value is small +enough. See :ref:`model-formsets-max-num` for more information. + +``raw_id_fields`` +~~~~~~~~~~~~~~~~~ + +By default, Django's admin uses a select-box interface (<select>) for +fields that are ``ForeignKey``. Sometimes you don't want to incur the +overhead of having to select all the related instances to display in the +drop-down. + +``raw_id_fields`` is a list of fields you would like to change +into a ``Input`` widget for either a ``ForeignKey`` or ``ManyToManyField``:: + + class BookInline(admin.TabularInline): + model = Book + raw_id_fields = ("pages",) + +``template`` +~~~~~~~~~~~~ + +The template used to render the inline on the page. + +``verbose_name`` +~~~~~~~~~~~~~~~~ + +An override to the ``verbose_name`` found in the model's inner ``Meta`` class. + +``verbose_name_plural`` +~~~~~~~~~~~~~~~~~~~~~~~ + +An override to the ``verbose_name_plural`` found in the model's inner ``Meta`` +class. + +Working with a model with two or more foreign keys to the same parent model +--------------------------------------------------------------------------- + +It is sometimes possible to have more than one foreign key to the same model. +Take this model for instance:: + + class Friendship(models.Model): + to_person = models.ForeignKey(Person, related_name="friends") + from_person = models.ForeignKey(Person, related_name="from_friends") + +If you wanted to display an inline on the ``Person`` admin add/change pages +you need to explicitly define the foreign key since it is unable to do so +automatically:: + + class FriendshipInline(admin.TabularInline): + model = Friendship + fk_name = "to_person" + + class PersonAdmin(admin.ModelAdmin): + inlines = [ + FriendshipInline, + ] + +Working with Many-to-Many Intermediary Models +---------------------------------------------- + +By default, admin widgets for many-to-many relations will be displayed inline +on whichever model contains the actual reference to the ``ManyToManyField``. +However, when you specify an intermediary model using the ``through`` +argument to a ``ManyToManyField``, the admin will not display a widget by +default. This is because each instance of that intermediary model requires +more information than could be displayed in a single widget, and the layout +required for multiple widgets will vary depending on the intermediate model. + +However, we still want to be able to edit that information inline. Fortunately, +this is easy to do with inline admin models. Suppose we have the following +models:: + + class Person(models.Model): + name = models.CharField(max_length=128) + + class Group(models.Model): + name = models.CharField(max_length=128) + members = models.ManyToManyField(Person, through='Membership') + + class Membership(models.Model): + person = models.ForeignKey(Person) + group = models.ForeignKey(Group) + date_joined = models.DateField() + invite_reason = models.CharField(max_length=64) + +The first step in displaying this intermediate model in the admin is to +define an inline class for the ``Membership`` model:: + + class MembershipInline(admin.TabularInline): + model = Membership + extra = 1 + +This simple example uses the default ``InlineModelAdmin`` values for the +``Membership`` model, and limits the extra add forms to one. This could be +customized using any of the options available to ``InlineModelAdmin`` classes. + +Now create admin views for the ``Person`` and ``Group`` models:: + + class PersonAdmin(admin.ModelAdmin): + inlines = (MembershipInline,) + + class GroupAdmin(admin.ModelAdmin): + inlines = (MembershipInline,) + +Finally, register your ``Person`` and ``Group`` models with the admin site:: + + admin.site.register(Person, PersonAdmin) + admin.site.register(Group, GroupAdmin) + +Now your admin site is set up to edit ``Membership`` objects inline from +either the ``Person`` or the ``Group`` detail pages. + +Using generic relations as an inline +------------------------------------ + +It is possible to use an inline with generically related objects. Let's say +you have the following models:: + + class Image(models.Model): + image = models.ImageField(upload_to="images") + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey("content_type", "object_id") + + class Product(models.Model): + name = models.CharField(max_length=100) + +If you want to allow editing and creating ``Image`` instance on the ``Product`` +add/change views you can simply use ``GenericInlineModelAdmin`` provided by +``django.contrib.contenttypes.generic``. In your ``admin.py`` for this +example app:: + + from django.contrib import admin + from django.contrib.contenttypes import generic + + from myproject.myapp.models import Image, Product + + class ImageInline(generic.GenericTabularInline): + model = Image + + class ProductAdmin(admin.ModelAdmin): + inlines = [ + ImageInline, + ] + + admin.site.register(Product, ProductAdmin) + +``django.contrib.contenttypes.generic`` provides both a ``GenericTabularInline`` +and ``GenericStackedInline`` and behave just like any other inline. See the +:ref:`contenttypes documentation <ref-contrib-contenttypes>` for more specific +information. + +``AdminSite`` objects +===================== + +Hooking ``AdminSite`` instances into your URLconf +------------------------------------------------- + +The last step in setting up the Django admin is to hook your ``AdminSite`` +instance into your URLconf. Do this by pointing a given URL at the +``AdminSite.root`` method. + +In this example, we register the default ``AdminSite`` instance +``django.contrib.admin.site`` at the URL ``/admin/`` :: + + # urls.py + from django.conf.urls.defaults import * + from django.contrib import admin + + admin.autodiscover() + + urlpatterns = patterns('', + ('^admin/(.*)', admin.site.root), + ) + +Above we used ``admin.autodiscover()`` to automatically load the +``INSTALLED_APPS`` admin.py modules. + +In this example, we register the ``AdminSite`` instance +``myproject.admin.admin_site`` at the URL ``/myadmin/`` :: + + # urls.py + from django.conf.urls.defaults import * + from myproject.admin import admin_site + + urlpatterns = patterns('', + ('^myadmin/(.*)', admin_site.root), + ) + +There is really no need to use autodiscover when using your own ``AdminSite`` +instance since you will likely be importing all the per-app admin.py modules +in your ``myproject.admin`` module. + +Note that the regular expression in the URLpattern *must* group everything in +the URL that comes after the URL root -- hence the ``(.*)`` in these examples. + +Multiple admin sites in the same URLconf +---------------------------------------- + +It's easy to create multiple instances of the admin site on the same +Django-powered Web site. Just create multiple instances of ``AdminSite`` and +root each one at a different URL. + +In this example, the URLs ``/basic-admin/`` and ``/advanced-admin/`` feature +separate versions of the admin site -- using the ``AdminSite`` instances +``myproject.admin.basic_site`` and ``myproject.admin.advanced_site``, +respectively:: + + # urls.py + from django.conf.urls.defaults import * + from myproject.admin import basic_site, advanced_site + + urlpatterns = patterns('', + ('^basic-admin/(.*)', basic_site.root), + ('^advanced-admin/(.*)', advanced_site.root), + ) diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt new file mode 100644 index 0000000000..03f5ff1281 --- /dev/null +++ b/docs/ref/contrib/auth.txt @@ -0,0 +1,6 @@ +.. _ref-contrib-auth: + +``django.contrib.auth`` +======================= + +See :ref:`topics-auth`. diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt new file mode 100644 index 0000000000..fe9a32b64f --- /dev/null +++ b/docs/ref/contrib/contenttypes.txt @@ -0,0 +1,347 @@ +.. _ref-contrib-contenttypes: + +========================== +The contenttypes framework +========================== + +.. module:: django.contrib.contenttypes + :synopsis: Provides generic interface to installed models. + +Django includes a :mod:`contenttypes` application that can track all of +the models installed in your Django-powered project, providing a +high-level, generic interface for working with your models. + +Overview +======== + +At the heart of the contenttypes application is the +:class:`~django.contrib.contenttypes.models.ContentType` model, which lives at +``django.contrib.contenttypes.models.ContentType``. Instances of +:class:`~django.contrib.contenttypes.models.ContentType` represent and store +information about the models installed in your project, and new instances of +:class:`~django.contrib.contenttypes.models.ContentType` are automatically +created whenever new models are installed. + +Instances of :class:`~django.contrib.contenttypes.models.ContentType` have +methods for returning the model classes they represent and for querying objects +from those models. :class:`~django.contrib.contenttypes.models.ContentType` +also has a :ref:`custom manager <custom-managers>` that adds methods for +working with :class:`~django.contrib.contenttypes.models.ContentType` and for +obtaining instances of :class:`~django.contrib.contenttypes.models.ContentType` +for a particular model. + +Relations between your models and +:class:`~django.contrib.contenttypes.models.ContentType` can also be used to +enable "generic" relationships between an instance of one of your +models and instances of any model you have installed. + +Installing the contenttypes framework +===================================== + +The contenttypes framework is included in the default +:setting:`INSTALLED_APPS` list created by ``django-admin.py startproject``, +but if you've removed it or if you manually set up your +:setting:`INSTALLED_APPS` list, you can enable it by adding +``'django.contrib.contenttypes'`` to your :setting:`INSTALLED_APPS` setting. + +It's generally a good idea to have the contenttypes framework +installed; several of Django's other bundled applications require it: + + * The admin application uses it to log the history of each object + added or changed through the admin interface. + + * Django's :mod:`authentication framework <django.contrib.auth>` uses it + to tie user permissions to specific models. + + * Django's comments system (:mod:`django.contrib.comments`) uses it to + "attach" comments to any installed model. + +The ``ContentType`` model +========================= + +.. class:: models.ContentType + + Each instance of :class:`~django.contrib.contenttypes.models.ContentType` + has three fields which, taken together, uniquely describe an installed model: + + .. attribute:: models.ContentType.app_label + + The name of the application the model is part of. This is taken from + the :attr:`app_label` attribute of the model, and includes only the *last* + part of the application's Python import path; + "django.contrib.contenttypes", for example, becomes an :attr:`app_label` + of "contenttypes". + + .. attribute:: models.ContentType.model + + The name of the model class. + + .. attribute:: models.ContentType.name + + The human-readable name of the model. This is taken from the + :attr:`verbose_name <django.db.models.fields.Field.verbose_name>` + attribute of the model. + +Let's look at an example to see how this works. If you already have +the contenttypes application installed, and then add +:mod:`the sites application <django.contrib.sites>` to your +:setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it, +the model :class:`django.contrib.sites.models.Site` will be installed into +your database. Along with it a new instance of +:class:`~django.contrib.contenttypes.models.ContentType` will be +created with the following values: + + * :attr:`app_label` will be set to ``'sites'`` (the last part of the Python + path "django.contrib.sites"). + + * :attr:`model` will be set to ``'site'``. + + * :attr:`name` will be set to ``'site'``. + +.. _the verbose_name attribute: ../model-api/#verbose_name + +Methods on ``ContentType`` instances +==================================== + +.. class:: models.ContentType + + Each :class:`~django.contrib.contenttypes.models.ContentType` instance has + methods that allow you to get from a + :class:`~django.contrib.contenttypes.models.ContentType` instance to the model + it represents, or to retrieve objects from that model: + +.. method:: models.ContentType.get_object_for_this_type(**kwargs) + + Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the + model the :class:`~django.contrib.contenttypes.models.ContentType` + represents, and does :ref:`a get() lookup <get-kwargs>` on that model, + returning the corresponding object. + +.. method:: models.ContentType.model_class() + + Returns the model class represented by this + :class:`~django.contrib.contenttypes.models.ContentType` instance. + +For example, we could look up the +:class:`~django.contrib.contenttypes.models.ContentType` for the +:class:`~django.contrib.auth.models.User` model:: + + >>> from django.contrib.contenttypes.models import ContentType + >>> user_type = ContentType.objects.get(app_label="auth", model="user") + >>> user_type + <ContentType: user> + +And then use it to query for a particular ``User``, or to get access +to the ``User`` model class:: + + >>> user_type.model_class() + <class 'django.contrib.auth.models.User'> + >>> user_type.get_object_for_this_type(username='Guido') + <User: Guido> + +Together, +:meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type` +and :meth:`~django.contrib.contenttypes.models.ContentType.model_class` +enable two extremely important use cases: + + 1. Using these methods, you can write high-level generic code that + performs queries on any installed model -- instead of importing and using + a single specific model class, you can pass an ``app_label`` and + ``model`` into a :class:`~django.contrib.contenttypes.models.ContentType` + lookup at runtime, and then work with the model class or retrieve objects + from it. + + 2. You can relate another model to + :class:`~django.contrib.contenttypes.models.ContentType` as a way of + tying instances of it to particular model classes, and use these methods + to get access to those model classes. + +Several of Django's bundled applications make use of the latter technique. +For example, +:class:`the permissions system <django.contrib.auth.models.Permission` in +Django's authentication framework uses a +:class:`~django.contrib.auth.models.Permission` model with a foreign +key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets +:class:`~django.contrib.auth.models.Permission` represent concepts like +"can add blog entry" or "can delete news story". + +The ``ContentTypeManager`` +-------------------------- + +.. class:: models.ContentTypeManager + + :class:`~django.contrib.contenttypes.models.ContentType` also has a custom + manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`, + which adds the following methods: + + .. method:: models.ContentTypeManager.clear_cache() + + Clears an internal cache used by + :class:`~django.contrib.contenttypes.models.ContentType>` to keep track + of which models for which it has created + :class:`django.contrib.contenttypes.models.ContentType>` instances. You + probably won't ever need to call this method yourself; Django will call + it automatically when it's needed. + + .. method:: models.ContentTypeManager.get_for_model(model) + + Takes either a model class or an instance of a model, and returns the + :class:`~django.contrib.contenttypes.models.ContentType` instance + representing that model. + +The :meth:`~models.ContentTypeManager.get_for_model()` method is especially useful when you know you +need to work with a :class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't want to go to the +trouble of obtaining the model's metadata to perform a manual lookup:: + + >>> from django.contrib.auth.models import User + >>> user_type = ContentType.objects.get_for_model(User) + >>> user_type + <ContentType: user> + +.. _generic-relations: + +Generic relations +================= + +Adding a foreign key from one of your own models to +:class:`~django.contrib.contenttypes.models.ContentType` allows your model to +effectively tie itself to another model class, as in the example of the +:class:`~django.contrib.auth.models.Permission` model above. But it's possible +to go one step further and use +:class:`~django.contrib.contenttypes.models.ContentType` to enable truly +generic (sometimes called "polymorphic") relationships between models. + +A simple example is a tagging system, which might look like this:: + + from django.db import models + from django.contrib.contenttypes.models import ContentType + from django.contrib.contenttypes import generic + + class TaggedItem(models.Model): + tag = models.SlugField() + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey('content_type', 'object_id') + + def __unicode__(self): + return self.tag + +A normal :class:`~django.db.models.fields.related.ForeignKey` can only "point +to" one other model, which means that if the ``TaggedItem`` model used a +:class:`~django.db.models.fields.related.ForeignKey` it would have to +choose one and only one model to store tags for. The contenttypes +application provides a special field type -- +:class:`django.contrib.contenttypes.generic.GenericForeignKey` -- which +works around this and allows the relationship to be with any +model. There are three parts to setting up a +:class:`~django.contrib.contenttypes.generic.GenericForeignKey`: + + 1. Give your model a :class:`~django.db.models.fields.related.ForeignKey` + to :class:`~django.contrib.contenttypes.models.ContentType`. + + 2. Give your model a field that can store a primary-key value from the + models you'll be relating to. (For most models, this means an + :class:`~django.db.models.fields.IntegerField` or + :class:`~django.db.models.fields.PositiveIntegerField`.) + + This field must be of the same type as the primary key of the models + that will be involved in the generic relation. For example, if you use + :class:`~django.db.models.fields.IntegerField`, you won't be able to + form a generic relation with a model that uses a + :class:`~django.db.models.fields.CharField` as a primary key. + + 3. Give your model a + :class:`~django.contrib.contenttypes.generic.GenericForeignKey`, and + pass it the names of the two fields described above. If these fields + are named "content_type" and "object_id", you can omit this -- those + are the default field names + :class:`~django.contrib.contenttypes.generic.GenericForeignKey` will + look for. + +This will enable an API similar to the one used for a normal +:class:`~django.db.models.fields.related.ForeignKey`; +each ``TaggedItem`` will have a ``content_object`` field that returns the +object it's related to, and you can also assign to that field or use it when +creating a ``TaggedItem``:: + + >>> from django.contrib.auth.models import User + >>> guido = User.objects.get(username='Guido') + >>> t = TaggedItem(content_object=guido, tag='bdfl') + >>> t.save() + >>> t.content_object + <User: Guido> + +Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey` +is implemented, you cannot use such fields directly with filters (``filter()`` +and ``exclude()``, for example) via the database API. They aren't normal field +objects. These examples will *not* work:: + + # This will fail + >>> TaggedItem.objects.filter(content_object=guido) + # This will also fail + >>> TaggedItem.objects.get(content_object=guido) + +Reverse generic relations +------------------------- + +If you know which models you'll be using most often, you can also add +a "reverse" generic relationship to enable an additional API. For example:: + + class Bookmark(models.Model): + url = models.URLField() + tags = generic.GenericRelation(TaggedItem) + +``Bookmark`` instances will each have a ``tags`` attribute, which can +be used to retrieve their associated ``TaggedItems``:: + + >>> b = Bookmark(url='http://www.djangoproject.com/') + >>> b.save() + >>> t1 = TaggedItem(content_object=b, tag='django') + >>> t1.save() + >>> t2 = TaggedItem(content_object=b, tag='python') + >>> t2.save() + >>> b.tags.all() + [<TaggedItem: django>, <TaggedItem: python>] + +If you don't add the reverse relationship, you can do the lookup manually:: + + >>> b = Bookmark.objects.get(url='http://www.djangoproject.com/) + >>> bookmark_type = ContentType.objects.get_for_model(b) + >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, + ... object_id=b.id) + [<TaggedItem: django>, <TaggedItem: python>] + +Note that if you delete an object that has a +:class:`~django.contrib.contenttypes.generic.GenericRelation`, any objects +which have a :class:`~django.contrib.contenttypes.generic.GenericForeignKey` +pointing at it will be deleted as well. In the example above, this means that +if a ``Bookmark`` object were deleted, any ``TaggedItem`` objects pointing at +it would be deleted at the same time. + +Generic relations in forms and admin +------------------------------------ + +:mod:`django.contrib.contenttypes.generic` provides both a +:class:`~django.contrib.contenttypes.generic.GenericInlineFormSet` +and :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`. +This enables the use of generic relations in forms and the admin. See the +:ref:`model formset <topics-forms-modelforms>` and +:ref:`admin <ref-contrib-admin>` documentation for more information. + +.. class:: generic.GenericInlineModelAdmin + + The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin` + class inherits all properties from an + :class:`~django.contrib.admin.options.InlineModelAdmin` class. However, + it adds a couple of its own for working with the generic relation: + + .. attribute:: generic.GenericInlineModelAdmin.ct_field + + The name of the + :class:`~django.contrib.contenttypes.models.ContentType` foreign key + field on the model. Defaults to ``content_type``. + + .. attribute:: generic.GenericInlineModelAdmin.ct_fk_field + + The name of the integer field that represents the ID of the related + object. Defaults to ``object_id``. diff --git a/docs/ref/contrib/csrf.txt b/docs/ref/contrib/csrf.txt new file mode 100644 index 0000000000..cf0fe8a3bf --- /dev/null +++ b/docs/ref/contrib/csrf.txt @@ -0,0 +1,76 @@ +.. _ref-contrib-csrf: + +===================================== +Cross Site Request Forgery protection +===================================== + +.. module:: django.contrib.csrf + :synopsis: Protects against Cross Site Request Forgeries + +The CsrfMiddleware class provides easy-to-use protection against +`Cross Site Request Forgeries`_. This type of attack occurs when a malicious +Web site creates a link or form button that is intended to perform some action +on your Web site, using the credentials of a logged-in user who is tricked +into clicking on the link in their browser. + +The first defense against CSRF attacks is to ensure that GET requests +are side-effect free. POST requests can then be protected by adding this +middleware into your list of installed middleware. + +.. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF + +How to use it +============= + +Add the middleware ``'django.contrib.csrf.middleware.CsrfMiddleware'`` to +your list of middleware classes, :setting:`MIDDLEWARE_CLASSES`. It needs to process +the response after the SessionMiddleware, so must come before it in the +list. It also must process the response before things like compression +happen to the response, so it must come after GZipMiddleware in the list. + +How it works +============ + +CsrfMiddleware does two things: + +1. It modifies outgoing requests by adding a hidden form field to all + 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is + a hash of the session ID plus a secret. If there is no session ID set, + this modification of the response isn't done, so there is very little + performance penalty for those requests that don't have a session. + +2. On all incoming POST requests that have the session cookie set, it + checks that the 'csrfmiddlewaretoken' is present and correct. If it + isn't, the user will get a 403 error. + +This ensures that only forms that have originated from your Web site +can be used to POST data back. + +It deliberately only targets HTTP POST requests (and the corresponding POST +forms). GET requests ought never to have any potentially dangerous side +effects (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a +CSRF attack with a GET request ought to be harmless. + +POST requests that are not accompanied by a session cookie are not protected, +but they do not need to be protected, since the 'attacking' Web site +could make these kind of requests anyway. + +The Content-Type is checked before modifying the response, and only +pages that are served as 'text/html' or 'application/xml+xhtml' +are modified. + +.. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html + +Limitations +=========== + +CsrfMiddleware requires Django's session framework to work. If you have +a custom authentication system that manually sets cookies and the like, +it won't help you. + +If your app creates HTML pages and forms in some unusual way, (e.g. +it sends fragments of HTML in JavaScript document.write statements) +you might bypass the filter that adds the hidden field to the form, +in which case form submission will always fail. It may still be possible +to use the middleware, provided you can find some way to get the +CSRF token and ensure that is included when your form is submitted.
\ No newline at end of file diff --git a/docs/ref/contrib/databrowse.txt b/docs/ref/contrib/databrowse.txt new file mode 100644 index 0000000000..c4da2fe929 --- /dev/null +++ b/docs/ref/contrib/databrowse.txt @@ -0,0 +1,92 @@ +.. _ref-contrib-databrowse: + +========== +Databrowse +========== + +.. module:: django.contrib.databrowse + :synopsis: Databrowse is a Django application that lets you browse your data. + +Databrowse is a Django application that lets you browse your data. + +As the Django admin dynamically creates an admin interface by introspecting +your models, Databrowse dynamically creates a rich, browsable Web site by +introspecting your models. + +.. admonition:: Note + + Databrowse is **very** new and is currently under active development. It + may change substantially before the next Django release. + + With that said, it's easy to use, and it doesn't require writing any + code. So you can play around with it today, with very little investment in + time or coding. + +How to use Databrowse +===================== + + 1. Point Django at the default Databrowse templates. There are two ways to + do this: + + * Add ``'django.contrib.databrowse'`` to your :setting:`INSTALLED_APPS` + setting. This will work if your :setting:`TEMPLATE_LOADERS` setting + includes the ``app_directories`` template loader (which is the case by + default). See the :ref:`template loader docs <template-loaders>` for + more. + + * Otherwise, determine the full filesystem path to the + `:file:`django/contrib/databrowse/templates` directory, and add that + directory to your :setting:`TEMPLATE_DIRS` setting. + + 2. Register a number of models with the Databrowse site:: + + from django.contrib import databrowse + from myapp.models import SomeModel, SomeOtherModel + + databrowse.site.register(SomeModel) + databrowse.site.register(SomeOtherModel) + + Note that you should register the model *classes*, not instances. + + It doesn't matter where you put this, as long as it gets executed at some + point. A good place for it is in your :ref:`URLconf file + <topics-http-urls>` (``urls.py``). + + 3. Change your URLconf to import the :mod:`~django.contrib.databrowse` module:: + + from django.contrib import databrowse + + ...and add the following line to your URLconf:: + + (r'^databrowse/(.*)', databrowse.site.root), + + The prefix doesn't matter -- you can use ``databrowse/`` or ``db/`` or + whatever you'd like. + + 4. Run the Django server and visit ``/databrowse/`` in your browser. + +Requiring user login +==================== + +You can restrict access to logged-in users with only a few extra lines of +code. Simply add the following import to your URLconf:: + + from django.contrib.auth.decorators import login_required + +Then modify the :ref:`URLconf <topics-http-urls>` so that the +:func:`databrowse.site.root` view is decorated with +:func:`django.contrib.auth.decorators.login_required`:: + + (r'^databrowse/(.*)', login_required(databrowse.site.root)), + +If you haven't already added support for user logins to your :ref:`URLconf +<topics-http-urls>`, as described in the :ref:`user authentication docs +<ref-contrib-auth>`, then you will need to do so now with the following +mapping:: + + (r'^accounts/login/$', 'django.contrib.auth.views.login'), + +The final step is to create the login form required by +:func:`django.contrib.auth.views.login`. The +:ref:`user authentication docs <ref-contrib-auth>` provide full details and a +sample template that can be used for this purpose. diff --git a/docs/ref/contrib/flatpages.txt b/docs/ref/contrib/flatpages.txt new file mode 100644 index 0000000000..828a4fc0f2 --- /dev/null +++ b/docs/ref/contrib/flatpages.txt @@ -0,0 +1,153 @@ +.. _ref-contrib-flatpages: + +================= +The flatpages app +================= + +.. module:: django.contrib.flatpages + :synopsis: A framework for managing simple ?flat? HTML content in a database. + +Django comes with an optional "flatpages" application. It lets you store simple +"flat" HTML content in a database and handles the management for you via +Django's admin interface and a Python API. + +A flatpage is a simple object with a URL, title and content. Use it for +one-off, special-case pages, such as "About" or "Privacy Policy" pages, that +you want to store in a database but for which you don't want to develop a +custom Django application. + +A flatpage can use a custom template or a default, systemwide flatpage +template. It can be associated with one, or multiple, sites. + +**New in Django development version** + +The content field may optionally be left blank if you prefer to put your +content in a custom template. + +Here are some examples of flatpages on Django-powered sites: + + * http://www.chicagocrime.org/about/ + * http://www.everyblock.com/about/ + * http://www.lawrence.com/about/contact/ + +Installation +============ + +To install the flatpages app, follow these steps: + + 1. Install the :mod:`sites framework <django.contrib.sites>` by adding + ``'django.contrib.sites'`` to your :setting:`INSTALLED_APPS` setting, + if it's not already in there. + + 2. Add ``'django.contrib.flatpages'`` to your :setting:`INSTALLED_APPS` + setting. + + 3. Add ``'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'`` + to your :setting:`MIDDLEWARE_CLASSES` setting. + + 4. Run the command :djadmin:`manage.py syncdb <syncdb>`. + +How it works +============ + +``manage.py syncdb`` creates two tables in your database: ``django_flatpage`` +and ``django_flatpage_sites``. ``django_flatpage`` is a simple lookup table +that simply maps a URL to a title and bunch of text content. +``django_flatpage_sites`` associates a flatpage with a site. + +The :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` +does all of the work. Each time any Django application raises a 404 error, this +middleware checks the flatpages database for the requested URL as a last resort. +Specifically, it checks for a flatpage with the given URL with a site ID that +corresponds to the :setting:`SITE_ID` setting. + +If it finds a match, it follows this algorithm: + + * If the flatpage has a custom template, it loads that template. Otherwise, + it loads the template :file:`flatpages/default.html`. + + * It passes that template a single context variable, :data:`flatpage`, which + is the flatpage object. It uses + :class:`~django.template.context.RequestContext` in rendering the + template. + +If it doesn't find a match, the request continues to be processed as usual. + +The middleware only gets activated for 404s -- not for 500s or responses of any +other status code. + +Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you can +put :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` at +the end of the list, because it's a last resort. + +For more on middleware, read the :ref:`middleware docs +<topics-http-middleware>`. + +.. admonition:: Ensure that your 404 template works + + Note that the + :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` + only steps in once another view has successfully produced a 404 response. + If another view or middleware class attempts to produce a 404 but ends up + raising an exception instead (such as a ``TemplateDoesNotExist`` + exception if your site does not have an appropriate template to + use for HTTP 404 responses), the response will become an HTTP 500 + ("Internal Server Error") and the + :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` + will not attempt to serve a flat page. + +How to add, change and delete flatpages +======================================= + +Via the admin interface +----------------------- + +If you've activated the automatic Django admin interface, you should see a +"Flatpages" section on the admin index page. Edit flatpages as you edit any +other object in the system. + +Via the Python API +------------------ + +.. class:: models.FlatPage + + Flatpages are represented by a standard + :ref:`Django model <topics-db-models>`, + which lives in `django/contrib/flatpages/models.py`_. You can access + flatpage objects via the :ref:`Django database API <topics-db-queries>`. + +.. _django/contrib/flatpages/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models.py + +Flatpage templates +================== + +By default, flatpages are rendered via the template +:file:`flatpages/default.html`, but you can override that for a particular +flatpage. + +Creating the :file:`flatpages/default.html` template is your responsibility; +in your template directory, just create a :file:`flatpages` directory +containing a file :file:`default.html`. + +Flatpage templates are passed a single context variable, :data:`flatpage`, +which is the flatpage object. + +Here's a sample :file:`flatpages/default.html` template: + +.. code-block:: html+django + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" + "http://www.w3.org/TR/REC-html40/loose.dtd"> + <html> + <head> + <title>{{ flatpage.title }}</title> + </head> + <body> + {{ flatpage.content }} + </body> + </html> + +Since you're already entering raw HTML into the admin page for a flatpage, +both ``flatpage.title`` and ``flatpage.content`` are marked as **not** +requiring :ref:`automatic HTML escaping <automatic-html-escaping>` in the +template. diff --git a/docs/ref/contrib/formtools/form-preview.txt b/docs/ref/contrib/formtools/form-preview.txt new file mode 100644 index 0000000000..fa3fe16e7e --- /dev/null +++ b/docs/ref/contrib/formtools/form-preview.txt @@ -0,0 +1,110 @@ +.. _ref-contrib-formtools-form-preview: + +============ +Form preview +============ + +.. module:: django.contrib.formtools + :synopsis: Displays an HTML form, forces a preview, then does something + with the submission. + +Django comes with an optional "form preview" application that helps automate +the following workflow: + +"Display an HTML form, force a preview, then do something with the submission." + +To force a preview of a form submission, all you have to do is write a short +Python class. + +Overview +========= + +Given a :class:`django.forms.Form` subclass that you define, this +application takes care of the following workflow: + + 1. Displays the form as HTML on a Web page. + 2. Validates the form data when it's submitted via POST. + a. If it's valid, displays a preview page. + b. If it's not valid, redisplays the form with error messages. + 3. When the "confirmation" form is submitted from the preview page, calls + a hook that you define -- a + :meth:`~django.contrib.formtools.FormPreview.done()` method that gets + passed the valid data. + +The framework enforces the required preview by passing a shared-secret hash to +the preview page via hidden form fields. If somebody tweaks the form parameters +on the preview page, the form submission will fail the hash-comparison test. + +How to use ``FormPreview`` +========================== + + 1. Point Django at the default FormPreview templates. There are two ways to + do this: + + * Add ``'django.contrib.formtools'`` to your + :setting:`INSTALLED_APPS` setting. This will work if your + :setting:`TEMPLATE_LOADERS` setting includes the + ``app_directories`` template loader (which is the case by + default). See the :ref:`template loader docs <template-loaders>` + for more. + + * Otherwise, determine the full filesystem path to the + :file:`django/contrib/formtools/templates` directory, and add that + directory to your :setting:`TEMPLATE_DIRS` setting. + + 2. Create a :class:`~django.contrib.formtools.FormPreview` subclass that + overrides the :meth:`~django.contrib.formtools.FormPreview.done()` + method:: + + from django.contrib.formtools.preview import FormPreview + from myapp.models import SomeModel + + class SomeModelFormPreview(FormPreview): + + def done(self, request, cleaned_data): + # Do something with the cleaned_data, then redirect + # to a "success" page. + return HttpResponseRedirect('/form/success') + + This method takes an :class:`~django.http.HttpRequest` object and a + dictionary of the form data after it has been validated and cleaned. + It should return an :class:`~django.http.HttpResponseRedirect` that + is the end result of the form being submitted. + + 3. Change your URLconf to point to an instance of your + :class:`~django.contrib.formtools.FormPreview` subclass:: + + from myapp.preview import SomeModelFormPreview + from myapp.models import SomeModel + from django import forms + + ...and add the following line to the appropriate model in your URLconf:: + + (r'^post/$', SomeModelFormPreview(SomeModelForm)), + + where ``SomeModelForm`` is a Form or ModelForm class for the model. + + 4. Run the Django server and visit :file:`/post/` in your browser. + +``FormPreview`` classes +======================= + +.. class:: FormPreview + +A :class:`~django.contrib.formtools.FormPreview` class is a simple Python class +that represents the preview workflow. +:class:`~django.contrib.formtools.FormPreview` classes must subclass +``django.contrib.formtools.preview.FormPreview`` and override the +:meth:`~django.contrib.formtools.FormPreview.done()` method. They can live +anywhere in your codebase. + +``FormPreview`` templates +========================= + +By default, the form is rendered via the template :file:`formtools/form.html`, +and the preview page is rendered via the template :file:`formtools.preview.html`. +These values can be overridden for a particular form preview by setting +:attr:`~django.contrib.formtools.FormPreview.preview_template` and +:attr:`~django.contrib.formtools.FormPreview.form_template` attributes on the +FormPreview subclass. See :file:`django/contrib/formtools/templates` for the +default templates. diff --git a/docs/ref/contrib/formtools/form-wizard.txt b/docs/ref/contrib/formtools/form-wizard.txt new file mode 100644 index 0000000000..fe8d478d40 --- /dev/null +++ b/docs/ref/contrib/formtools/form-wizard.txt @@ -0,0 +1,316 @@ +.. _ref-contrib-formtools-form-wizard: + +=========== +Form wizard +=========== + +.. module:: django.contrib.formtools.wizard + :synopsis: Splits forms across multiple Web pages. + +**New in Django development version.** + +Django comes with an optional "form wizard" application that splits +:ref:`forms <topics-forms-index>` across multiple Web pages. It maintains +state in hashed HTML :samp:`<input type="hidden">` fields, and the data isn't +processed server-side until the final form is submitted. + +You might want to use this if you have a lengthy form that would be too +unwieldy for display on a single page. The first page might ask the user for +core information, the second page might ask for less important information, +etc. + +The term "wizard," in this context, is `explained on Wikipedia`_. + +.. _explained on Wikipedia: http://en.wikipedia.org/wiki/Wizard_%28software%29 +.. _forms: ../forms/ + +How it works +============ + +Here's the basic workflow for how a user would use a wizard: + + 1. The user visits the first page of the wizard, fills in the form and + submits it. + 2. The server validates the data. If it's invalid, the form is displayed + again, with error messages. If it's valid, the server calculates a + secure hash of the data and presents the user with the next form, + saving the validated data and hash in :samp:`<input type="hidden">` + fields. + 3. Step 1 and 2 repeat, for every subsequent form in the wizard. + 4. Once the user has submitted all the forms and all the data has been + validated, the wizard processes the data -- saving it to the database, + sending an e-mail, or whatever the application needs to do. + +Usage +===== + +This application handles as much machinery for you as possible. Generally, you +just have to do these things: + + 1. Define a number of :mod:`django.forms` + :class:`~django.forms.forms.Form` classes -- one per wizard page. + + 2. Create a :class:`~django.contrib.formtools.wizard.FormWizard` class + that specifies what to do once all of your forms have been submitted + and validated. This also lets you override some of the wizard's behavior. + + 3. Create some templates that render the forms. You can define a single, + generic template to handle every one of the forms, or you can define a + specific template for each form. + + 4. Point your URLconf at your + :class:`~django.contrib.formtools.wizard.FormWizard` class. + +Defining ``Form`` classes +========================= + +The first step in creating a form wizard is to create the :class:`~django.forms.forms.Form` classes. +These should be standard :mod:`django.forms` +:class:`~django.forms.forms.Form` classes, covered in the +:ref:`forms documentation <topics-forms-index>`. + +These classes can live anywhere in your codebase, but convention is to put them +in a file called :file:`forms.py` in your application. + +For example, let's write a "contact form" wizard, where the first page's form +collects the sender's e-mail address and subject, and the second page collects +the message itself. Here's what the :file:`forms.py` might look like:: + + from django import forms + + class ContactForm1(forms.Form): + subject = forms.CharField(max_length=100) + sender = forms.EmailField() + + class ContactForm2(forms.Form): + message = forms.CharField(widget=forms.Textarea) + +**Important limitation:** Because the wizard uses HTML hidden fields to store +data between pages, you may not include a :class:`~django.forms.fields.FileField` +in any form except the last one. + +Creating a ``FormWizard`` class +=============================== + +The next step is to create a :class:`~django.contrib.formtools.wizard.FormWizard` +class, which should be a subclass of ``django.contrib.formtools.wizard.FormWizard``. + +As your :class:`~django.forms.forms.Form` classes, this +:class:`~django.contrib.formtools.wizard.FormWizard` class can live anywhere +in your codebase, but convention is to put it in :file:`forms.py`. + +The only requirement on this subclass is that it implement a +:meth:`~django.contrib.formtools.wizard.FormWizard.done()` method, +which specifies what should happen when the data for *every* form is submitted +and validated. This method is passed two arguments: + + * ``request`` -- an :class:`~django.http.HttpRequest` object + * ``form_list`` -- a list of :mod:`django.forms` + :class:`~django.forms.forms.Form` classes + +In this simplistic example, rather than perform any database operation, the +method simply renders a template of the validated data:: + + from django.shortcuts import render_to_response + from django.contrib.formtools.wizard import FormWizard + + class ContactWizard(FormWizard): + def done(self, request, form_list): + return render_to_response('done.html', { + 'form_data': [form.cleaned_data for form in form_list], + }) + +Note that this method will be called via ``POST``, so it really ought to be a +good Web citizen and redirect after processing the data. Here's another +example:: + + from django.http import HttpResponseRedirect + from django.contrib.formtools.wizard import FormWizard + + class ContactWizard(FormWizard): + def done(self, request, form_list): + do_something_with_the_form_data(form_list) + return HttpResponseRedirect('/page-to-redirect-to-when-done/') + +See the section `Advanced FormWizard methods`_ below to learn about more +:class:`~django.contrib.formtools.wizard.FormWizard` hooks. + +Creating templates for the forms +================================ + +Next, you'll need to create a template that renders the wizard's forms. By +default, every form uses a template called :file:`forms/wizard.html`. (You can +change this template name by overriding +:meth:`~django.contrib.formtools.wizard..get_template()`, which is documented +below. This hook also allows you to use a different template for each form.) + +This template expects the following context: + + * ``step_field`` -- The name of the hidden field containing the step. + * ``step0`` -- The current step (zero-based). + * ``step`` -- The current step (one-based). + * ``step_count`` -- The total number of steps. + * ``form`` -- The :class:`~django.forms.forms.Form` instance for the + current step (either empty or with errors). + * ``previous_fields`` -- A string representing every previous data field, + plus hashes for completed forms, all in the form of hidden fields. Note + that you'll need to run this through the + :meth:`~django.template.defaultfilters.safe` template filter, to prevent + auto-escaping, because it's raw HTML. + +It will also be passed any objects in :data:`extra_context`, which is a +dictionary you can specify that contains extra values to add to the context. +You can specify it in two ways: + + * Set the :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context` + attribute on your :class:`~django.contrib.formtools.wizard.FormWizard` + subclass to a dictionary. + + * Pass :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context` + as extra parameters in the URLconf. + +Here's a full example template:: + + {% extends "base.html" %} + + {% block content %} + <p>Step {{ step }} of {{ step_count }}</p> + <form action="." method="post"> + <table> + {{ form }} + </table> + <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> + {{ previous_fields|safe }} + <input type="submit"> + </form> + {% endblock %} + +Note that ``previous_fields``, ``step_field`` and ``step0`` are all required +for the wizard to work properly. + +Hooking the wizard into a URLconf +================================= + +Finally, give your new :class:`~django.contrib.formtools.wizard.FormWizard` +object a URL in ``urls.py``. The wizard takes a list of your form objects as +arguments:: + + from django.conf.urls.defaults import * + from mysite.testapp.forms import ContactForm1, ContactForm2, ContactWizard + + urlpatterns = patterns('', + (r'^contact/$', ContactWizard([ContactForm1, ContactForm2])), + ) + +Advanced FormWizard methods +=========================== + +.. class:: FormWizard + + Aside from the :meth:`~django.contrib.formtools.wizard.FormWizard.done()` + method, :class:`~django.contrib.formtools.wizard.FormWizard` offers a few + advanced method hooks that let you customize how your wizard works. + + Some of these methods take an argument ``step``, which is a zero-based counter + representing the current step of the wizard. (E.g., the first form is ``0`` and + the second form is ``1``.) + +.. method:: FormWizard.prefix_for_step + + Given the step, returns a :class:`~django.forms.forms.Form` prefix to + use. By default, this simply uses the step itself. For more, see the + :ref:`form prefix documentation <form-prefix>`. + + Default implementation:: + + def prefix_for_step(self, step): + return str(step) + +.. method:: FormWizard.render_hash_failure + + Renders a template if the hash check fails. It's rare that you'd need to + override this. + + Default implementation:: + + def render_hash_failure(self, request, step): + return self.render(self.get_form(step), request, step, + context={'wizard_error': 'We apologize, but your form has expired. Please continue filling out the form from this page.'}) + +.. method:: FormWizard.security_hash + + Calculates the security hash for the given request object and :class:`~django.forms.forms.Form` instance. + + By default, this uses an MD5 hash of the form data and your + :setting:`SECRET_KEY` setting. It's rare that somebody would need to override + this. + + Example:: + + def security_hash(self, request, form): + return my_hash_function(request, form) + +.. method:: FormWizard.parse_params + + A hook for saving state from the request object and ``args`` / ``kwargs`` that + were captured from the URL by your URLconf. + + By default, this does nothing. + + Example:: + + def parse_params(self, request, *args, **kwargs): + self.my_state = args[0] + +.. method:: FormWizard.get_template + + Returns the name of the template that should be used for the given step. + + By default, this returns :file:`'forms/wizard.html'`, regardless of step. + + Example:: + + def get_template(self, step): + return 'myapp/wizard_%s.html' % step + + If :meth:`~FormWizard.get_template` returns a list of strings, then the wizard will use the + template system's :func:`~django.template.loader.select_template()` + function, + :ref:`explained in the template docs <ref-templates-api-the-python-api>`. + This means the system will use the first template that exists on the + filesystem. For example:: + + def get_template(self, step): + return ['myapp/wizard_%s.html' % step, 'myapp/wizard.html'] + + .. _explained in the template docs: ../templates_python/#the-python-api + +.. method:: FormWizard.render_template + + Renders the template for the given step, returning an + :class:`~django.http.HttpResponseRedirect` object. + + Override this method if you want to add a custom context, return a different + MIME type, etc. If you only need to override the template name, use + :meth:`~FormWizard.get_template` instead. + + The template will be rendered with the context documented in the + "Creating templates for the forms" section above. + +.. method:: FormWizard.process_step + + Hook for modifying the wizard's internal state, given a fully validated + :class:`~django.forms.forms.Form` object. The Form is guaranteed to + have clean, valid data. + + This method should *not* modify any of that data. Rather, it might want to set + ``self.extra_context`` or dynamically alter ``self.form_list``, based on + previously submitted forms. + + Note that this method is called every time a page is rendered for *all* + submitted steps. + + The function signature:: + + def process_step(self, request, form, step): + # ... diff --git a/docs/ref/contrib/formtools/index.txt b/docs/ref/contrib/formtools/index.txt new file mode 100644 index 0000000000..92010a25db --- /dev/null +++ b/docs/ref/contrib/formtools/index.txt @@ -0,0 +1,12 @@ +.. _ref-contrib-formtools-index: + +django.contrib.formtools +======================== + +A set of high-level abstractions for Django forms (:mod:`django.forms`). + +.. toctree:: + :maxdepth: 1 + + form-preview + form-wizard diff --git a/docs/ref/contrib/humanize.txt b/docs/ref/contrib/humanize.txt new file mode 100644 index 0000000000..4a544f037c --- /dev/null +++ b/docs/ref/contrib/humanize.txt @@ -0,0 +1,91 @@ +.. _ref-contrib-humanize: + +======================== +django.contrib.humanize +======================== + +.. module:: django.contrib.humanize + :synopsis: A set of Django template filters useful for adding a "human + touch" to data. + +A set of Django template filters useful for adding a "human touch" to data. + +To activate these filters, add ``'django.contrib.humanize'`` to your +:setting:`INSTALLED_APPS` setting. Once you've done that, use +``{% load humanize %}`` in a template, and you'll have access to these filters: + +apnumber +-------- + +For numbers 1-9, returns the number spelled out. Otherwise, returns the +number. This follows Associated Press style. + +Examples: + + * ``1`` becomes ``'one'``. + * ``2`` becomes ``'two'``. + * ``10`` becomes ``10``. + +You can pass in either an integer or a string representation of an integer. + +intcomma +-------- + +Converts an integer to a string containing commas every three digits. + +Examples: + + * ``4500`` becomes ``'4,500'``. + * ``45000`` becomes ``'45,000'``. + * ``450000`` becomes ``'450,000'``. + * ``4500000`` becomes ``'4,500,000'``. + +You can pass in either an integer or a string representation of an integer. + +intword +------- + +Converts a large integer to a friendly text representation. Works best for +numbers over 1 million. + +Examples: + + * ``1000000`` becomes ``'1.0 million'``. + * ``1200000`` becomes ``'1.2 million'``. + * ``1200000000`` becomes ``'1.2 billion'``. + +Values up to 1000000000000000 (one quadrillion) are supported. + +You can pass in either an integer or a string representation of an integer. + +ordinal +------- + +Converts an integer to its ordinal as a string. + +Examples: + + * ``1`` becomes ``'1st'``. + * ``2`` becomes ``'2nd'``. + * ``3`` becomes ``'3rd'``. + +You can pass in either an integer or a string representation of an integer. + +naturalday +---------- + +**New in Django development version** + +For dates that are the current day or within one day, return "today", +"tomorrow" or "yesterday", as appropriate. Otherwise, format the date using +the passed in format string. + +**Argument:** Date formatting string as described in the :ttag:`now` tag. + +Examples (when 'today' is 17 Feb 2007): + + * ``16 Feb 2007`` becomes ``yesterday``. + * ``17 Feb 2007`` becomes ``today``. + * ``18 Feb 2007`` becomes ``tomorrow``. + * Any other day is formatted according to given argument or the + :setting:`DATE_FORMAT` setting if no argument is given. diff --git a/docs/ref/contrib/index.txt b/docs/ref/contrib/index.txt new file mode 100644 index 0000000000..e6c693d905 --- /dev/null +++ b/docs/ref/contrib/index.txt @@ -0,0 +1,199 @@ +.. _ref-contrib-index: + +============================ +The "django.contrib" add-ons +============================ + +Django aims to follow Python's `"batteries included" philosophy`_. It ships +with a variety of extra, optional tools that solve common Web-development +problems. + +This code lives in ``django/contrib`` in the Django distribution. This document +gives a rundown of the packages in ``contrib``, along with any dependencies +those packages have. + +.. admonition:: Note + + For most of these add-ons -- specifically, the add-ons that include either + models or template tags -- you'll need to add the package name (e.g., + ``'django.contrib.admin'``) to your ``INSTALLED_APPS`` setting and re-run + ``manage.py syncdb``. + +.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included + +.. toctree:: + :maxdepth: 1 + + admin + auth + contenttypes + csrf + databrowse + flatpages + formtools/index + humanize + localflavor + redirects + sitemaps + sites + syndication + webdesign + +admin +===== + +The automatic Django administrative interface. For more information, see +:ref:`Tutorial 2 <intro-tutorial02>` and the +:ref:`admin documentation <ref-contrib-admin>`. + +Requires the auth_ and contenttypes_ contrib packages to be installed. + +auth +==== + +Django's authentication framework. + +See :ref:`topics-auth`. + +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. + +See the :ref:`contenttypes documentation <ref-contrib-contenttypes>`. + +csrf +==== + +A middleware for preventing Cross Site Request Forgeries + +See the :ref:`csrf documentation <ref-contrib-csrf>`. + +flatpages +========= + +A framework for managing simple "flat" HTML content in a database. + +See the :ref:`flatpages documentation <ref-contrib-flatpages>`. + +Requires the sites_ contrib package to be installed as well. + +formtools +========= + +A set of high-level abstractions for Django forms (django.forms). + +django.contrib.formtools.preview +-------------------------------- + +An abstraction of the following workflow: + +"Display an HTML form, force a preview, then do something with the submission." + +See the :ref:`form preview documentation <ref-contrib-formtools-form-preview>`. + +django.contrib.formtools.wizard +-------------------------------- + +Splits forms across multiple Web pages. + +See the :ref:`form wizard documentation <ref-contrib-formtools-form-wizard>`. + +humanize +======== + +A set of Django template filters useful for adding a "human touch" to data. + +See the :ref:`humanize documentation <ref-contrib-humanize>`. + +localflavor +=========== + +A collection of various Django snippets that are useful only for a particular +country or culture. For example, ``django.contrib.localflavor.us.forms`` +contains a ``USZipCodeField`` that you can use to validate U.S. zip codes. + +See the :ref:`localflavor documentation <ref-contrib-localflavor>`. + +.. _ref-contrib-markup: + +markup +====== + +A collection of template filters that implement common markup languages: + + * ``textile`` -- implements `Textile`_ + * ``markdown`` -- implements `Markdown`_ + * ``restructuredtext`` -- implements `ReST (ReStructured Text)`_ + +In each case, the filter expects formatted markup as a string and returns a +string representing the marked-up text. For example, the ``textile`` filter +converts text that is marked-up in Textile format to HTML. + +To activate these filters, add ``'django.contrib.markup'`` to your +:setting:`INSTALLED_APPS` setting. Once you've done that, use ``{% load markup %}`` in +a template, and you'll have access to these filters. For more documentation, +read the source code in django/contrib/markup/templatetags/markup.py. + +.. _Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29 +.. _Markdown: http://en.wikipedia.org/wiki/Markdown +.. _ReST (ReStructured Text): http://en.wikipedia.org/wiki/ReStructuredText + +redirects +========= + +A framework for managing redirects. + +See the :ref:`redirects documentation <ref-contrib-redirects>`. + +sessions +======== + +A framework for storing data in anonymous sessions. + +See the :ref:`sessions documentation <topics-http-sessions>`. + +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 :ref:`sites documentation <ref-contrib-sites>`. + +sitemaps +======== + +A framework for generating Google sitemap XML files. + +See the :ref:`sitemaps documentation <ref-contrib-sitemaps>`. + +syndication +=========== + +A framework for generating syndication feeds, in RSS and Atom, quite easily. + +See the :ref:`syndication documentation <ref-contrib-syndication>`. + +webdesign +========= + +Helpers and utilities targeted primarily at Web *designers* rather than +Web *developers*. + +See the :ref:`Web design helpers documentation <ref-contrib-webdesign>`. + +Other add-ons +============= + +If you have an idea for functionality to include in ``contrib``, let us know! +Code it up, and post it to the `django-users mailing list`_. + +.. _django-users mailing list: http://groups.google.com/group/django-users diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt new file mode 100644 index 0000000000..9b9a4a38a3 --- /dev/null +++ b/docs/ref/contrib/localflavor.txt @@ -0,0 +1,651 @@ +.. _ref-contrib-localflavor: + +========================== +The "local flavor" add-ons +========================== + +.. module:: django.contrib.localflavor + :synopsis: A collection of various Django snippets that are useful only for + a particular country or culture. + +Following its "batteries included" philosophy, Django comes with assorted +pieces of code that are useful for particular countries or cultures. These are +called the "local flavor" add-ons and live in the +:mod:`django.contrib.localflavor` package. + +Inside that package, country- or culture-specific code is organized into +subpackages, named using `ISO 3166 country codes`_. + +Most of the ``localflavor`` add-ons are localized form components deriving +from the :ref:`forms <topics-forms-index>` framework -- for example, a +:class:`~django.contrib.localflavor.us.forms.USStateField` that knows how to +validate U.S. state abbreviations, and a +:class:`~django.contrib.localflavor.fi.forms.FISocialSecurityNumber` that +knows how to validate Finnish social security numbers. + +To use one of these localized components, just import the relevant subpackage. +For example, here's how you can create a form with a field representing a +French telephone number:: + + from django import forms + from django.contrib.localflavor import fr + + class MyForm(forms.Form): + my_french_phone_no = fr.forms.FRPhoneNumberField() + +Supported countries +=================== + +Countries currently supported by :mod:`~django.contrib.localflavor` are: + + * Argentina_ + * Australia_ + * Austria_ + * Brazil_ + * Canada_ + * Chile_ + * Finland_ + * France_ + * Germany_ + * Holland_ + * Iceland_ + * India_ + * Italy_ + * Japan_ + * Mexico_ + * Norway_ + * Peru_ + * Poland_ + * Romania_ + * Slovakia_ + * `South Africa`_ + * Spain_ + * Switzerland_ + * `United Kingdom`_ + * `United States of America`_ + +The ``django.contrib.localflavor`` package also includes a ``generic`` subpackage, +containing useful code that is not specific to one particular country or +culture. Currently, it defines date and datetime input fields based on those +from :ref:`forms <topics-forms-index>`, but with non-US default formats. +Here's an example of how to use them:: + + from django import forms + from django.contrib.localflavor import generic + + class MyForm(forms.Form): + my_date_field = generic.forms.DateField() + +.. _ISO 3166 country codes: http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm +.. _Argentina: `Argentina (ar)`_ +.. _Australia: `Australia (au)`_ +.. _Austria: `Austria (at)`_ +.. _Brazil: `Brazil (br)`_ +.. _Canada: `Canada (ca)`_ +.. _Chile: `Chile (cl)`_ +.. _Finland: `Finland (fi)`_ +.. _France: `France (fr)`_ +.. _Germany: `Germany (de)`_ +.. _Holland: `Holland (nl)`_ +.. _Iceland: `Iceland (is\_)`_ +.. _India: `India (in\_)`_ +.. _Italy: `Italy (it)`_ +.. _Japan: `Japan (jp)`_ +.. _Mexico: `Mexico (mx)`_ +.. _Norway: `Norway (no)`_ +.. _Peru: `Peru (pe)`_ +.. _Poland: `Poland (pl)`_ +.. _Romania: `Romania (ro)`_ +.. _Slovakia: `Slovakia (sk)`_ +.. _South Africa: `South Africa (za)`_ +.. _Spain: `Spain (es)`_ +.. _Switzerland: `Switzerland (ch)`_ +.. _United Kingdom: `United Kingdom (uk)`_ +.. _United States of America: `United States of America (us)`_ + +Adding flavors +============== + +We'd love to add more of these to Django, so please `create a ticket`_ with +any code you'd like to contribute. One thing we ask is that you please use +Unicode objects (``u'mystring'``) for strings, rather than setting the encoding +in the file. See any of the existing flavors for examples. + +.. _create a ticket: http://code.djangoproject.com/simpleticket + +Argentina (``ar``) +============================================= + +.. class:: ar.forms.ARPostalCodeField + + A form field that validates input as either a classic four-digit Argentinian + postal code or a CPA_. + +.. _CPA: http://www.correoargentino.com.ar/consulta_cpa/home.php + +.. class:: ar.forms.ARDNIField + + A form field that validates input as a Documento Nacional de Identidad (DNI) + number. + +.. class:: ar.forms.ARCUITField + + A form field that validates input as a Codigo Unico de Identificacion + Tributaria (CUIT) number. + +.. class:: ar.forms.ARProvinceSelect + + A ``Select`` widget that uses a list of Argentina's provinces and autonomous + cities as its choices. + +Australia (``au``) +============================================= + +.. class:: au.forms.AUPostCodeField + + A form field that validates input as an Australian postcode. + +.. class:: au.forms.AUPhoneNumberField + + A form field that validates input as an Australian phone number. Valid numbers + have ten digits. + +.. class:: au.forms.AUStateSelect + + A ``Select`` widget that uses a list of Australian states/territories as its + choices. + +Austria (``at``) +================ + +.. class:: at.forms.ATZipCodeField + + A form field that validates its input as an Austrian zip code. + +.. class:: at.forms.ATStateSelect + + A ``Select`` widget that uses a list of Austrian states as its choices. + +.. class:: at.forms.ATSocialSecurityNumberField + + A form field that validates its input as an Austrian social security number. + +Brazil (``br``) +=============== + +.. class:: br.forms.BRPhoneNumberField + + A form field that validates input as a Brazilian phone number, with the format + XX-XXXX-XXXX. + +.. class:: br.forms.BRZipCodeField + + A form field that validates input as a Brazilian zip code, with the format + XXXXX-XXX. + +.. class:: br.forms.BRStateSelect + + A ``Select`` widget that uses a list of Brazilian states/territories as its + choices. + +Canada (``ca``) +=============== + +.. class:: ca.forms.CAPhoneNumberField + + A form field that validates input as a Canadian phone number, with the format + XXX-XXX-XXXX. + +.. class:: ca.forms.CAPostalCodeField + + A form field that validates input as a Canadian postal code, with the format + XXX XXX. + +.. class:: ca.forms.CAProvinceField + + A form field that validates input as a Canadian province name or abbreviation. + +.. class:: ca.forms.CASocialInsuranceNumberField + + A form field that validates input as a Canadian Social Insurance Number (SIN). + A valid number must have the format XXX-XXX-XXX and pass a `Luhn mod-10 + checksum`_. + +.. _Luhn mod-10 checksum: http://en.wikipedia.org/wiki/Luhn_algorithm + +.. class:: ca.forms.CAProvinceSelect + + A ``Select`` widget that uses a list of Canadian provinces and territories as + its choices. + +Chile (``cl``) +============== + +.. class:: cl.forms.CLRutField + + A form field that validates input as a Chilean national identification number + ('Rol Unico Tributario' or RUT). The valid format is XX.XXX.XXX-X. + +.. class:: cl.forms.CLRegionSelect + + A ``Select`` widget that uses a list of Chilean regions (Regiones) as its + choices. + +Finland (``fi``) +================ + +.. class:: fi.forms.FISocialSecurityNumber + + A form field that validates input as a Finnish social security number. + +.. class:: fi.forms.FIZipCodeField + + A form field that validates input as a Finnish zip code. Valid codes + consist of five digits. + +.. class:: fi.forms.FIMunicipalitySelect + + A ``Select`` widget that uses a list of Finnish municipalities as its + choices. + +France (``fr``) +=============== + +.. class:: fr.forms.FRPhoneNumberField + + A form field that validates input as a French local phone number. The + correct format is 0X XX XX XX XX. 0X.XX.XX.XX.XX and 0XXXXXXXXX validate + but are corrected to 0X XX XX XX XX. + +.. class:: fr.forms.FRZipCodeField + + A form field that validates input as a French zip code. Valid codes + consist of five digits. + +.. class:: fr.forms.FRDepartmentSelect + + A ``Select`` widget that uses a list of French departments as its choices. + +Germany (``de``) +================ + +.. class:: de.forms.DEIdentityCardNumberField + + A form field that validates input as a German identity card number + (Personalausweis_). Valid numbers have the format + XXXXXXXXXXX-XXXXXXX-XXXXXXX-X, with no group consisting entirely of zeroes. + +.. _Personalausweis: http://de.wikipedia.org/wiki/Personalausweis + +.. class:: de.forms.DEZipCodeField + + A form field that validates input as a German zip code. Valid codes + consist of five digits. + +.. class:: de.forms.DEStateSelect + + A ``Select`` widget that uses a list of German states as its choices. + +Holland (``nl``) +================ + +.. class:: nl.forms.NLPhoneNumberField + + A form field that validates input as a Dutch telephone number. + +.. class:: nl.forms.NLSofiNumberField + + A form field that validates input as a Dutch social security number + (SoFI/BSN). + +.. class:: nl.forms.NLZipCodeField + + A form field that validates input as a Dutch zip code. + +.. class:: nl.forms.NLProvinceSelect + + A ``Select`` widget that uses a list of Dutch provinces as its list of + choices. + +Iceland (``is_``) +================= + +.. class:: is_.forms.ISIdNumberField + + A form field that validates input as an Icelandic identification number + (kennitala). The format is XXXXXX-XXXX. + +.. class:: is_.forms.ISPhoneNumberField + + A form field that validates input as an Icelandtic phone number (seven + digits with an optional hyphen or space after the first three digits). + +.. class:: is_.forms.ISPostalCodeSelect + + A ``Select`` widget that uses a list of Icelandic postal codes as its + choices. + +India (``in_``) +=============== + +.. class:: in.forms.INStateField + + A form field that validates input as an Indian state/territory name or + abbreviation. Input is normalized to the standard two-letter vehicle + registration abbreviation for the given state or territory. + +.. class:: in.forms.INZipCodeField + + A form field that validates input as an Indian zip code, with the + format XXXXXXX. + +.. class:: in.forms.INStateSelect + + A ``Select`` widget that uses a list of Indian states/territories as its + choices. + +Italy (``it``) +============== + +.. class:: it.forms.ITSocialSecurityNumberField + + A form field that validates input as an Italian social security number + (`codice fiscale`_). + +.. _codice fiscale: http://www.agenziaentrate.it/ilwwcm/connect/Nsi/Servizi/Codice+fiscale+-+tessera+sanitaria/Codice+fiscale/NSI+Informazioni+sulla+codificazione+delle+persone+fisiche + +.. class:: it.forms.ITVatNumberField + + A form field that validates Italian VAT numbers (partita IVA). + +.. class:: it.forms.ITZipCodeField + + A form field that validates input as an Italian zip code. Valid codes + must have five digits. + +.. class:: it.forms.ITProvinceSelect + + A ``Select`` widget that uses a list of Italian provinces as its choices. + +.. class:: it.forms.ITRegionSelect + + A ``Select`` widget that uses a list of Italian regions as its choices. + +Japan (``jp``) +============== + +.. class:: jp.forms.JPPostalCodeField + + A form field that validates input as a Japanese postcode. It accepts seven + digits, with or without a hyphen. + +.. class:: jp.forms.JPPrefectureSelect + + A ``Select`` widget that uses a list of Japanese prefectures as its choices. + +Mexico (``mx``) +=============== + +.. class:: mx.forms.MXStateSelect + + A ``Select`` widget that uses a list of Mexican states as its choices. + +Norway (``no``) +=============== + +.. class:: no.forms.NOSocialSecurityNumber + + A form field that validates input as a Norwegian social security number + (personnummer_). + +.. _personnummer: http://no.wikipedia.org/wiki/Personnummer + +.. class:: no.forms.NOZipCodeField + + A form field that validates input as a Norwegian zip code. Valid codes + have four digits. + +.. class:: no.forms.NOMunicipalitySelect + + A ``Select`` widget that uses a list of Norwegian municipalities (fylker) as + its choices. + +Peru (``pe``) +============= + +.. class:: pt.forms.PEDNIField + + A form field that validates input as a DNI (Peruvian national identity) + number. + +.. class:: pt.forms.PERUCField + + A form field that validates input as an RUC (Registro Unico de + Contribuyentes) number. Valid RUC numbers have 11 digits. + +.. class:: pt.forms.PEDepartmentSelect + + A ``Select`` widget that uses a list of Peruvian Departments as its choices. + +Poland (``pl``) +=============== + +.. class:: pl.forms.PLNationalIdentificationNumberField + + A form field that validates input as a Polish national identification number + (PESEL_). + +.. _PESEL: http://en.wikipedia.org/wiki/PESEL + +.. class:: pl.forms.PLNationalBusinessRegisterField + + A form field that validates input as a Polish National Official Business + Register Number (REGON_), having either seven or nine digits. The checksum + algorithm used for REGONs is documented at + http://wipos.p.lodz.pl/zylla/ut/nip-rego.html. + +.. _REGON: http://www.stat.gov.pl/bip/regon_ENG_HTML.htm + +.. class:: pl.forms.PLPostalCodeField + + A form field that validates input as a Polish postal code. The valid format + is XX-XXX, where X is a digit. + +.. class:: pl.forms.PLTaxNumberField + + A form field that validates input as a Polish Tax Number (NIP). Valid + formats are XXX-XXX-XX-XX or XX-XX-XXX-XXX. The checksum algorithm used + for NIPs is documented at http://wipos.p.lodz.pl/zylla/ut/nip-rego.html. + +.. class:: pl.forms.PLAdministrativeUnitSelect + + A ``Select`` widget that uses a list of Polish administrative units as its + choices. + +.. class:: pl.forms.PLVoivodeshipSelect + + A ``Select`` widget that uses a list of Polish voivodeships (administrative + provinces) as its choices. + +Romania (``ro``) +================ + +.. class:: ro.forms.ROCIFField + + A form field that validates Romanian fiscal identification codes (CIF). The + return value strips the leading RO, if given. + +.. class:: ro.forms.ROCNPField + + A form field that validates Romanian personal numeric codes (CNP). + +.. class:: ro.forms.ROCountyField + + A form field that validates its input as a Romanian county (judet) name or + abbreviation. It normalizes the input to the standard vehicle registration + abbreviation for the given county. This field will only accept names written + with diacritics; consider using ROCountySelect as an alternative. + +.. class:: ro.forms.ROCountySelect + + A ``Select`` widget that uses a list of Romanian counties (judete) as its + choices. + +.. class:: ro.forms.ROIBANField + + A form field that validates its input as a Romanian International Bank + Account Number (IBAN). The valid format is ROXX-XXXX-XXXX-XXXX-XXXX-XXXX, + with or without hyphens. + +.. class:: ro.forms.ROPhoneNumberField + + A form field that validates Romanian phone numbers, short special numbers + excluded. + +.. class:: ro.forms.ROPostalCodeField + + A form field that validates Romanian postal codes. + +Slovakia (``sk``) +================= + +.. class:: sk.forms.SKPostalCodeField + + A form field that validates input as a Slovak postal code. Valid formats + are XXXXX or XXX XX, where X is a digit. + +.. class:: sk.forms.SKDistrictSelect + + A ``Select`` widget that uses a list of Slovak districts as its choices. + +.. class:: sk.forms.SKRegionSelect + + A ``Select`` widget that uses a list of Slovak regions as its choices. + +South Africa (``za``) +===================== + +.. class:: za.forms.ZAIDField + + A form field that validates input as a South African ID number. Validation + uses the Luhn checksum and a simplistic (i.e., not entirely accurate) check + for birth date. + +.. class:: za.forms.ZAPostCodeField + + A form field that validates input as a South African postcode. Valid + postcodes must have four digits. + +Spain (``es``) +============== + +.. class:: es.forms.ESIdentityCardNumberField + + A form field that validates input as a Spanish NIF/NIE/CIF (Fiscal + Identification Number) code. + +.. class:: es.forms.ESCCCField + + A form field that validates input as a Spanish bank account number (Codigo + Cuenta Cliente or CCC). A valid CCC number has the format + EEEE-OOOO-CC-AAAAAAAAAA, where the E, O, C and A digits denote the entity, + office, checksum and account, respectively. The first checksum digit + validates the entity and office. The second checksum digit validates the + account. It is also valid to use a space as a delimiter, or to use no + delimiter. + +.. class:: es.forms.ESPhoneNumberField + + A form field that validates input as a Spanish phone number. Valid numbers + have nine digits, the first of which is 6, 8 or 9. + +.. class:: es.forms.ESPostalCodeField + + A form field that validates input as a Spanish postal code. Valid codes + have five digits, the first two being in the range 01 to 52, representing + the province. + +.. class:: es.forms.ESProvinceSelect + + A ``Select`` widget that uses a list of Spanish provinces as its choices. + +.. class:: es.forms.ESRegionSelect + + A ``Select`` widget that uses a list of Spanish regions as its choices. + +Switzerland (``ch``) +==================== + +.. class:: ch.forms.CHIdentityCardNumberField + + A form field that validates input as a Swiss identity card number. + A valid number must confirm to the X1234567<0 or 1234567890 format and + have the correct checksums -- see http://adi.kousz.ch/artikel/IDCHE.htm. + +.. class:: ch.forms.CHPhoneNumberField + + A form field that validates input as a Swiss phone number. The correct + format is 0XX XXX XX XX. 0XX.XXX.XX.XX and 0XXXXXXXXX validate but are + corrected to 0XX XXX XX XX. + +.. class:: ch.forms.CHZipCodeField + + A form field that validates input as a Swiss zip code. Valid codes + consist of four digits. + +.. class:: ch.forms.CHStateSelect + + A ``Select`` widget that uses a list of Swiss states as its choices. + +United Kingdom (``uk``) +======================= + +.. class:: uk.forms.UKPostcodeField + + A form field that validates input as a UK postcode. The regular + expression used is sourced from the schema for British Standard BS7666 + address types at http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd. + +.. class:: ch.forms.UKCountySelect + + A ``Select`` widget that uses a list of UK counties/regions as its choices. + +.. class:: ch.forms.UKNationSelect + + A ``Select`` widget that uses a list of UK nations as its choices. + +United States of America (``us``) +================================= + +.. class:: us.forms.USPhoneNumberField + + A form field that validates input as a U.S. phone number. + +.. class:: us.forms.USSocialSecurityNumberField + + A form field that validates input as a U.S. Social Security Number (SSN). + A valid SSN must obey the following rules: + + * Format of XXX-XX-XXXX + * No group of digits consisting entirely of zeroes + * Leading group of digits cannot be 666 + * Number not in promotional block 987-65-4320 through 987-65-4329 + * Number not one known to be invalid due to widespread promotional + use or distribution (e.g., the Woolworth's number or the 1962 + promotional number) + +.. class:: us.forms.USStateField + + A form field that validates input as a U.S. state name or abbreviation. It + normalizes the input to the standard two-letter postal service abbreviation + for the given state. + +.. class:: us.forms.USZipCodeField + + A form field that validates input as a U.S. ZIP code. Valid formats are + XXXXX or XXXXX-XXXX. + +.. class:: us.forms.USStateSelect + + A form ``Select`` widget that uses a list of U.S. states/territories as its + choices. diff --git a/docs/ref/contrib/redirects.txt b/docs/ref/contrib/redirects.txt new file mode 100644 index 0000000000..6f9c57c09d --- /dev/null +++ b/docs/ref/contrib/redirects.txt @@ -0,0 +1,72 @@ +.. _ref-contrib-redirects: + +================= +The redirects app +================= + +.. module:: django.contrib.redirects + :synopsis: A framework for managing redirects. + +Django comes with an optional redirects application. It lets you store simple +redirects in a database and handles the redirecting for you. + +Installation +============ + +To install the redirects app, follow these steps: + + 1. Add ``'django.contrib.redirects'`` to your :setting:`INSTALLED_APPS` + setting. + 2. Add ``'django.contrib.redirects.middleware.RedirectFallbackMiddleware'`` + to your :setting:`MIDDLEWARE_CLASSES` setting. + 3. Run the command :djadmin:`manage.py syncdb <syncdb>`. + +How it works +============ + +``manage.py syncdb`` creates a ``django_redirect`` table in your database. This +is a simple lookup table with ``site_id``, ``old_path`` and ``new_path`` fields. + +The ``RedirectFallbackMiddleware`` does all of the work. Each time any Django +application raises a 404 error, this middleware checks the redirects database +for the requested URL as a last resort. Specifically, it checks for a redirect +with the given ``old_path`` with a site ID that corresponds to the +:setting:`SITE_ID` setting. + + * If it finds a match, and ``new_path`` is not empty, it redirects to + ``new_path``. + * If it finds a match, and ``new_path`` is empty, it sends a 410 ("Gone") + HTTP header and empty (content-less) response. + * If it doesn't find a match, the request continues to be processed as + usual. + +The middleware only gets activated for 404s -- not for 500s or responses of any +other status code. + +Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you +can put ``RedirectFallbackMiddleware`` at the end of the list, because it's a +last resort. + +For more on middleware, read the :ref:`middleware docs +<topics-http-middleware>`. + +How to add, change and delete redirects +======================================= + +Via the admin interface +----------------------- + +If you've activated the automatic Django admin interface, you should see a +"Redirects" section on the admin index page. Edit redirects as you edit any +other object in the system. + +Via the Python API +------------------ + +.. class:: models.Redirect + + Redirects are represented by a standard :ref:`Django model <topics-db-models>`, + which lives in `django/contrib/redirects/models.py`_. You can access redirect + objects via the :ref:`Django database API <topics-db-queries>`. + +.. _django/contrib/redirects/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/redirects/models.py diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt new file mode 100644 index 0000000000..c95ded6712 --- /dev/null +++ b/docs/ref/contrib/sitemaps.txt @@ -0,0 +1,343 @@ +.. _ref-contrib-sitemaps: + +===================== +The sitemap framework +===================== + +.. module:: django.contrib.sitemaps + :synopsis: A framework for generating Google sitemap XML files. + +Django comes with a high-level sitemap-generating framework that makes +creating sitemap_ XML files easy. + +.. _sitemap: http://www.sitemaps.org/ + +Overview +======== + +A sitemap is an XML file on your Web site that tells search-engine indexers how +frequently your pages change and how "important" certain pages are in relation +to other pages on your site. This information helps search engines index your +site. + +The Django sitemap framework automates the creation of this XML file by letting +you express this information in Python code. + +It works much like Django's :ref:`syndication framework +<ref-contrib-syndication>`. To create a sitemap, just write a +:class:`~django.contrib.sitemaps.Sitemap` class and point to it in your +:ref:`URLconf <topics-http-urls>`. + +Installation +============ + +To install the sitemap app, follow these steps: + + 1. Add ``'django.contrib.sitemaps'`` to your :setting:`INSTALLED_APPS` + setting. + + 2. Make sure ``'django.template.loaders.app_directories.load_template_source'`` + is in your :setting:`TEMPLATE_LOADERS` setting. It's in there by default, + so you'll only need to change this if you've changed that setting. + + 3. Make sure you've installed the + :mod:`sites framework <django.contrib.sites>`. + +(Note: The sitemap application doesn't install any database tables. The only +reason it needs to go into :setting:`INSTALLED_APPS` is so that the +:func:`~django.template.loaders.app_directories.load_template_source` template +loader can find the default templates.) + +Initialization +============== + +To activate sitemap generation on your Django site, add this line to your +:ref:`URLconf <topics-http-urls>`:: + + (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) + +This tells Django to build a sitemap when a client accesses :file:`/sitemap.xml`. + +The name of the sitemap file is not important, but the location is. Search +engines will only index links in your sitemap for the current URL level and +below. For instance, if :file:`sitemap.xml` lives in your root directory, it may +reference any URL in your site. However, if your sitemap lives at +:file:`/content/sitemap.xml`, it may only reference URLs that begin with +:file:`/content/`. + +The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``. +``sitemaps`` should be a dictionary that maps a short section label (e.g., +``blog`` or ``news``) to its :class:`~django.contrib.sitemaps.Sitemap` class +(e.g., ``BlogSitemap`` or ``NewsSitemap``). It may also map to an *instance* of +a :class:`~django.contrib.sitemaps.Sitemap` class (e.g., +``BlogSitemap(some_var)``). + +Sitemap classes +=============== + +A :class:`~django.contrib.sitemaps.Sitemap` class is a simple Python +class that represents a "section" of entries in your sitemap. For example, +one :class:`~django.contrib.sitemaps.Sitemap` class could represent +all the entries of your weblog, while another could represent all of the +events in your events calendar. + +In the simplest case, all these sections get lumped together into one +:file:`sitemap.xml`, but it's also possible to use the framework to generate a +sitemap index that references individual sitemap files, one per section. (See +`Creating a sitemap index`_ below.) + +:class:`~django.contrib.sitemaps.Sitemap` classes must subclass +``django.contrib.sitemaps.Sitemap``. They can live anywhere in your codebase. + +A simple example +================ + +Let's assume you have a blog system, with an ``Entry`` model, and you want your +sitemap to include all the links to your individual blog entries. Here's how +your sitemap class might look:: + + from django.contrib.sitemaps import Sitemap + from mysite.blog.models import Entry + + class BlogSitemap(Sitemap): + changefreq = "never" + priority = 0.5 + + def items(self): + return Entry.objects.filter(is_draft=False) + + def lastmod(self, obj): + return obj.pub_date + +Note: + + * :attr:`~Sitemap.changefreq` and :attr:`~Sitemap.priority` are class + attributes corresponding to ``<changefreq>`` and ``<priority>`` elements, + respectively. They can be made callable as functions, as + :attr:`~Sitemap.lastmod` was in the example. + * :attr:`~Sitemap.items()` is simply a method that returns a list of + objects. The objects returned will get passed to any callable methods + corresponding to a sitemap property (:attr:`~Sitemap.location`, + :attr:`~Sitemap.lastmod`, :attr:`~Sitemap.changefreq`, and + :attr:`~Sitemap.priority`). + * :attr:`~Sitemap.lastmod` should return a Python ``datetime`` object. + * There is no :attr:`~Sitemap.location` method in this example, but you + can provide it in order to specify the URL for your object. By default, + :attr:`~Sitemap.location()` calls ``get_absolute_url()`` on each object + and returns the result. + +Sitemap class reference +======================= + +.. class:: Sitemap + + A ``Sitemap`` class can define the following methods/attributes: + + .. attribute:: Sitemap.items + + **Required.** A method that returns a list of objects. The framework + doesn't care what *type* of objects they are; all that matters is that + these objects get passed to the :attr:`~Sitemap.location()`, + :attr:`~Sitemap.lastmod()`, :attr:`~Sitemap.changefreq()` and + :attr:`~Sitemap.priority()` methods. + + .. attribute:: Sitemap.location + + **Optional.** Either a method or attribute. + + If it's a method, it should return the absolute URL for a given object as + returned by :attr:`~Sitemap.items()`. + + If it's an attribute, its value should be a string representing an absolute URL + to use for *every* object returned by :attr:`~Sitemap.items()`. + + In both cases, "absolute URL" means a URL that doesn't include the protocol or + domain. Examples: + + * Good: :file:`'/foo/bar/'` + * Bad: :file:`'example.com/foo/bar/'` + * Bad: :file:`'http://example.com/foo/bar/'` + + If :attr:`~Sitemap.location` isn't provided, the framework will call the + ``get_absolute_url()`` method on each object as returned by + :attr:`~Sitemap.items()`. + + .. attribute:: Sitemap.lastmod + + **Optional.** Either a method or attribute. + + If it's a method, it should take one argument -- an object as returned by + :attr:`~Sitemap.items()` -- and return that object's last-modified date/time, as a Python + ``datetime.datetime`` object. + + If it's an attribute, its value should be a Python ``datetime.datetime`` object + representing the last-modified date/time for *every* object returned by + :attr:`~Sitemap.items()`. + + .. attribute:: Sitemap.changefreq + + **Optional.** Either a method or attribute. + + If it's a method, it should take one argument -- an object as returned by + :attr:`~Sitemap.items()` -- and return that object's change frequency, as a Python string. + + If it's an attribute, its value should be a string representing the change + frequency of *every* object returned by :attr:`~Sitemap.items()`. + + Possible values for :attr:`~Sitemap.changefreq`, whether you use a method or attribute, are: + + * ``'always'`` + * ``'hourly'`` + * ``'daily'`` + * ``'weekly'`` + * ``'monthly'`` + * ``'yearly'`` + * ``'never'`` + + .. method:: Sitemap.priority + + **Optional.** Either a method or attribute. + + If it's a method, it should take one argument -- an object as returned by + :attr:`~Sitemap.items()` -- and return that object's priority, as either a string or float. + + If it's an attribute, its value should be either a string or float representing + the priority of *every* object returned by :attr:`~Sitemap.items()`. + + Example values for :attr:`~Sitemap.priority`: ``0.4``, ``1.0``. The default priority of a + page is ``0.5``. See the `sitemaps.org documentation`_ for more. + + .. _sitemaps.org documentation: http://www.sitemaps.org/protocol.html#prioritydef + +Shortcuts +========= + +The sitemap framework provides a couple convenience classes for common cases: + +.. class:: FlatPageSitemap + + The :class:`django.contrib.sitemaps.FlatPageSitemap` class looks at all + :mod:`flatpages <django.contrib.flatpages>` defined for the current + :setting:`SITE_ID` (see the + :mod:`sites documentation <django.contrib.sites>`) and + creates an entry in the sitemap. These entries include only the + :attr:`~Sitemap.location` attribute -- not :attr:`~Sitemap.lastmod`, + :attr:`~Sitemap.changefreq` or :attr:`~Sitemap.priority`. + +.. class:: GenericSitemap + + The :class:`django.contrib.sitemaps.GenericSitemap` class works with any + :ref:`generic views <ref-generic-views>` you already have. + To use it, create an instance, passing in the same :data:`info_dict` you pass to + the generic views. The only requirement is that the dictionary have a + :data:`queryset` entry. It may also have a :data:`date_field` entry that specifies a + date field for objects retrieved from the :data:`queryset`. This will be used for + the :attr:`~Sitemap.lastmod` attribute in the generated sitemap. You may + also pass :attr:`~Sitemap.priority` and :attr:`~Sitemap.changefreq` + keyword arguments to the :class:`~django.contrib.sitemaps.GenericSitemap` + constructor to specify these attributes for all URLs. + +Example +------- + +Here's an example of a :ref:`URLconf <topics-http-urls>` using both:: + + from django.conf.urls.defaults import * + from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap + from mysite.blog.models import Entry + + info_dict = { + 'queryset': Entry.objects.all(), + 'date_field': 'pub_date', + } + + sitemaps = { + 'flatpages': FlatPageSitemap, + 'blog': GenericSitemap(info_dict, priority=0.6), + } + + urlpatterns = patterns('', + # some generic view using info_dict + # ... + + # the sitemap + (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) + ) + +.. _URLconf: ../url_dispatch/ + +Creating a sitemap index +======================== + +The sitemap framework also has the ability to create a sitemap index that +references individual sitemap files, one per each section defined in your +:data:`sitemaps` dictionary. The only differences in usage are: + + * You use two views in your URLconf: :func:`django.contrib.sitemaps.views.index` + and :func:`django.contrib.sitemaps.views.sitemap`. + * The :func:`django.contrib.sitemaps.views.sitemap` view should take a + :data:`section` keyword argument. + +Here is what the relevant URLconf lines would look like for the example above:: + + (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}) + (r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) + +This will automatically generate a :file:`sitemap.xml` file that references both +:file:`sitemap-flatpages.xml` and :file:`sitemap-blog.xml`. The +:class:`~django.contrib.sitemaps.Sitemap` classes and the :data:`sitemaps` dict +don't change at all. + +If one of your sitemaps is going to have more than 50,000 URLs you should +create an index file. Your sitemap will be paginated and the index will +reflect that. + +Pinging Google +============== + +You may want to "ping" Google when your sitemap changes, to let it know to +reindex your site. The framework provides a function to do just that: +:func:`django.contrib.sitemaps.ping_google()`. + +.. function:: ping_google + + :func:`ping_google` takes an optional argument, :data:`sitemap_url`, + which should be the absolute URL of your site's sitemap (e.g., + :file:`'/sitemap.xml'`). If this argument isn't provided, + :func:`ping_google` will attempt to figure out your + sitemap by performing a reverse looking in your URLconf. + + :func:`ping_google` raises the exception + :exc:`django.contrib.sitemaps.SitemapNotFound` if it cannot determine your + sitemap URL. + +One useful way to call :func:`ping_google` is from a model's ``save()`` +method:: + + from django.contrib.sitemaps import ping_google + + class Entry(models.Model): + # ... + def save(self): + super(Entry, self).save() + try: + ping_google() + except Exception: + # Bare 'except' because we could get a variety + # of HTTP-related exceptions. + pass + +A more efficient solution, however, would be to call :func:`ping_google` from a +cron script, or some other scheduled task. The function makes an HTTP request +to Google's servers, so you may not want to introduce that network overhead +each time you call ``save()``. + +Pinging Google via `manage.py` +------------------------------ + +**New in Django development version** + +Once the sitemaps application is added to your project, you may also +ping the Google server's through the command line manage.py interface:: + + python manage.py ping_google [/sitemap.xml] diff --git a/docs/ref/contrib/sites.txt b/docs/ref/contrib/sites.txt new file mode 100644 index 0000000000..5a29370561 --- /dev/null +++ b/docs/ref/contrib/sites.txt @@ -0,0 +1,401 @@ +.. _ref-contrib-sites: + +===================== +The "sites" framework +===================== + +.. module:: django.contrib.sites + :synopsis: Lets you operate multiple web sites from the same database and + Django project + +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 a simple model: + +.. class:: django.contrib.sites.models.Site + +This model has :attr:`~django.contrib.sites.models.Site.domain` and +:attr:`~django.contrib.sites.models.Site.name` fields. The :setting:`SITE_ID` +setting specifies the database ID of the +:class:`~django.contrib.sites.models.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 :class:`~django.db.models.ManyToManyField` in the +``Article`` model:: + + from django.db import models + from django.contrib.sites.models import Site + + class Article(models.Model): + headline = models.CharField(max_length=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 :class:`~django.contrib.sites.models.Site` +model in a many-to-one relationship, using +:class:`~django.db.models.fields.related.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(max_length=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 the 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 :class:`~django.contrib.sites.models.Site` object +for the value of :setting:`settings.SITE_ID <SITE_ID>` is quite common, so +the :class:`~django.contrib.sites.models.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 +:class:`~django.contrib.sites.models.Site` +objects, we can abstract the "thank you" notice to use the values of the +current site's :attr:`~django.contrib.sites.models.Site.name` and +:attr:`~django.contrib.sites.models.Site.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 (:setting:`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 :file:`subject.txt` and :file:`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 :class:`~django.contrib.sites.models.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/' + +Caching the current ``Site`` object +=================================== + +**New in Django development version** + +As the current site is stored in the database, each call to +``Site.objects.get_current()`` could result in a database query. But Django is a +little cleverer than that: on the first request, the current site is cached, and +any subsequent call returns the cached data instead of hitting the database. + +If for any reason you want to force a database query, you can tell Django to +clear the cache using ``Site.objects.clear_cache()``:: + + # First call; current site fetched from database. + current_site = Site.objects.get_current() + # ... + + # Second call; current site fetched from cache. + current_site = Site.objects.get_current() + # ... + + # Force a database query for the third call. + Site.objects.clear_cache() + current_site = Site.objects.get_current() + +The ``CurrentSiteManager`` +========================== + +.. class:: django.contrib.sites.managers.CurrentSiteManager + +If :class:`~django.contrib.sites.models.Site`\s play a key role in your application, +consider using the helpful +:class:`~django.contrib.sites.managers.CurrentSiteManager` in your model(s). +It's a model :ref:`manager <topics-db-managers>` that automatically filters +its queries to include only objects associated with the current +:class:`~django.contrib.sites.models.Site`. + +Use :class:`~django.contrib.sites.managers.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(max_length=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 :setting:`SITE_ID` setting. + +Put another way, these two statements are equivalent:: + + Photo.objects.filter(site=settings.SITE_ID) + Photo.on_site.all() + +How did :class:`~django.contrib.sites.managers.CurrentSiteManager` know which +field of ``Photo`` was the :class:`~django.contrib.sites.models.Site`? It +defaults to looking for a field called +:class:`~django.contrib.sites.models.Site`. If your model has a +:class:`~django.db.models.fields.related.ForeignKey` or +:class:`~django.db.models.fields.related.ManyToManyField` called something +*other* than :class:`~django.contrib.sites.models.Site`, you need to explicitly +pass that as the parameter to +:class:`~django.contrib.sites.managers.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(max_length=100) + pub_date = models.DateField() + publish_on = models.ForeignKey(Site) + objects = models.Manager() + on_site = CurrentSiteManager('publish_on') + +If you attempt to use :class:`~django.contrib.sites.managers.CurrentSiteManager` +and pass a field name that doesn't exist, Django will raise a :exc:`ValueError`. + +Finally, note that you'll probably want to keep a normal (non-site-specific) +``Manager`` on your model, even if you use +:class:`~django.contrib.sites.managers.CurrentSiteManager`. As explained +in the :ref:`manager documentation <topics-db-managers>`, if you define a manager +manually, then Django won't create the automatic ``objects = models.Manager()`` +manager for you.Also, note that certain parts of Django -- namely, the Django admin site and +generic views -- use whichever manager is defined *first* in the model, so if +you want your admin site to have access to all objects (not just site-specific +ones), put ``objects = models.Manager()`` in your model, before you define +:class:`~django.contrib.sites.managers.CurrentSiteManager`. + +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 :setting:`SITE_ID` setting. + +Here's how Django uses the sites framework: + +* In the :mod:`redirects framework <django.contrib.redirects>`, each + redirect object is associated with a particular site. When Django searches + for a redirect, it takes into account the current :setting:`SITE_ID`. + +* In the comments framework, each comment is associated with a particular + site. When a comment is posted, its + :class:`~django.contrib.sites.models.Site` is set to the current + :setting:`SITE_ID`, and when comments are listed via the appropriate + template tag, only the comments for the current site are displayed. + +* In the :mod:`flatpages framework <django.contrib.flatpages>`, each + flatpage is associated with a particular site. When a flatpage is created, + you specify its :class:`~django.contrib.sites.models.Site`, and the + :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` + checks the current :setting:`SITE_ID` in retrieving flatpages to display. + +* In the :mod:`syndication framework <django.contrib.syndication>`, the + templates for ``title`` and ``description`` automatically have access to a + variable ``{{ site }}``, which is the + :class:`~django.contrib.sites.models.Site` object representing the current + site. Also, the hook for providing item URLs will use the ``domain`` from + the current :class:`~django.contrib.sites.models.Site` object if you don't + specify a fully-qualified domain. + +* In the :mod:`authentication framework <django.contrib.auth>`, the + :func:`django.contrib.auth.views.login` view passes the current + :class:`~django.contrib.sites.models.Site` name to the template as + ``{{ site_name }}``. + +* The shortcut view (:func:`django.views.defaults.shortcut`) uses the domain + of the current :class:`~django.contrib.sites.models.Site` object when + calculating an object's URL. + +* In the admin framework, the "view on site" link uses the current + :class:`~django.contrib.sites.models.Site` to work out the domain for the + site that it will redirect to. + + +``RequestSite`` objects +======================= + +.. _requestsite-objects: + +**New in Django development version** + +Some :ref:`django.contrib <ref-contrib-index>` applications take advantage of +the sites framework but are architected in a way that doesn't *require* the +sites framework to be installed in your database. (Some people don't want to, or +just aren't *able* to install the extra database table that the sites framework +requires.) For those cases, the framework provides a +:class:`~django.contrib.sites.models.RequestSite` class, which can be used as a +fallback when the database-backed sites framework is not available. + +A :class:`~django.contrib.sites.models.RequestSite` object has a similar +interface to a normal :class:`~django.contrib.sites.models.Site` object, except +its :meth:`~django.contrib.sites.models.RequestSite.__init__()` method takes an +:class:`~django.http.HttpRequest` object. It's able to deduce the +:attr:`~django.contrib.sites.models.RequestSite.domain` and +:attr:`~django.contrib.sites.models.RequestSite.name` by looking at the +request's domain. It has :meth:`~django.contrib.sites.models.RequestSite.save()` +and :meth:`~django.contrib.sites.models.RequestSite.delete()` methods to match +the interface of :class:`~django.contrib.sites.models.Site`, but the methods +raise :exc:`NotImplementedError`. diff --git a/docs/ref/contrib/syndication.txt b/docs/ref/contrib/syndication.txt new file mode 100644 index 0000000000..6624793460 --- /dev/null +++ b/docs/ref/contrib/syndication.txt @@ -0,0 +1,992 @@ +.. _ref-contrib-syndication: + +============================== +The syndication feed framework +============================== + +.. module:: django.contrib.syndication + :synopsis: A framework for generating syndication feeds, in RSS and Atom, + quite easily. + +Django comes with a high-level syndication-feed-generating framework that makes +creating RSS_ and Atom_ feeds easy. + +To create any syndication feed, all you have to do is write a short Python +class. You can create as many feeds as you want. + +Django also comes with a lower-level feed-generating API. Use this if you want +to generate feeds outside of a Web context, or in some other lower-level way. + +.. _RSS: http://www.whatisrss.com/ +.. _Atom: http://www.atomenabled.org/ + +The high-level framework +======================== + +Overview +-------- + +The high-level feed-generating framework is a view that's hooked to ``/feeds/`` +by default. Django uses the remainder of the URL (everything after ``/feeds/``) +to determine which feed to output. + +To create a feed, just write a :class:`~django.contrib.syndication.feeds.Feed` +class and point to it in your :ref:`URLconf <topics-http-urls>`. + +Initialization +-------------- + +If you're not using the latest Django development version, you'll need to make +sure Django's sites framework is installed -- including its database table. (See +the :mod:`sites framework documentation <django.contrib.sites>` for more +information.) This has changed in the Django development version; the +syndication feed framework no longer requires the sites framework. + +To activate syndication feeds on your Django site, add this line to your +:ref:`URLconf <topics-http-urls>`:: + + (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), + +This tells Django to use the RSS framework to handle all URLs starting with +:file:`"feeds/"`. (You can change that :file:`"feeds/"` prefix to fit your own +needs.) + +This URLconf line has an extra argument: ``{'feed_dict': feeds}``. Use this +extra argument to pass the syndication framework the feeds that should be +published under that URL. + +Specifically, :data:`feed_dict` should be a dictionary that maps a feed's slug +(short URL label) to its :class:`~django.contrib.syndication.feeds.Feed` class. + +You can define the ``feed_dict`` in the URLconf itself. Here's a full example +URLconf:: + + from django.conf.urls.defaults import * + from myproject.feeds import LatestEntries, LatestEntriesByCategory + + feeds = { + 'latest': LatestEntries, + 'categories': LatestEntriesByCategory, + } + + urlpatterns = patterns('', + # ... + (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', + {'feed_dict': feeds}), + # ... + ) + +The above example registers two feeds: + + * The feed represented by ``LatestEntries`` will live at ``feeds/latest/``. + * The feed represented by ``LatestEntriesByCategory`` will live at + ``feeds/categories/``. + +Once that's set up, you just need to define the +:class:`~django.contrib.syndication.feeds.Feed` classes themselves. + +Feed classes +------------ + +A :class:`~django.contrib.syndication.feeds.Feed` class is a simple Python class +that represents a syndication feed. A feed can be simple (e.g., a "site news" +feed, or a basic feed displaying the latest entries of a blog) or more complex +(e.g., a feed displaying all the blog entries in a particular category, where +the category is variable). + +:class:`~django.contrib.syndication.feeds.Feed` classes must subclass +``django.contrib.syndication.feeds.Feed``. They can live anywhere in your +codebase. + +A simple example +---------------- + +This simple example, taken from `chicagocrime.org`_, describes a feed of the +latest five news items:: + + from django.contrib.syndication.feeds import Feed + from chicagocrime.models import NewsItem + + class LatestEntries(Feed): + title = "Chicagocrime.org site news" + link = "/sitenews/" + description = "Updates on changes and additions to chicagocrime.org." + + def items(self): + return NewsItem.objects.order_by('-pub_date')[:5] + +Note: + +* The class subclasses ``django.contrib.syndication.feeds.Feed``. + +* :attr:`title`, :attr:`link` and :attr:`description` correspond to the + standard RSS ``<title>``, ``<link>`` and ``<description>`` elements, + respectively. + +* :meth:`items()` is, simply, a method that returns a list of objects that + should be included in the feed as ``<item>`` elements. Although this + example returns ``NewsItem`` objects using Django's + :ref:`object-relational mapper <ref-models-querysets>`, :meth:`items()` + doesn't have to return model instances. Although you get a few bits of + functionality "for free" by using Django models, :meth:`items()` can + return any type of object you want. + +* If you're creating an Atom feed, rather than an RSS feed, set the + :attr:`subtitle` attribute instead of the :attr:`description` attribute. + See `Publishing Atom and RSS feeds in tandem`_, later, for an example. + +One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``, +``<link>`` and ``<description>``. We need to tell the framework what data to put +into those elements. + + * To specify the contents of ``<title>`` and ``<description>``, create + :ref:`Django templates <topics-templates>` called + :file:`feeds/latest_title.html`` and + :file:`feeds/latest_description.html`, where :attr:`latest` is the + :attr:`slug` specified in the URLconf for the given feed. Note the + ``.html`` extension is required. The RSS system renders that template for + each item, passing it two template context variables: + + * ``{{ obj }}`` -- The current object (one of whichever objects you + returned in :meth:`items()`). + + * ``{{ site }}`` -- A :class:`django.contrib.sites.models.Site` object + representing the current site. This is useful for ``{{ site.domain + }}`` or ``{{ site.name }}``. Note that if you're using the latest + Django development version and do *not* have the Django sites + framework installed, this will be set to a + :class:`django.contrib.sites.models.RequestSite` object. See the + :ref:`RequestSite section of the sites framework documentation + <requestsite-objects>` for more. + + If you don't create a template for either the title or description, the + framework will use the template ``"{{ obj }}"`` by default -- that is, the + normal string representation of the object. You can also change the names + of these two templates by specifying ``title_template`` and + ``description_template`` as attributes of your + :class:`~django.contrib.syndication.feeds.Feed` class. + + * To specify the contents of ``<link>``, you have two options. For each item + in :meth:`items()`, Django first tries executing a ``get_absolute_url()`` + method on that object. If that method doesn't exist, it tries calling a + method :meth:`item_link()` in the + :class:`~django.contrib.syndication.feeds.Feed` class, passing it a single + parameter, :attr:`item`, which is the object itself. Both + ``get_absolute_url()`` and :meth:`item_link()` should return the item's + URL as a normal Python string. As with ``get_absolute_url()``, the result + of :meth:`item_link()` will be included directly in the URL, so you are + responsible for doing all necessary URL quoting and conversion to ASCII + inside the method itself. + + * For the LatestEntries example above, we could have very simple feed + templates: + + * latest_title.html: + + .. code-block:: html+django + + {{ obj.title }} + + * latest_description.html: + + .. code-block:: html+django + + {{ obj.description }} + +.. _chicagocrime.org: http://www.chicagocrime.org/ + +A complex example +----------------- + +The framework also supports more complex feeds, via parameters. + +For example, `chicagocrime.org`_ offers an RSS feed of recent crimes for every +police beat in Chicago. It'd be silly to create a separate +:class:`~django.contrib.syndication.feeds.Feed` class for each police beat; that +would violate the :ref:`DRY principle <dry>` and would couple data to +programming logic. Instead, the syndication framework lets you make generic +feeds that output items based on information in the feed's URL. + +On chicagocrime.org, the police-beat feeds are accessible via URLs like this: + + * :file:`/rss/beats/0613/` -- Returns recent crimes for beat 0613. + * :file:`/rss/beats/1424/` -- Returns recent crimes for beat 1424. + +The slug here is ``"beats"``. The syndication framework sees the extra URL bits +after the slug -- ``0613`` and ``1424`` -- and gives you a hook to tell it what +those URL bits mean, and how they should influence which items get published in +the feed. + +An example makes this clear. Here's the code for these beat-specific feeds:: + + from django.contrib.syndication.feeds import FeedDoesNotExist + + class BeatFeed(Feed): + def get_object(self, bits): + # In case of "/rss/beats/0613/foo/bar/baz/", or other such clutter, + # check that bits has only one member. + if len(bits) != 1: + raise ObjectDoesNotExist + return Beat.objects.get(beat__exact=bits[0]) + + def title(self, obj): + return "Chicagocrime.org: Crimes for beat %s" % obj.beat + + def link(self, obj): + if not obj: + raise FeedDoesNotExist + return obj.get_absolute_url() + + def description(self, obj): + return "Crimes recently reported in police beat %s" % obj.beat + + def items(self, obj): + return Crime.objects.filter(beat__id__exact=obj.id).order_by('-crime_date')[:30] + +Here's the basic algorithm the RSS framework follows, given this class and a +request to the URL :file:`/rss/beats/0613/`: + + * The framework gets the URL :file:`/rss/beats/0613/` and notices there's an + extra bit of URL after the slug. It splits that remaining string by the + slash character (``"/"``) and calls the + :class:`~django.contrib.syndication.feeds.Feed` class' + :meth:`get_object()` method, passing it the bits. In this case, bits is + ``['0613']``. For a request to :file:`/rss/beats/0613/foo/bar/`, bits + would be ``['0613', 'foo', 'bar']``. + + * :meth:`get_object()` is responsible for retrieving the given beat, from + the given ``bits``. In this case, it uses the Django database API to + retrieve the beat. Note that :meth:`get_object()` should raise + :exc:`django.core.exceptions.ObjectDoesNotExist` if given invalid + parameters. There's no ``try``/``except`` around the + ``Beat.objects.get()`` call, because it's not necessary; that function + raises :exc:`Beat.DoesNotExist` on failure, and :exc:`Beat.DoesNotExist` + is a subclass of :exc:`ObjectDoesNotExist`. Raising + :exc:`ObjectDoesNotExist` in :meth:`get_object()` tells Django to produce + a 404 error for that request. + + **New in Django development version:** The :meth:`get_object()` method + also has a chance to handle the :file:`/rss/beats/` url. In this case, + :data:`bits` will be an empty list. In our example, ``len(bits) != 1`` and + an :exc:`ObjectDoesNotExist` exception will be raised, so + :file:`/rss/beats/` will generate a 404 page. But you can handle this case + however you like. For example, you could generate a combined feed for all + beats. + + * To generate the feed's ``<title>``, ``<link>`` and ``<description>``, + Django uses the :meth:`title()`, :meth:`link()` and :meth:`description()` + methods. In the previous example, they were simple string class + attributes, but this example illustrates that they can be either strings + *or* methods. For each of :attr:`title`, :attr:`link` and + :attr:`description`, Django follows this algorithm: + + * First, it tries to call a method, passing the ``obj`` argument, where + ``obj`` is the object returned by :meth:`get_object()`. + + * Failing that, it tries to call a method with no arguments. + + * Failing that, it uses the class attribute. + + Inside the :meth:`link()` method, we handle the possibility that ``obj`` + might be ``None``, which can occur when the URL isn't fully specified. In + some cases, you might want to do something else in this case, which would + mean you'd need to check for ``obj`` existing in other methods as well. + (The :meth:`link()` method is called very early in the feed generation + process, so it's a good place to bail out early.) + + * Finally, note that :meth:`items()` in this example also takes the ``obj`` + argument. The algorithm for :attr:`items` is the same as described in the + previous step -- first, it tries :meth:`items(obj)`, then :meth:`items()`, + then finally an :attr:`items` class attribute (which should be a list). + +The ``ExampleFeed`` class below gives full documentation on methods and +attributes of :class:`~django.contrib.syndication.feeds.Feed` classes. + +Specifying the type of feed +--------------------------- + +By default, feeds produced in this framework use RSS 2.0. + +To change that, add a ``feed_type`` attribute to your +:class:`~django.contrib.syndication.feeds.Feed` class, like so:: + + from django.utils.feedgenerator import Atom1Feed + + class MyFeed(Feed): + feed_type = Atom1Feed + +Note that you set ``feed_type`` to a class object, not an instance. + +Currently available feed types are: + + * :class:`django.utils.feedgenerator.Rss201rev2Feed` (RSS 2.01. Default.) + * :class:`django.utils.feedgenerator.RssUserland091Feed` (RSS 0.91.) + * :class:`django.utils.feedgenerator.Atom1Feed` (Atom 1.0.) + +Enclosures +---------- + +To specify enclosures, such as those used in creating podcast feeds, use the +:attr:`item_enclosure_url`, :attr:`item_enclosure_length` and +:attr:`item_enclosure_mime_type` hooks. See the ``ExampleFeed`` class below for +usage examples. + +Language +-------- + +Feeds created by the syndication framework automatically include the +appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This +comes directly from your :setting:`LANGUAGE_CODE setting`. + +URLs +---- + +The :attr:`link` method/attribute can return either an absolute URL (e.g. +:file:`"/blog/"`) or a URL with the fully-qualified domain and protocol (e.g. +``"http://www.example.com/blog/"``). If :attr:`link` doesn't return the domain, +the syndication framework will insert the domain of the current site, according +to your :setting:`SITE_ID setting <SITE_ID>`. + +Atom feeds require a ``<link rel="self">`` that defines the feed's current +location. The syndication framework populates this automatically, using the +domain of the current site according to the :setting:`SITE_ID` setting. + +Publishing Atom and RSS feeds in tandem +--------------------------------------- + +Some developers like to make available both Atom *and* RSS versions of their +feeds. That's easy to do with Django: Just create a subclass of your +:class:`~django.contrib.syndication.feeds.Feed` +class and set the :attr:`feed_type` to something different. Then update your +URLconf to add the extra versions. + +Here's a full example:: + + from django.contrib.syndication.feeds import Feed + from chicagocrime.models import NewsItem + from django.utils.feedgenerator import Atom1Feed + + class RssSiteNewsFeed(Feed): + title = "Chicagocrime.org site news" + link = "/sitenews/" + description = "Updates on changes and additions to chicagocrime.org." + + def items(self): + return NewsItem.objects.order_by('-pub_date')[:5] + + class AtomSiteNewsFeed(RssSiteNewsFeed): + feed_type = Atom1Feed + subtitle = RssSiteNewsFeed.description + +.. Note:: + In this example, the RSS feed uses a :attr:`description` while the Atom + feed uses a :attr:`subtitle`. That's because Atom feeds don't provide for + a feed-level "description," but they *do* provide for a "subtitle." + + If you provide a :attr:`description` in your + :class:`~django.contrib.syndication.feeds.Feed` class, Django will *not* + automatically put that into the :attr:`subtitle` element, because a + subtitle and description are not necessarily the same thing. Instead, you + should define a :attr:`subtitle` attribute. + + In the above example, we simply set the Atom feed's :attr:`subtitle` to the + RSS feed's :attr:`description`, because it's quite short already. + +And the accompanying URLconf:: + + from django.conf.urls.defaults import * + from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed + + feeds = { + 'rss': RssSiteNewsFeed, + 'atom': AtomSiteNewsFeed, + } + + urlpatterns = patterns('', + # ... + (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', + {'feed_dict': feeds}), + # ... + ) + +Feed class reference +-------------------- + +.. class:: django.contrib.syndication.feeds.Feed + +This example illustrates all possible attributes and methods for a +:class:`~django.contrib.syndication.feeds.Feed` class:: + + from django.contrib.syndication.feeds import Feed + from django.utils import feedgenerator + + class ExampleFeed(Feed): + + # FEED TYPE -- Optional. This should be a class that subclasses + # django.utils.feedgenerator.SyndicationFeed. This designates which + # type of feed this should be: RSS 2.0, Atom 1.0, etc. + # If you don't specify feed_type, your feed will be RSS 2.0. + # This should be a class, not an instance of the class. + + feed_type = feedgenerator.Rss201rev2Feed + + # TEMPLATE NAMES -- Optional. These should be strings representing + # names of Django templates that the system should use in rendering the + # title and description of your feed items. Both are optional. + # If you don't specify one, or either, Django will use the template + # 'feeds/SLUG_title.html' and 'feeds/SLUG_description.html', where SLUG + # is the slug you specify in the URL. + + title_template = None + description_template = None + + # TITLE -- One of the following three is required. The framework looks + # for them in this order. + + def title(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + title as a normal Python string. + """ + + def title(self): + """ + Returns the feed's title as a normal Python string. + """ + + title = 'foo' # Hard-coded title. + + # LINK -- One of the following three is required. The framework looks + # for them in this order. + + def link(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + link as a normal Python string. + """ + + def link(self): + """ + Returns the feed's link as a normal Python string. + """ + + link = '/foo/bar/' # Hard-coded link. + + # GUID -- One of the following three is optional. The framework looks + # for them in this order. This property is only used for Atom feeds + # (where it is the feed-level ID element). If not provided, the feed + # link is used as the ID. + # + # (New in Django development version) + + def feed_guid(self, obj): + """ + Takes the object returned by get_object() and returns the globally + unique ID for the feed as a normal Python string. + """ + + def feed_guid(self): + """ + Returns the feed's globally unique ID as a normal Python string. + """ + + feed_guid = '/foo/bar/1234' # Hard-coded guid. + + # DESCRIPTION -- One of the following three is required. The framework + # looks for them in this order. + + def description(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + description as a normal Python string. + """ + + def description(self): + """ + Returns the feed's description as a normal Python string. + """ + + description = 'Foo bar baz.' # Hard-coded description. + + # AUTHOR NAME --One of the following three is optional. The framework + # looks for them in this order. + + def author_name(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's name as a normal Python string. + """ + + def author_name(self): + """ + Returns the feed's author's name as a normal Python string. + """ + + author_name = 'Sally Smith' # Hard-coded author name. + + # AUTHOR E-MAIL --One of the following three is optional. The framework + # looks for them in this order. + + def author_email(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's e-mail as a normal Python string. + """ + + def author_email(self): + """ + Returns the feed's author's e-mail as a normal Python string. + """ + + author_email = 'test@example.com' # Hard-coded author e-mail. + + # AUTHOR LINK --One of the following three is optional. The framework + # looks for them in this order. In each case, the URL should include + # the "http://" and domain name. + + def author_link(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's URL as a normal Python string. + """ + + def author_link(self): + """ + Returns the feed's author's URL as a normal Python string. + """ + + author_link = 'http://www.example.com/' # Hard-coded author URL. + + # CATEGORIES -- One of the following three is optional. The framework + # looks for them in this order. In each case, the method/attribute + # should return an iterable object that returns strings. + + def categories(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + categories as iterable over strings. + """ + + def categories(self): + """ + Returns the feed's categories as iterable over strings. + """ + + categories = ("python", "django") # Hard-coded list of categories. + + # COPYRIGHT NOTICE -- One of the following three is optional. The + # framework looks for them in this order. + + def copyright(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + copyright notice as a normal Python string. + """ + + def copyright(self): + """ + Returns the feed's copyright notice as a normal Python string. + """ + + copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice. + + # TTL -- One of the following three is optional. The framework looks + # for them in this order. Ignored for Atom feeds. + + def ttl(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + TTL (Time To Live) as a normal Python string. + """ + + def ttl(self): + """ + Returns the feed's TTL as a normal Python string. + """ + + ttl = 600 # Hard-coded Time To Live. + + # ITEMS -- One of the following three is required. The framework looks + # for them in this order. + + def items(self, obj): + """ + Takes the object returned by get_object() and returns a list of + items to publish in this feed. + """ + + def items(self): + """ + Returns a list of items to publish in this feed. + """ + + items = ('Item 1', 'Item 2') # Hard-coded items. + + # GET_OBJECT -- This is required for feeds that publish different data + # for different URL parameters. (See "A complex example" above.) + + def get_object(self, bits): + """ + Takes a list of strings gleaned from the URL and returns an object + represented by this feed. Raises + django.core.exceptions.ObjectDoesNotExist on error. + """ + + # ITEM LINK -- One of these three is required. The framework looks for + # them in this order. + + # First, the framework tries the two methods below, in + # order. Failing that, it falls back to the get_absolute_url() + # method on each item returned by items(). + + def item_link(self, item): + """ + Takes an item, as returned by items(), and returns the item's URL. + """ + + def item_link(self): + """ + Returns the URL for every item in the feed. + """ + + # ITEM_GUID -- The following method is optional. This property is + # only used for Atom feeds (it is the ID element for an item in an + # Atom feed). If not provided, the item's link is used by default. + # + # (New in Django development version) + + def item_guid(self, obj): + """ + Takes an item, as return by items(), and returns the item's ID. + """ + + # ITEM AUTHOR NAME -- One of the following three is optional. The + # framework looks for them in this order. + + def item_author_name(self, item): + """ + Takes an item, as returned by items(), and returns the item's + author's name as a normal Python string. + """ + + def item_author_name(self): + """ + Returns the author name for every item in the feed. + """ + + item_author_name = 'Sally Smith' # Hard-coded author name. + + # ITEM AUTHOR E-MAIL --One of the following three is optional. The + # framework looks for them in this order. + # + # If you specify this, you must specify item_author_name. + + def item_author_email(self, obj): + """ + Takes an item, as returned by items(), and returns the item's + author's e-mail as a normal Python string. + """ + + def item_author_email(self): + """ + Returns the author e-mail for every item in the feed. + """ + + item_author_email = 'test@example.com' # Hard-coded author e-mail. + + # ITEM AUTHOR LINK --One of the following three is optional. The + # framework looks for them in this order. In each case, the URL should + # include the "http://" and domain name. + # + # If you specify this, you must specify item_author_name. + + def item_author_link(self, obj): + """ + Takes an item, as returned by items(), and returns the item's + author's URL as a normal Python string. + """ + + def item_author_link(self): + """ + Returns the author URL for every item in the feed. + """ + + item_author_link = 'http://www.example.com/' # Hard-coded author URL. + + # ITEM ENCLOSURE URL -- One of these three is required if you're + # publishing enclosures. The framework looks for them in this order. + + def item_enclosure_url(self, item): + """ + Takes an item, as returned by items(), and returns the item's + enclosure URL. + """ + + def item_enclosure_url(self): + """ + Returns the enclosure URL for every item in the feed. + """ + + item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link. + + # ITEM ENCLOSURE LENGTH -- One of these three is required if you're + # publishing enclosures. The framework looks for them in this order. + # In each case, the returned value should be either an integer, or a + # string representation of the integer, in bytes. + + def item_enclosure_length(self, item): + """ + Takes an item, as returned by items(), and returns the item's + enclosure length. + """ + + def item_enclosure_length(self): + """ + Returns the enclosure length for every item in the feed. + """ + + item_enclosure_length = 32000 # Hard-coded enclosure length. + + # ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're + # publishing enclosures. The framework looks for them in this order. + + def item_enclosure_mime_type(self, item): + """ + Takes an item, as returned by items(), and returns the item's + enclosure MIME type. + """ + + def item_enclosure_mime_type(self): + """ + Returns the enclosure MIME type for every item in the feed. + """ + + item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type. + + # ITEM PUBDATE -- It's optional to use one of these three. This is a + # hook that specifies how to get the pubdate for a given item. + # In each case, the method/attribute should return a Python + # datetime.datetime object. + + def item_pubdate(self, item): + """ + Takes an item, as returned by items(), and returns the item's + pubdate. + """ + + def item_pubdate(self): + """ + Returns the pubdate for every item in the feed. + """ + + item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate. + + # ITEM CATEGORIES -- It's optional to use one of these three. This is + # a hook that specifies how to get the list of categories for a given + # item. In each case, the method/attribute should return an iterable + # object that returns strings. + + def item_categories(self, item): + """ + Takes an item, as returned by items(), and returns the item's + categories. + """ + + def item_categories(self): + """ + Returns the categories for every item in the feed. + """ + + item_categories = ("python", "django") # Hard-coded categories. + + # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the + # following three is optional. The framework looks for them in this + # order. + + def item_copyright(self, obj): + """ + Takes an item, as returned by items(), and returns the item's + copyright notice as a normal Python string. + """ + + def item_copyright(self): + """ + Returns the copyright notice for every item in the feed. + """ + + item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice. + + +The low-level framework +======================= + +Behind the scenes, the high-level RSS framework uses a lower-level framework +for generating feeds' XML. This framework lives in a single module: +`django/utils/feedgenerator.py`_. + +You use this framework on your own, for lower-level feed generation. You can +also create custom feed generator subclasses for use with the ``feed_type`` +``Feed`` option. + +``SyndicationFeed`` classes +--------------------------- + +The :mod:`~django.utils.feedgenerator` module contains a base class: + +.. class:: django.utils.feedgenerator.SyndicationFeed + +and several subclasses: + +.. class:: django.utils.feedgenerator.RssUserland091Feed +.. class:: django.utils.feedgenerator.Rss201rev2Feed +.. class:: django.utils.feedgenerator.Atom1Feed + +Each of these three classes knows how to render a certain type of feed as XML. +They share this interface: + +.. method:: SyndicationFeed.__init__(**kwargs) + + Initialize the feed with the given dictionary of metadata, which applies to + the entire feed. Required keyword arguments are: + + * ``title`` + * ``link`` + * ``description`` + + There's also a bunch of other optional keywords: + + * ``language`` + * ``author_email`` + * ``author_name`` + * ``author_link`` + * ``subtitle`` + * ``categories`` + * ``feed_url`` + * ``feed_copyright`` + * ``feed_guid`` + * ``ttl`` + + Any extra keyword arguments you pass to ``__init__`` will be stored in + ``self.feed`` for use with `custom feed generators`_. + + All parameters should be Unicode objects, except ``categories``, which + should be a sequence of Unicode objects. + +.. method:: SyndicationFeed.add_item(**kwargs) + + Add an item to the feed with the given parameters. + + Required keyword arguments are: + + * ``title`` + * ``link`` + * ``description`` + + Optional keyword arguments are: + + * ``author_email`` + * ``author_name`` + * ``author_link`` + * ``pubdate`` + * ``comments`` + * ``unique_id`` + * ``enclosure`` + * ``categories`` + * ``item_copyright`` + * ``ttl`` + + Extra keyword arguments will be stored for `custom feed generators`_. + + All parameters, if given, should be Unicode objects, except: + + * ``pubdate`` should be a `Python datetime object`_. + * ``enclosure`` should be an instance of ``feedgenerator.Enclosure``. + * ``categories`` should be a sequence of Unicode objects. + +.. method:: SyndicationFeed.write(outfile, encoding) + + Outputs the feed in the given encoding to outfile, which is a file-like object. + +.. method:: SyndicationFeed.writeString(encoding) + + Returns the feed as a string in the given encoding. + +For example, to create an Atom 1.0 feed and print it to standard output:: + + >>> from django.utils import feedgenerator + >>> f = feedgenerator.Atom1Feed( + ... title=u"My Weblog", + ... link=u"http://www.example.com/", + ... description=u"In which I write about what I ate today.", + ... language=u"en") + >>> f.add_item(title=u"Hot dog today", + ... link=u"http://www.example.com/entries/1/", + ... description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>") + >>> print f.writeString('utf8') + <?xml version="1.0" encoding="utf8"?> + <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"> + ... + </feed> + +.. _django/utils/feedgenerator.py: http://code.djangoproject.com/browser/django/trunk/django/utils/feedgenerator.py +.. _Python datetime object: http://www.python.org/doc/current/lib/module-datetime.html + +Custom feed generators +---------------------- + +If you need to produce a custom feed format, you've got a couple of options. + +If the feed format is totally custom, you'll want to subclass +``SyndicationFeed`` and completely replace the ``write()`` and +``writeString()`` methods. + +However, if the feed format is a spin-off of RSS or Atom (i.e. GeoRSS_, Apple's +`iTunes podcast format`_, etc.), you've got a better choice. These types of +feeds typically add extra elements and/or attributes to the underlying format, +and there are a set of methods that ``SyndicationFeed`` calls to get these extra +attributes. Thus, you can subclass the appropriate feed generator class +(``Atom1Feed`` or ``Rss201rev2Feed``) and extend these callbacks. They are: + +.. _georss: http://georss.org/ +.. _itunes podcast format: http://www.apple.com/itunes/store/podcaststechspecs.html + +``SyndicationFeed.root_attributes(self, )`` + Return a ``dict`` of attributes to add to the root feed element + (``feed``/``channel``). + +``SyndicationFeed.add_root_elements(self, handler)`` + Callback to add elements inside the root feed element + (``feed``/``channel``). ``handler`` is an `XMLGenerator`_ from Python's + built-in SAX library; you'll call methods on it to add to the XML + document in process. + +``SyndicationFeed.item_attributes(self, item)`` + Return a ``dict`` of attributes to add to each item (``item``/``entry``) + element. The argument, ``item``, is a dictionary of all the data passed to + ``SyndicationFeed.add_item()``. + +``SyndicationFeed.add_item_elements(self, handler, item)`` + Callback to add elements to each item (``item``/``entry``) element. + ``handler`` and ``item`` are as above. + +.. warning:: + + If you override any of these methods, be sure to call the superclass methods + since they add the required elements for each feed format. + +For example, you might start implementing an iTunes RSS feed generator like so:: + + class iTunesFeed(Rss201rev2Feed): + def root_attibutes(self): + attrs = super(iTunesFeed, self).root_attibutes() + attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd + return attrs + + def add_root_elements(self, handler): + super(iTunesFeed, self).add_root_elements(handler) + handler.addQuickElement('itunes:explicit', 'clean') + +Obviously there's a lot more work to be done for a complete custom feed class, +but the above example should demonstrate the basic idea. + +.. _XMLGenerator: http://docs.python.org/dev/library/xml.sax.utils.html#xml.sax.saxutils.XMLGenerator
\ No newline at end of file diff --git a/docs/ref/contrib/webdesign.txt b/docs/ref/contrib/webdesign.txt new file mode 100644 index 0000000000..e69ad49232 --- /dev/null +++ b/docs/ref/contrib/webdesign.txt @@ -0,0 +1,58 @@ +.. _ref-contrib-webdesign: + +======================== +django.contrib.webdesign +======================== + +.. module:: django.contrib.webdesign + :synopsis: Helpers and utilities targeted primarily at Web *designers* + rather than Web *developers*. + +The ``django.contrib.webdesign`` package, part of the +:ref:`"django.contrib" add-ons <ref-contrib-index>`, provides various Django +helpers that are particularly useful to Web *designers* (as opposed to +developers). + +At present, the package contains only a single template tag. If you have ideas +for Web-designer-friendly functionality in Django, please +:ref:`suggest them <internals-contributing>`. + +Template tags +============= + +To use these template tags, add ``'django.contrib.webdesign'`` to your +:setting:`INSTALLED_APPS` setting. Once you've done that, use +``{% load webdesign %}`` in a template to give your template access to the tags. + + +lorem +===== + +Displays random "lorem ipsum" Latin text. This is useful for providing sample +data in templates. + +Usage:: + + {% lorem [count] [method] [random] %} + +The ``{% lorem %}`` tag can be used with zero, one, two or three arguments. +The arguments are: + + =========== ============================================================= + Argument Description + =========== ============================================================= + ``count`` A number (or variable) containing the number of paragraphs or + words to generate (default is 1). + ``method`` Either ``w`` for words, ``p`` for HTML paragraphs or ``b`` + for plain-text paragraph blocks (default is ``b``). + ``random`` The word ``random``, which if given, does not use the common + paragraph ("Lorem ipsum dolor sit amet...") when generating + text. + =========== ============================================================= + +Examples: + + * ``{% lorem %}`` will output the common "lorem ipsum" paragraph. + * ``{% lorem 3 p %}`` will output the common "lorem ipsum" paragraph + and two random paragraphs each wrapped in HTML ``<p>`` tags. + * ``{% lorem 2 w random %}`` will output two random Latin words. diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt new file mode 100644 index 0000000000..c3c079b01d --- /dev/null +++ b/docs/ref/databases.txt @@ -0,0 +1,305 @@ +.. _ref-databases: + +=============================== +Notes about supported databases +=============================== + +Django attempts to support as many features as possible on all database +backends. However, not all database backends are alike, and we've had to make +design decisions on which features to support and which assumptions we can make +safely. + +This file describes some of the features that might be relevant to Django +usage. Of course, it is not intended as a replacement for server-specific +documentation or reference manuals. + +MySQL notes +=========== + +Django expects the database to support transactions, referential integrity, +and Unicode support (UTF-8 encoding). Fortunately, MySQL_ has all these +features as available as far back as 3.23. While it may be possible to use +3.23 or 4.0, you'll probably have less trouble if you use 4.1 or 5.0. + +MySQL 4.1 +--------- + +`MySQL 4.1`_ has greatly improved support for character sets. It is possible to +set different default character sets on the database, table, and column. +Previous versions have only a server-wide character set setting. It's also the +first version where the character set can be changed on the fly. 4.1 also has +support for views, but Django currently doesn't use views. + +MySQL 5.0 +--------- + +`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed +data on all database schema. Django's ``inspectdb`` feature uses this +``information_schema`` if it's available. 5.0 also has support for stored +procedures, but Django currently doesn't use stored procedures. + +.. _MySQL: http://www.mysql.com/ +.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html +.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html + +Storage engines +--------------- + +MySQL has several `storage engines`_ (previously called table types). You can +change the default storage engine in the server configuration. + +The default engine is MyISAM_. The main drawback of MyISAM is that it doesn't +currently support transactions or foreign keys. On the plus side, it's +currently the only engine that supports full-text indexing and searching. + +The InnoDB_ engine is fully transactional and supports foreign key references. + +The BDB_ engine, like InnoDB, is also fully transactional and supports foreign +key references. However, its use seems to be deprecated. + +`Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon. +For now, InnoDB is probably your best choice. + +.. _storage engines: http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html +.. _MyISAM: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html +.. _BDB: http://dev.mysql.com/doc/refman/5.0/en/bdb-storage-engine.html +.. _InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb.html +.. _Other storage engines: http://dev.mysql.com/doc/refman/5.1/en/storage-engines-other.html +.. _SolidDB: http://forge.mysql.com/projects/view.php?id=139 +.. _Falcon: http://dev.mysql.com/doc/falcon/en/index.html + +MySQLdb +------- + +`MySQLdb`_ is the Python interface to MySQL. Version 1.2.1p2 or later is +required for full MySQL support in Django. Earlier versions will not work with +the ``mysql`` backend. + +If you are trying to use an older version of MySQL and the ``mysql_old`` +backend, then 1.2.0 *might* work for you. + +.. note:: + If you see ``ImportError: cannot import name ImmutableSet`` when trying to + use Django, your MySQLdb installation may contain an outdated ``sets.py`` + file that conflicts with the built-in module of the same name from Python + 2.4 and later. To fix this, verify that you have installed MySQLdb version + 1.2.1p2 or newer, then delete the ``sets.py`` file in the MySQLdb + directory that was left by an earlier version. + +.. _MySQLdb: http://sourceforge.net/projects/mysql-python + +Creating your database +---------------------- + +You can `create your database`_ using the command-line tools and this SQL:: + + CREATE DATABASE <dbname> CHARACTER SET utf8; + +This ensures all tables and columns will use UTF-8 by default. + +.. _create your database: http://dev.mysql.com/doc/refman/5.0/en/create-database.html + +Connecting to the database +-------------------------- + +Refer to the :ref:`settings documentation <ref-settings>`. + +Connection settings are used in this order: + + 1. :setting:`DATABASE_OPTIONS`. + 2. :setting:`DATABASE_NAME`, :setting:`DATABASE_USER`, + :setting:`DATABASE_PASSWORD`, :setting:`DATABASE_HOST`, + :setting:`DATABASE_PORT` + 3. MySQL option files. + +In other words, if you set the name of the database in ``DATABASE_OPTIONS``, +this will take precedence over ``DATABASE_NAME``, which would override +anything in a `MySQL option file`_. + +Here's a sample configuration which uses a MySQL option file:: + + # settings.py + DATABASE_ENGINE = "mysql" + DATABASE_OPTIONS = { + 'read_default_file': '/path/to/my.cnf', + } + + # my.cnf + [client] + database = DATABASE_NAME + user = DATABASE_USER + password = DATABASE_PASSWORD + default-character-set = utf8 + +Several other MySQLdb connection options may be useful, such as ``ssl``, +``use_unicode``, ``init_command``, and ``sql_mode``. Consult the +`MySQLdb documentation`_ for more details. + +.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html +.. _MySQLdb documentation: http://mysql-python.sourceforge.net/ + +Creating your tables +-------------------- + +When Django generates the schema, it doesn't specify a storage engine, so +tables will be created with whatever default storage engine your database +server is configured for. The easiest solution is to set your database server's +default storage engine to the desired engine. + +If you're using a hosting service and can't change your server's default +storage engine, you have a couple of options. + + * After the tables are created, execute an ``ALTER TABLE`` statement to + convert a table to a new storage engine (such as InnoDB):: + + ALTER TABLE <tablename> ENGINE=INNODB; + + This can be tedious if you have a lot of tables. + + * Another option is to use the ``init_command`` option for MySQLdb prior to + creating your tables:: + + DATABASE_OPTIONS = { + # ... + "init_command": "SET storage_engine=INNODB", + # ... + } + + This sets the default storage engine upon connecting to the database. + After your tables have been created, you should remove this option. + + * Another method for changing the storage engine is described in + AlterModelOnSyncDB_. + +.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB + + +.. _oracle-notes: + +Oracle notes +============ + +Django supports `Oracle Database Server`_ versions 9i and higher. Oracle +version 10g or later is required to use Django's ``regex`` and ``iregex`` query +operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer. + +.. _`Oracle Database Server`: http://www.oracle.com/ +.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/ + +In order for the ``python manage.py syncdb`` command to work, your Oracle +database user must have privileges to run the following commands: + + * CREATE TABLE + * CREATE SEQUENCE + * CREATE PROCEDURE + * CREATE TRIGGER + +To run Django's test suite, the user needs these *additional* privileges: + + * CREATE USER + * DROP USER + * CREATE TABLESPACE + * DROP TABLESPACE + +Connecting to the database +-------------------------- + +Your Django settings.py file should look something like this for Oracle:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = '' + DATABASE_PORT = '' + +If you don't use a ``tnsnames.ora`` file or a similar naming method that +recognizes the SID ("xe" in this example), then fill in both +:setting:`DATABASE_HOST` and :setting:`DATABASE_PORT` like so:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = 'dbprod01ned.mycompany.com' + DATABASE_PORT = '1540' + +You should supply both :setting:`DATABASE_HOST` and :setting:`DATABASE_PORT`, or leave both +as empty strings. + +Tablespace options +------------------ + +A common paradigm for optimizing performance in Oracle-based systems is the +use of `tablespaces`_ to organize disk layout. The Oracle backend supports +this use case by adding ``db_tablespace`` options to the ``Meta`` and +``Field`` classes. (When you use a backend that lacks support for tablespaces, +Django ignores these options.) + +.. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace + +A tablespace can be specified for the table(s) generated by a model by +supplying the ``db_tablespace`` option inside the model's ``class Meta``. +Additionally, you can pass the ``db_tablespace`` option to a ``Field`` +constructor to specify an alternate tablespace for the ``Field``'s column +index. If no index would be created for the column, the ``db_tablespace`` +option is ignored:: + + class TablespaceExample(models.Model): + name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes") + data = models.CharField(max_length=255, db_index=True) + edges = models.ManyToManyField(to="self", db_tablespace="indexes") + + class Meta: + db_tablespace = "tables" + +In this example, the tables generated by the ``TablespaceExample`` model +(i.e., the model table and the many-to-many table) would be stored in the +``tables`` tablespace. The index for the name field and the indexes on the +many-to-many table would be stored in the ``indexes`` tablespace. The ``data`` +field would also generate an index, but no tablespace for it is specified, so +it would be stored in the model tablespace ``tables`` by default. + +**New in the Django development version:** Use the :setting:`DEFAULT_TABLESPACE` +and :setting:`DEFAULT_INDEX_TABLESPACE` settings to specify default values for +the db_tablespace options. These are useful for setting a tablespace for the +built-in Django apps and other applications whose code you cannot control. + +Django does not create the tablespaces for you. Please refer to `Oracle's +documentation`_ for details on creating and managing tablespaces. + +.. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403 + +Naming issues +------------- + +Oracle imposes a name length limit of 30 characters. To accommodate this, the +backend truncates database identifiers to fit, replacing the final four +characters of the truncated name with a repeatable MD5 hash value. + +NULL and empty strings +---------------------- + +Django generally prefers to use the empty string ('') rather than NULL, but +Oracle treats both identically. To get around this, the Oracle backend +coerces the ``null=True`` option on fields that permit the empty string as a +value. When fetching from the database, it is assumed that a NULL value in +one of these fields really means the empty string, and the data is silently +converted to reflect this assumption. + +``TextField`` limitations +------------------------- + +The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes +some limitations on the usage of such LOB columns in general: + + * LOB columns may not be used as primary keys. + + * LOB columns may not be used in indexes. + + * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that + attempting to use the ``QuerySet.distinct`` method on a model that + includes ``TextField`` columns will result in an error when run against + Oracle. A workaround to this is to keep ``TextField`` columns out of any + models that you foresee performing ``distinct()`` queries on, and to + include the ``TextField`` in a related model instead. diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt new file mode 100644 index 0000000000..d6cb4e62f3 --- /dev/null +++ b/docs/ref/django-admin.txt @@ -0,0 +1,893 @@ +.. _ref-django-admin: + +============================= +django-admin.py and manage.py +============================= + +``django-admin.py`` is Django's command-line utility for administrative tasks. +This document outlines all it can do. + +In addition, ``manage.py`` is automatically created in each Django project. +``manage.py`` is a thin wrapper around ``django-admin.py`` that takes care of +two things for you before delegating to ``django-admin.py``: + + * It puts your project's package on ``sys.path``. + + * It sets the :envvar:`DJANGO_SETTINGS_MODULE` environment variable so that + it points to your project's ``settings.py`` file. + +The ``django-admin.py`` script should be on your system path if you installed +Django via its ``setup.py`` utility. If it's not on your path, you can find it +in ``site-packages/django/bin`` within your Python installation. Consider +symlinking it from some place on your path, such as ``/usr/local/bin``. + +For Windows users, who do not have symlinking functionality available, you can +copy ``django-admin.py`` to a location on your existing path or edit the +``PATH`` settings (under ``Settings - Control Panel - System - Advanced - +Environment...``) to point to its installed location. + +Generally, when working on a single Django project, it's easier to use +``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the +``--settings`` command line option, if you need to switch between multiple +Django settings files. + +The command-line examples throughout this document use ``django-admin.py`` to +be consistent, but any example can use ``manage.py`` just as well. + +Usage +===== + +.. code-block:: bash + + django-admin.py <subcommand> [options] + manage.py <subcommand> [options] + +``subcommand`` should be one of the subcommands listed in this document. +``options``, which is optional, should be zero or more of the options available +for the given subcommand. + +Getting runtime help +-------------------- + +.. django-admin-option:: --help + +In Django 0.96, run ``django-admin.py --help`` to display a help message that +includes a terse list of all available subcommands and options. + +In the Django development version, run ``django-admin.py help`` to display a +list of all available subcommands. Run ``django-admin.py help <subcommand>`` +to display a description of the given subcommand and a list of its available +options. + +App names +--------- + +Many subcommands take a list of "app names." An "app name" is the basename of +the package containing your models. For example, if your ``INSTALLED_APPS`` +contains the string ``'mysite.blog'``, the app name is ``blog``. + +Determining the version +----------------------- + +.. django-admin-option:: --version + +Run ``django-admin.py --version`` to display the current Django version. + +Examples of output:: + + 0.95 + 0.96 + 0.97-pre-SVN-6069 + +Displaying debug output +----------------------- + +.. django-admin-option:: --verbosity <amount> + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + + +Available subcommands +===================== + +adminindex +---------- + +.. django-admin:: adminindex <appname appname ...> + +Prints the admin-index template snippet for the given app name(s). + +Use admin-index template snippets if you want to customize the look and feel of +your admin's index page. See :ref:`Tutorial 2 <intro-tutorial02>` for more +information. + +cleanup +------- + +**New in Django development version** + +Can be run as a cronjob or directly to clean out old data from the database +(only expired sessions at the moment). + +compilemessages +--------------- + +**New in Django development version** + +Compiles .po files created with ``makemessages`` to .mo files for use with +the builtin gettext support. See :ref:`topics-i18n`. + +--locale +~~~~~~~~ + +Use the ``--locale`` or ``-l`` option to specify the locale to process. +If not provided all locales are processed. + +Example usage:: + + django-admin.py compilemessages --locale=br_PT + +createcachetable +---------------- + +.. django-admin:: createcachetable <tablename> + +Creates a cache table named ``tablename`` for use with the database cache +backend. See :ref:`topics-cache` for more information. + +createsuperuser +--------------- + +.. django-admin:: createsuperuser + +**New in Django development version** + +Creates a superuser account (a user who has all permissions). This is +useful if you need to create an initial superuser account but did not +do so during ``syncdb``, or if you need to programmatically generate +superuser accounts for your site(s). + +When run interactively, this command will prompt for a password for +the new superuser account. When run non-interactively, no password +will be set, and the superuser account will not be able to log in until +a password has been manually set for it. + +.. django-admin-option:: --username +.. django-admin-option:: --email + +The username and e-mail address for the new account can be supplied by +using the ``--username`` and ``--email`` arguments on the command +line. If either of those is not supplied, ``createsuperuser`` will prompt for +it when running interactively. + +This command is only available if Django's :ref:`authentication system +<topics-auth>` (``django.contrib.auth``) is installed. + +dbshell +------- + +.. django-admin:: dbshell + +Runs the command-line client for the database engine specified in your +``DATABASE_ENGINE`` setting, with the connection parameters specified in your +``DATABASE_USER``, ``DATABASE_PASSWORD``, etc., settings. + + * For PostgreSQL, this runs the ``psql`` command-line client. + * For MySQL, this runs the ``mysql`` command-line client. + * For SQLite, this runs the ``sqlite3`` command-line client. + +This command assumes the programs are on your ``PATH`` so that a simple call to +the program name (``psql``, ``mysql``, ``sqlite3``) will find the program in +the right place. There's no way to specify the location of the program +manually. + +diffsettings +------------ + +.. django-admin:: diffsettings + +Displays differences between the current settings file and Django's default +settings. + +Settings that don't appear in the defaults are followed by ``"###"``. For +example, the default settings don't define ``ROOT_URLCONF``, so +``ROOT_URLCONF`` is followed by ``"###"`` in the output of ``diffsettings``. + +Note that Django's default settings live in ``django/conf/global_settings.py``, +if you're ever curious to see the full list of defaults. + +dumpdata +-------- + +.. django-admin:: dumpdata <appname appname ...> + +Outputs to standard output all data in the database associated with the named +application(s). + +If no application name is provided, all installed applications will be dumped. + +The output of ``dumpdata`` can be used as input for ``loaddata``. + +Note that ``dumpdata`` uses the default manager on the model for selecting the +records to dump. If you're using a :ref:`custom manager <custom-managers>` as +the default manager and it filters some of the available records, not all of the +objects will be dumped. + +.. django-admin-option:: --exclude + +**New in Django development version** + +Exclude a specific application from the applications whose contents is +output. For example, to specifically exclude the `auth` application from +the output, you would call:: + + django-admin.py dumpdata --exclude=auth + +If you want to exclude multiple applications, use multiple ``--exclude`` +directives:: + + django-admin.py dumpdata --exclude=auth --exclude=contenttype + + +.. django-admin-option:: --format <fmt> + + By default, ``dumpdata`` will format its output in JSON, but you can use the + ``--format`` option to specify another format. Currently supported formats + are listed in :ref:`serialization-formats`. + +.. django-admin-option:: --indent <num> + + By default, ``dumpdata`` will output all data on a single line. This isn't + easy for humans to read, so you can use the ``--indent`` option to + pretty-print the output with a number of indentation spaces. + +flush +----- + +.. django-admin: flush + +Returns the database to the state it was in immediately after syncdb was +executed. This means that all data will be removed from the database, any +post-synchronization handlers will be re-executed, and the ``initial_data`` +fixture will be re-installed. + +The behavior of this command has changed in the Django development version. +Previously, this command cleared *every* table in the database, including any +table that Django didn't know about (i.e., tables that didn't have associated +models and/or weren't in ``INSTALLED_APPS``). Now, the command only clears +tables that are represented by Django models and are activated in +``INSTALLED_APPS``. + +.. django-admin-option:: --noinput + + Use the ``--noinput`` option to suppress all user prompting, such as "Are + you sure?" confirmation messages. This is useful if ``django-admin.py`` is + being executed as an unattended, automated script. + +inspectdb +--------- + +Introspects the database tables in the database pointed-to by the +``DATABASE_NAME`` setting and outputs a Django model module (a ``models.py`` +file) to standard output. + +Use this if you have a legacy database with which you'd like to use Django. +The script will inspect the database and create a model for each table within +it. + +As you might expect, the created models will have an attribute for every field +in the table. Note that ``inspectdb`` has a few special cases in its field-name +output: + + * If ``inspectdb`` cannot map a column's type to a model field type, it'll + use ``TextField`` and will insert the Python comment + ``'This field type is a guess.'`` next to the field in the generated + model. + + * If the database column name is a Python reserved word (such as + ``'pass'``, ``'class'`` or ``'for'``), ``inspectdb`` will append + ``'_field'`` to the attribute name. For example, if a table has a column + ``'for'``, the generated model will have a field ``'for_field'``, with + the ``db_column`` attribute set to ``'for'``. ``inspectdb`` will insert + the Python comment + ``'Field renamed because it was a Python reserved word.'`` next to the + field. + +This feature is meant as a shortcut, not as definitive model generation. After +you run it, you'll want to look over the generated models yourself to make +customizations. In particular, you'll need to rearrange models' order, so that +models that refer to other models are ordered properly. + +Primary keys are automatically introspected for PostgreSQL, MySQL and +SQLite, in which case Django puts in the ``primary_key=True`` where +needed. + +``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection +only works in PostgreSQL and with certain types of MySQL tables. + +loaddata <fixture fixture ...> +------------------------------ + +Searches for and loads the contents of the named fixture into the database. + +A *fixture* is a collection of files that contain the serialized contents of +the database. Each fixture has a unique name, and the files that comprise the +fixture can be distributed over multiple directories, in multiple applications. + +Django will search in three locations for fixtures: + + 1. In the ``fixtures`` directory of every installed application + 2. In any directory named in the ``FIXTURE_DIRS`` setting + 3. In the literal path named by the fixture + +Django will load any and all fixtures it finds in these locations that match +the provided fixture names. + +If the named fixture has a file extension, only fixtures of that type +will be loaded. For example:: + + django-admin.py loaddata mydata.json + +would only load JSON fixtures called ``mydata``. The fixture extension +must correspond to the registered name of a serializer (e.g., ``json`` or +``xml``). + +If you omit the extension, Django will search all available fixture types +for a matching fixture. For example:: + + django-admin.py loaddata mydata + +would look for any fixture of any fixture type called ``mydata``. If a fixture +directory contained ``mydata.json``, that fixture would be loaded +as a JSON fixture. However, if two fixtures with the same name but different +fixture type are discovered (for example, if ``mydata.json`` and +``mydata.xml`` were found in the same fixture directory), fixture +installation will be aborted, and any data installed in the call to +``loaddata`` will be removed from the database. + +The fixtures that are named can include directory components. These +directories will be included in the search path. For example:: + + django-admin.py loaddata foo/bar/mydata.json + +would search ``<appname>/fixtures/foo/bar/mydata.json`` for each installed +application, ``<dirname>/foo/bar/mydata.json`` for each directory in +``FIXTURE_DIRS``, and the literal path ``foo/bar/mydata.json``. + +Note that the order in which fixture files are processed is undefined. However, +all fixture data is installed as a single transaction, so data in +one fixture can reference data in another fixture. If the database backend +supports row-level constraints, these constraints will be checked at the +end of the transaction. + +The ``dumpdata`` command can be used to generate input for ``loaddata``. + +.. admonition:: MySQL and Fixtures + + Unfortunately, MySQL isn't capable of completely supporting all the + features of Django fixtures. If you use MyISAM tables, MySQL doesn't + support transactions or constraints, so you won't get a rollback if + multiple transaction files are found, or validation of fixture data. + If you use InnoDB tables, you won't be able to have any forward + references in your data files - MySQL doesn't provide a mechanism to + defer checking of row constraints until a transaction is committed. + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + +Example usage:: + + django-admin.py loaddata --verbosity=2 + +makemessages +------------ + +**New in Django development version** + +Runs over the entire source tree of the current directory and pulls out all +strings marked for translation. It creates (or updates) a message file in the +conf/locale (in the django tree) or locale (for project and application) +directory. After making changes to the messages files you need to compile them +with ``compilemessages`` for use with the builtin gettext support. See the +:ref:`i18n documentation <how-to-create-language-files>` for details. + +--all +~~~~~ + +Use the ``--all`` or ``-a`` option to update the message files for all +available languages. + +Example usage:: + + django-admin.py makemessages --all + +--extension +~~~~~~~~~~~ + +Use the ``--extension`` or ``-e`` option to specify a list of file extensions +to examine (default: ".html"). + +Example usage:: + + django-admin.py makemessages --locale=de --extension xhtml + +Separate multiple extensions with commas or use -e or --extension multiple times:: + + django-admin.py makemessages --locale=de --extension=html,txt --extension xml + +--locale +~~~~~~~~ + +Use the ``--locale`` or ``-l`` option to specify the locale to process. + +Example usage:: + + django-admin.py makemessages --locale=br_PT + +--domain +~~~~~~~~ + +Use the ``--domain`` or ``-d`` option to change the domain of the messages files. +Currently supported: + + * ``django`` for all ``*.py`` and ``*.html`` files (default) + * ``djangojs`` for ``*.js`` files + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` or ``-v`` to specify the amount of notification and debug +information that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + +Example usage:: + + django-admin.py makemessages --verbosity=2 + +reset <appname appname ...> +--------------------------- + +Executes the equivalent of ``sqlreset`` for the given app name(s). + +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + +runfcgi [options] +----------------- + +Starts a set of FastCGI processes suitable for use with any Web server that +supports the FastCGI protocol. See the :ref:`FastCGI deployment documentation +<howto-deployment-fastcgi>` for details. Requires the Python FastCGI module from +`flup`_. + +.. _flup: http://www.saddi.com/software/flup/ + +runserver [optional port number, or ipaddr:port] +------------------------------------------------ + +Starts a lightweight development Web server on the local machine. By default, +the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an +IP address and port number explicitly. + +If you run this script as a user with normal privileges (recommended), you +might not have access to start a port on a low port number. Low port numbers +are reserved for the superuser (root). + +DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through +security audits or performance tests. (And that's how it's gonna stay. We're in +the business of making Web frameworks, not Web servers, so improving this +server to be able to handle a production environment is outside the scope of +Django.) + +The development server automatically reloads Python code for each request, as +needed. You don't need to restart the server for code changes to take effect. + +When you start the server, and each time you change Python code while the +server is running, the server will validate all of your installed models. (See +the ``validate`` command below.) If the validator finds errors, it will print +them to standard output, but it won't stop the server. + +You can run as many servers as you want, as long as they're on separate ports. +Just execute ``django-admin.py runserver`` more than once. + +Note that the default IP address, 127.0.0.1, is not accessible from other +machines on your network. To make your development server viewable to other +machines on the network, use its own IP address (e.g. ``192.168.2.1``) or +``0.0.0.0``. + +--adminmedia +~~~~~~~~~~~~ + +Use the ``--adminmedia`` option to tell Django where to find the various CSS +and JavaScript files for the Django admin interface. Normally, the development +server serves these files out of the Django source tree magically, but you'd +want to use this if you made any changes to those files for your own site. + +Example usage:: + + django-admin.py runserver --adminmedia=/tmp/new-admin-style/ + +--noreload +~~~~~~~~~~ + +Use the ``--noreload`` option to disable the use of the auto-reloader. This +means any Python code changes you make while the server is running will *not* +take effect if the particular Python modules have already been loaded into +memory. + +Example usage:: + + django-admin.py runserver --noreload + +Examples of using different ports and addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Port 8000 on IP address 127.0.0.1:: + + django-admin.py runserver + +Port 8000 on IP address 1.2.3.4:: + + django-admin.py runserver 1.2.3.4:8000 + +Port 7000 on IP address 127.0.0.1:: + + django-admin.py runserver 7000 + +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_URL`` and so forth). If +you want to configure Django to serve static media, read :ref:`howto-static-files`. + +Turning off auto-reload +~~~~~~~~~~~~~~~~~~~~~~~ + +To disable auto-reloading of code while the development server is running, use the +``--noreload`` option, like so:: + + django-admin.py runserver --noreload + +shell +----- + +Starts the Python interactive interpreter. + +Django will use IPython_, if it's installed. If you have IPython installed and +want to force use of the "plain" Python interpreter, use the ``--plain`` +option, like so:: + + django-admin.py shell --plain + +.. _IPython: http://ipython.scipy.org/ + +sql <appname appname ...> +------------------------- + +Prints the CREATE TABLE SQL statements for the given app name(s). + +sqlall <appname appname ...> +---------------------------- + +Prints the CREATE TABLE and initial-data SQL statements for the given app name(s). + +Refer to the description of ``sqlcustom`` for an explanation of how to +specify initial data. + +sqlclear <appname appname ...> +------------------------------ + +Prints the DROP TABLE SQL statements for the given app name(s). + +sqlcustom <appname appname ...> +------------------------------- + +Prints the custom SQL statements for the given app name(s). + +For each model in each specified app, this command looks for the file +``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given app name and +``<modelname>`` is the model's name in lowercase. For example, if you have an +app ``news`` that includes a ``Story`` model, ``sqlcustom`` 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 make any +table modifications, or insert any SQL functions into the database. + +Note that the order in which the SQL files are processed is undefined. + +sqlflush +-------- + +Prints the SQL statements that would be executed for the `flush`_ command. + +sqlindexes <appname appname ...> +-------------------------------- + +Prints the CREATE INDEX SQL statements for the given app name(s). + +sqlreset <appname appname ...> +------------------------------ + +Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s). + +sqlsequencereset <appname appname ...> +-------------------------------------- + +Prints the SQL statements for resetting sequences for the given app name(s). + +See http://simon.incutio.com/archive/2004/04/21/postgres for more information. + +startapp <appname> +------------------ + +Creates a Django app directory structure for the given app name in the current +directory. + +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. + +.. admonition:: Syncdb will not alter existing tables + + ``syncdb`` will only create tables for models which have not yet been + installed. It will *never* issue ``ALTER TABLE`` statements to match + changes made to a model class after installation. Changes to model classes + and database schemas often involve some form of ambiguity and, in those + cases, Django would have to guess at the correct changes to make. There is + a risk that critical data would be lost in the process. + + If you have made changes to a model and wish to alter the database tables + to match, use the ``sql`` command to display the new SQL structure and + compare that to your existing table schema to work out the changes. + +If you're installing the ``django.contrib.auth`` application, ``syncdb`` will +give you the option of creating a superuser immediately. + +``syncdb`` will also search for and install any fixture named ``initial_data`` +with an appropriate extension (e.g. ``json`` or ``xml``). See the +documentation for ``loaddata`` for details on the specification of fixture +data files. + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + +Example usage:: + + django-admin.py syncdb --verbosity=2 + +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + +test +---- + +Runs tests for all installed models. See :ref:`topics-testing` for more +information. + +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + +Example usage:: + + django-admin.py test --verbosity=2 + +testserver <fixture fixture ...> +-------------------------------- + +**New in Django development version** + +Runs a Django development server (as in ``runserver``) using data from the +given fixture(s). + +For example, this command:: + + django-admin.py testserver mydata.json + +...would perform the following steps: + + 1. Create a test database, as described in :ref:`topics-testing`. + 2. Populate the test database with fixture data from the given fixtures. + (For more on fixtures, see the documentation for ``loaddata`` above.) + 3. Runs the Django development server (as in ``runserver``), pointed at + this newly created test database instead of your production database. + +This is useful in a number of ways: + + * When you're writing :ref:`unit tests <topics-testing>` of how your views + act with certain fixture data, you can use ``testserver`` to interact with + the views in a Web browser, manually. + + * Let's say you're developing your Django application and have a "pristine" + copy of a database that you'd like to interact with. You can dump your + database to a fixture (using the ``dumpdata`` command, explained above), + then use ``testserver`` to run your Web application with that data. With + this arrangement, you have the flexibility of messing up your data + in any way, knowing that whatever data changes you're making are only + being made to a test database. + +Note that this server does *not* automatically detect changes to your Python +source code (as ``runserver`` does). It does, however, detect changes to +templates. + +--addrport [port number or ipaddr:port] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use ``--addrport`` to specify a different port, or IP address and port, from +the default of 127.0.0.1:8000. This value follows exactly the same format and +serves exactly the same function as the argument to the ``runserver`` subcommand. + +Examples: + +To run the test server on port 7000 with ``fixture1`` and ``fixture2``:: + + django-admin.py testserver --addrport 7000 fixture1 fixture2 + django-admin.py testserver fixture1 fixture2 --addrport 7000 + +(The above statements are equivalent. We include both of them to demonstrate +that it doesn't matter whether the options come before or after the fixture +arguments.) + +To run on 1.2.3.4:7000 with a ``test`` fixture:: + + django-admin.py testserver --addrport 1.2.3.4:7000 test + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no output. + * ``1`` means normal output (default). + * ``2`` means verbose output. + +Example usage:: + + django-admin.py testserver --verbosity=2 + +validate +-------- + +Validates all installed models (according to the ``INSTALLED_APPS`` setting) +and prints validation errors to standard output. + +Default options +=============== + +Although some subcommands may allow their own custom options, every subcommand +allows for the following options: + +--pythonpath +------------ + +Example usage:: + + django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject' + +Adds the given filesystem path to the Python `import search path`_. If this +isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment +variable. + +Note that this option is unnecessary in ``manage.py``, because it takes care of +setting the Python path for you. + +.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html + +--settings +---------- + +Example usage:: + + django-admin.py syncdb --settings=mysite.settings + +Explicitly specifies the settings module to use. The settings module should be +in Python package syntax, e.g. ``mysite.settings``. If this isn't provided, +``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment +variable. + +Note that this option is unnecessary in ``manage.py``, because it uses +``settings.py`` from the current project by default. + +--traceback +----------- + +Example usage:: + + django-admin.py syncdb --traceback + +By default, ``django-admin.py`` will show a simple error message whenever an +error occurs. If you specify ``--traceback``, ``django-admin.py`` will +output a full stack trace whenever an exception is raised. + +Extra niceties +============== + +Syntax coloring +--------------- + +The ``django-admin.py`` / ``manage.py`` commands that output SQL to standard +output will use pretty color-coded output if your terminal supports +ANSI-colored output. It won't use the color codes if you're piping the +command's output to another program. + +Bash completion +--------------- + +If you use the Bash shell, consider installing the Django bash completion +script, which lives in ``extras/django_bash_completion`` in the Django +distribution. It enables tab-completion of ``django-admin.py`` and +``manage.py`` commands, so you can, for instance... + + * Type ``django-admin.py``. + * Press [TAB] to see all available options. + * Type ``sql``, then [TAB], to see all available options whose names start + with ``sql``. + + + +See :ref:`howto-custom-management-commands` for how to add customized actions. diff --git a/docs/ref/files/file.txt b/docs/ref/files/file.txt new file mode 100644 index 0000000000..bc59311792 --- /dev/null +++ b/docs/ref/files/file.txt @@ -0,0 +1,117 @@ +.. _ref-files-file: + +The ``File`` object +=================== + +.. currentmodule:: django.core.files + +.. class:: File(file_object) + +``File`` attributes and methods +------------------------------- + +Django's ``File`` has the following attributes and methods: + +``File.path`` +~~~~~~~~~~~~~ + +The absolute path to the file's location on a local filesystem. + +:ref:`Custom file storage systems <howto-custom-file-storage>` may not store +files locally; files stored on these systems will have a ``path`` of ``None``. + +``File.url`` +~~~~~~~~~~~~ + +The URL where the file can be retrieved. This is often useful in :ref:`templates +<topics-templates>`; for example, a bit of a template for displaying a ``Car`` +(see above) might look like:: + + <img src='{{ car.photo.url }}' alt='{{ car.name }}' /> + +``File.size`` +~~~~~~~~~~~~~ + +The size of the file in bytes. + +``File.open(mode=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Open or reopen the file (which by definition also does ``File.seek(0)``). The +``mode`` argument allows the same values as Python's standard ``open()``. + +When reopening a file, ``mode`` will override whatever mode the file was +originally opened with; ``None`` means to reopen with the original mode. + +``File.read(num_bytes=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Read content from the file. The optional ``size`` is the number of bytes to +read; if not specified, the file will be read to the end. + +``File.__iter__()`` +~~~~~~~~~~~~~~~~~~~ + +Iterate over the file yielding one line at a time. + +``File.chunks(chunk_size=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Iterate over the file yielding "chunks" of a given size. ``chunk_size`` defaults +to 64 KB. + +This is especially useful with very large files since it allows them to be +streamed off disk and avoids storing the whole file in memory. + +``File.multiple_chunks(chunk_size=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Returns ``True`` if the file is large enough to require multiple chunks to +access all of its content give some ``chunk_size``. + +``File.write(content)`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Writes the specified content string to the file. Depending on the storage system +behind the scenes, this content might not be fully committed until ``close()`` +is called on the file. + +``File.close()`` +~~~~~~~~~~~~~~~~ + +Close the file. + +Additional ``ImageField`` attributes +------------------------------------ + +``File.width`` and ``File.height`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These attributes provide the dimensions of the image. + +Additional methods on files attached to objects +----------------------------------------------- + +Any ``File`` that's associated with an object (as with ``Car.photo``, above) +will also have a couple of extra methods: + +``File.save(name, content, save=True)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Saves a new file with the file name and contents provided. This will not replace +the existing file, but will create a new file and update the object to point to +it. If ``save`` is ``True``, the model's ``save()`` method will be called once +the file is saved. That is, these two lines:: + + >>> car.photo.save('myphoto.jpg', contents, save=False) + >>> car.save() + +are the same as this one line:: + + >>> car.photo.save('myphoto.jpg', contents, save=True) + +``File.delete(save=True)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Remove the file from the model instance and delete the underlying file. The +``save`` argument works as above. diff --git a/docs/ref/files/index.txt b/docs/ref/files/index.txt new file mode 100644 index 0000000000..bdc327b2d7 --- /dev/null +++ b/docs/ref/files/index.txt @@ -0,0 +1,13 @@ +.. _ref-files-index: + +File handling reference +======================= + +.. module:: django.core.files + :synopsis: File handling and storage + +.. toctree:: + :maxdepth: 1 + + file + storage
\ No newline at end of file diff --git a/docs/ref/files/storage.txt b/docs/ref/files/storage.txt new file mode 100644 index 0000000000..a09cd2f86d --- /dev/null +++ b/docs/ref/files/storage.txt @@ -0,0 +1,50 @@ +.. _ref-files-storage: + +File storage API +================ + +``Storage.exists(name)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +``True`` if a file exists given some ``name``. + +``Storage.path(name)`` +~~~~~~~~~~~~~~~~~~~~~~ + +The local filesystem path where the file can be opened using Python's standard +``open()``. For storage systems that aren't accessible from the local +filesystem, this will raise ``NotImplementedError`` instead. + +``Storage.size(name)`` +~~~~~~~~~~~~~~~~~~~~~~ + +Returns the total size, in bytes, of the file referenced by ``name``. + +``Storage.url(name)`` +~~~~~~~~~~~~~~~~~~~~~ + +Returns the URL where the contents of the file referenced by ``name`` can be +accessed. + +``Storage.open(name, mode='rb')`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Opens the file given by ``name``. Note that although the returned file is +guaranteed to be a ``File`` object, it might actually be some subclass. In the +case of remote file storage this means that reading/writing could be quite slow, +so be warned. + +``Storage.save(name, content)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Saves a new file using the storage system, preferably with the name specified. +If there already exists a file with this name ``name``, the storage system may +modify the filename as necessary to get a unique name. The actual name of the +stored file will be returned. + +``Storage.delete(name)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Deletes the file referenced by ``name``. This method won't raise an exception if +the file doesn't exist. + diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt new file mode 100644 index 0000000000..f8d8a9940a --- /dev/null +++ b/docs/ref/forms/api.txt @@ -0,0 +1,688 @@ +.. _ref-forms-api: + +============= +The Forms API +============= + +.. currentmodule:: django.forms + +.. admonition:: About this document + + This document covers the gritty details of Django's forms API. You should + read the :ref:`introduction to working with forms <topics-forms-index>` + first. + +.. _ref-forms-api-bound-unbound: + +Bound and unbound forms +----------------------- + +A :class:`Form` instance is either **bound** to a set of data, or **unbound**. + + * If it's **bound** to a set of data, it's capable of validating that data + and rendering the form as HTML with the data displayed in the HTML. + + * If it's **unbound**, it cannot do validation (because there's no data to + validate!), but it can still render the blank form as HTML. + +To create an unbound :class:`Form` instance, simply instantiate the class:: + + >>> f = ContactForm() + +To bind data to a form, pass the data as a dictionary as the first parameter to +your :class:`Form` class constructor:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + +In this dictionary, the keys are the field names, which correspond to the +attributes in your :class:`Form` class. The values are the data you're trying to +validate. These will usually be strings, but there's no requirement that they be +strings; the type of data you pass depends on the :class:`Field`, as we'll see +in a moment. + +.. attribute:: Form.is_bound + +If you need to distinguish between bound and unbound form instances at runtime, +check the value of the form's :attr:`~Form.is_bound` attribute:: + + >>> f = ContactForm() + >>> f.is_bound + False + >>> f = ContactForm({'subject': 'hello'}) + >>> f.is_bound + True + +Note that passing an empty dictionary creates a *bound* form with empty data:: + + >>> f = ContactForm({}) + >>> f.is_bound + True + +If you have a bound :class:`Form` instance and want to change the data somehow, +or if you want to bind an unbound :class:`Form` instance to some data, create +another :class:`Form` instance. There is no way to change data in a +:class:`Form` instance. Once a :class:`Form` instance has been created, you +should consider its data immutable, whether it has data or not. + +Using forms to validate data +---------------------------- + +.. method:: Form.is_valid() + +The primary task of a :class:`Form` object is to validate data. With a bound +:class:`Form` instance, call the :meth:`~Form.is_valid` method to run validation +and return a boolean designating whether the data was valid:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + True + +Let's try with some invalid data. In this case, ``subject`` is blank (an error, +because all fields are required by default) and ``sender`` is not a valid +e-mail address:: + + >>> data = {'subject': '', + ... 'message': 'Hi there', + ... 'sender': 'invalid e-mail address', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + False + +.. attribute:: Form.errors + +Access the :attr:`~Form.errors` attribute to get a dictionary of error +messages:: + + >>> f.errors + {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']} + +In this dictionary, the keys are the field names, and the values are lists of +Unicode strings representing the error messages. The error messages are stored +in lists because a field can have multiple error messages. + +You can access :attr:`~Form.errors` without having to call +:meth:`~Form.is_valid` first. The form's data will be validated the first time +either you call :meth:`~Form.is_valid` or access :attr:`~Form.errors`. + +The validation routines will only get called once, regardless of how many times +you access :attr:`~Form.errors` or call :meth:`~Form.is_valid`. This means that +if validation has side effects, those side effects will only be triggered once. + +Behavior of unbound forms +~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's meaningless to validate a form with no data, but, for the record, here's +what happens with unbound forms:: + + >>> f = ContactForm() + >>> f.is_valid() + False + >>> f.errors + {} + +Accessing "clean" data +---------------------- + +Each ``Field`` in a ``Form`` class is responsible not only for validating data, +but also for "cleaning" it -- normalizing it to a consistent format. This is a +nice feature, because it allows data for a particular field to be input in +a variety of ways, always resulting in consistent output. + +For example, ``DateField`` normalizes input into a Python ``datetime.date`` +object. Regardless of whether you pass it a string in the format +``'1994-07-15'``, a ``datetime.date`` object or a number of other formats, +``DateField`` will always normalize it to a ``datetime.date`` object as long as +it's valid. + +Once you've created a ``Form`` instance with a set of data and validated it, +you can access the clean data via the ``cleaned_data`` attribute of the ``Form`` +object:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + True + >>> f.cleaned_data + {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} + +.. note:: + **New in Django development version** The ``cleaned_data`` attribute was + called ``clean_data`` in earlier releases. + +Note that any text-based field -- such as ``CharField`` or ``EmailField`` -- +always cleans the input into a Unicode string. We'll cover the encoding +implications later in this document. + +If your data does *not* validate, your ``Form`` instance will not have a +``cleaned_data`` attribute:: + + >>> data = {'subject': '', + ... 'message': 'Hi there', + ... 'sender': 'invalid e-mail address', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + False + >>> f.cleaned_data + Traceback (most recent call last): + ... + AttributeError: 'ContactForm' object has no attribute 'cleaned_data' + +``cleaned_data`` will always *only* contain a key for fields defined in the +``Form``, even if you pass extra data when you define the ``Form``. In this +example, we pass a bunch of extra fields to the ``ContactForm`` constructor, +but ``cleaned_data`` contains only the form's fields:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True, + ... 'extra_field_1': 'foo', + ... 'extra_field_2': 'bar', + ... 'extra_field_3': 'baz'} + >>> f = ContactForm(data) + >>> f.is_valid() + True + >>> f.cleaned_data # Doesn't contain extra_field_1, etc. + {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} + +``cleaned_data`` will include a key and value for *all* fields defined in the +``Form``, even if the data didn't include a value for fields that are not +required. In this example, the data dictionary doesn't include a value for the +``nick_name`` field, but ``cleaned_data`` includes it, with an empty value:: + + >>> class OptionalPersonForm(Form): + ... first_name = CharField() + ... last_name = CharField() + ... nick_name = CharField(required=False) + >>> data = {'first_name': u'John', 'last_name': u'Lennon'} + >>> f = OptionalPersonForm(data) + >>> f.is_valid() + True + >>> f.cleaned_data + {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} + +In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an +empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat +empty values as an empty string. Each field type knows what its "blank" value +is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For +full details on each field's behavior in this case, see the "Empty value" note +for each field in the "Built-in ``Field`` classes" section below. + +You can write code to perform validation for particular form fields (based on +their name) or for the form as a whole (considering combinations of various +fields). More information about this is in :ref:`ref-forms-validation`. + +Outputting forms as HTML +------------------------ + +The second task of a ``Form`` object is to render itself as HTML. To do so, +simply ``print`` it:: + + >>> f = ContactForm() + >>> print f + <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr> + <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr> + <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr> + <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr> + +If the form is bound to data, the HTML output will include that data +appropriately. For example, if a field is represented by an +``<input type="text">``, the data will be in the ``value`` attribute. If a +field is represented by an ``<input type="checkbox">``, then that HTML will +include ``checked="checked"`` if appropriate:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> print f + <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr> + <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr> + <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr> + <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr> + +This default output is a two-column HTML table, with a ``<tr>`` for each field. +Notice the following: + + * For flexibility, the output does *not* include the ``<table>`` and + ``</table>`` tags, nor does it include the ``<form>`` and ``</form>`` + tags or an ``<input type="submit">`` tag. It's your job to do that. + + * Each field type has a default HTML representation. ``CharField`` and + ``EmailField`` are represented by an ``<input type="text">``. + ``BooleanField`` is represented by an ``<input type="checkbox">``. Note + these are merely sensible defaults; you can specify which HTML to use for + a given field by using widgets, which we'll explain shortly. + + * The HTML ``name`` for each tag is taken directly from its attribute name + in the ``ContactForm`` class. + + * The text label for each field -- e.g. ``'Subject:'``, ``'Message:'`` and + ``'Cc myself:'`` is generated from the field name by converting all + underscores to spaces and upper-casing the first letter. Again, note + these are merely sensible defaults; you can also specify labels manually. + + * Each text label is surrounded in an HTML ``<label>`` tag, which points + to the appropriate form field via its ``id``. Its ``id``, in turn, is + generated by prepending ``'id_'`` to the field name. The ``id`` + attributes and ``<label>`` tags are included in the output by default, to + follow best practices, but you can change that behavior. + +Although ``<table>`` output is the default output style when you ``print`` a +form, other output styles are available. Each style is available as a method on +a form object, and each rendering method returns a Unicode object. + +``as_p()`` +~~~~~~~~~~ + +``Form.as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>`` +containing one field:: + + >>> f = ContactForm() + >>> f.as_p() + u'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>' + >>> print f.as_p() + <p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p> + <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p> + <p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p> + <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> + +``as_ul()`` +~~~~~~~~~~~ + +``Form.as_ul()`` renders the form as a series of ``<li>`` tags, with each +``<li>`` containing one field. It does *not* include the ``<ul>`` or ``</ul>``, +so that you can specify any HTML attributes on the ``<ul>`` for flexibility:: + + >>> f = ContactForm() + >>> f.as_ul() + u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>' + >>> print f.as_ul() + <li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li> + <li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li> + <li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li> + +``as_table()`` +~~~~~~~~~~~~~~ + +Finally, ``Form.as_table()`` outputs the form as an HTML ``<table>``. This is +exactly the same as ``print``. In fact, when you ``print`` a form object, it +calls its ``as_table()`` method behind the scenes:: + + >>> f = ContactForm() + >>> f.as_table() + u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>' + >>> print f.as_table() + <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr> + <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr> + <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr> + <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr> + +.. _ref-forms-api-configuring-label: + +Configuring HTML ``<label>`` tags +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An HTML ``<label>`` tag designates which label text is associated with which +form element. This small enhancement makes forms more usable and more accessible +to assistive devices. It's always a good idea to use ``<label>`` tags. + +By default, the form rendering methods include HTML ``id`` attributes on the +form elements and corresponding ``<label>`` tags around the labels. The ``id`` +attribute values are generated by prepending ``id_`` to the form field names. +This behavior is configurable, though, if you want to change the ``id`` +convention or remove HTML ``id`` attributes and ``<label>`` tags entirely. + +Use the ``auto_id`` argument to the ``Form`` constructor to control the label +and ``id`` behavior. This argument must be ``True``, ``False`` or a string. + +If ``auto_id`` is ``False``, then the form output will not include ``<label>`` +tags nor ``id`` attributes:: + + >>> f = ContactForm(auto_id=False) + >>> print f.as_table() + <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr> + <tr><th>Message:</th><td><input type="text" name="message" /></td></tr> + <tr><th>Sender:</th><td><input type="text" name="sender" /></td></tr> + <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr> + >>> print f.as_ul() + <li>Subject: <input type="text" name="subject" maxlength="100" /></li> + <li>Message: <input type="text" name="message" /></li> + <li>Sender: <input type="text" name="sender" /></li> + <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> + >>> print f.as_p() + <p>Subject: <input type="text" name="subject" maxlength="100" /></p> + <p>Message: <input type="text" name="message" /></p> + <p>Sender: <input type="text" name="sender" /></p> + <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> + +If ``auto_id`` is set to ``True``, then the form output *will* include +``<label>`` tags and will simply use the field name as its ``id`` for each form +field:: + + >>> f = ContactForm(auto_id=True) + >>> print f.as_table() + <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr> + <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr> + <tr><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr> + <tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr> + >>> print f.as_ul() + <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li> + <li><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li> + <li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li> + >>> print f.as_p() + <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p> + <p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p> + <p><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p> + <p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p> + +If ``auto_id`` is set to a string containing the format character ``'%s'``, +then the form output will include ``<label>`` tags, and will generate ``id`` +attributes based on the format string. For example, for a format string +``'field_%s'``, a field named ``subject`` will get the ``id`` value +``'field_subject'``. Continuing our example:: + + >>> f = ContactForm(auto_id='id_for_%s') + >>> print f.as_table() + <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr> + <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr> + <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr> + <tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr> + >>> print f.as_ul() + <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li> + <li><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li> + <li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> + >>> print f.as_p() + <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p> + <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p> + <p><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p> + <p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p> + +If ``auto_id`` is set to any other true value -- such as a string that doesn't +include ``%s`` -- then the library will act as if ``auto_id`` is ``True``. + +By default, ``auto_id`` is set to the string ``'id_%s'``. + +Normally, a colon (``:``) will be appended after any label name when a form is +rendered. It's possible to change the colon to another character, or omit it +entirely, using the ``label_suffix`` parameter:: + + >>> f = ContactForm(auto_id='id_for_%s', label_suffix='') + >>> print f.as_ul() + <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li> + <li><label for="id_for_sender">Sender</label> <input type="text" name="sender" id="id_for_sender" /></li> + <li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> + >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->') + >>> print f.as_ul() + <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li> + <li><label for="id_for_sender">Sender -></label> <input type="text" name="sender" id="id_for_sender" /></li> + <li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> + +Note that the label suffix is added only if the last character of the +label isn't a punctuation character (``.``, ``!``, ``?`` or ``:``) + +Notes on field ordering +~~~~~~~~~~~~~~~~~~~~~~~ + +In the ``as_p()``, ``as_ul()`` and ``as_table()`` shortcuts, the fields are +displayed in the order in which you define them in your form class. For +example, in the ``ContactForm`` example, the fields are defined in the order +``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML +output, just change the order in which those fields are listed in the class. + +How errors are displayed +~~~~~~~~~~~~~~~~~~~~~~~~ + +If you render a bound ``Form`` object, the act of rendering will automatically +run the form's validation if it hasn't already happened, and the HTML output +will include the validation errors as a ``<ul class="errorlist">`` near the +field. The particular positioning of the error messages depends on the output +method you're using:: + + >>> data = {'subject': '', + ... 'message': 'Hi there', + ... 'sender': 'invalid e-mail address', + ... 'cc_myself': True} + >>> f = ContactForm(data, auto_id=False) + >>> print f.as_table() + <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr> + <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr> + <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr> + <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr> + >>> print f.as_ul() + <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li> + <li>Message: <input type="text" name="message" value="Hi there" /></li> + <li><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li> + <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li> + >>> print f.as_p() + <p><ul class="errorlist"><li>This field is required.</li></ul></p> + <p>Subject: <input type="text" name="subject" maxlength="100" /></p> + <p>Message: <input type="text" name="message" value="Hi there" /></p> + <p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p> + <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> + <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> + +Customizing the error list format +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, forms use ``django.forms.util.ErrorList`` to format validation +errors. If you'd like to use an alternate class for displaying errors, you can +pass that in at construction time:: + + >>> from django.forms.util import ErrorList + >>> class DivErrorList(ErrorList): + ... def __unicode__(self): + ... return self.as_divs() + ... def as_divs(self): + ... if not self: return u'' + ... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self]) + >>> f = ContactForm(data, auto_id=False, error_class=DivErrorList) + >>> f.as_p() + <div class="errorlist"><div class="error">This field is required.</div></div> + <p>Subject: <input type="text" name="subject" maxlength="100" /></p> + <p>Message: <input type="text" name="message" value="Hi there" /></p> + <div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> + <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> + <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> + +More granular output +~~~~~~~~~~~~~~~~~~~~ + +The ``as_p()``, ``as_ul()`` and ``as_table()`` methods are simply shortcuts for +lazy developers -- they're not the only way a form object can be displayed. + +To display the HTML for a single field in your form, use dictionary lookup +syntax using the field's name as the key, and print the resulting object:: + + >>> f = ContactForm() + >>> print f['subject'] + <input id="id_subject" type="text" name="subject" maxlength="100" /> + >>> print f['message'] + <input type="text" name="message" id="id_message" /> + >>> print f['sender'] + <input type="text" name="sender" id="id_sender" /> + >>> print f['cc_myself'] + <input type="checkbox" name="cc_myself" id="id_cc_myself" /> + +Call ``str()`` or ``unicode()`` on the field to get its rendered HTML as a +string or Unicode object, respectively:: + + >>> str(f['subject']) + '<input id="id_subject" type="text" name="subject" maxlength="100" />' + >>> unicode(f['subject']) + u'<input id="id_subject" type="text" name="subject" maxlength="100" />' + +The field-specific output honors the form object's ``auto_id`` setting:: + + >>> f = ContactForm(auto_id=False) + >>> print f['message'] + <input type="text" name="message" /> + >>> f = ContactForm(auto_id='id_%s') + >>> print f['message'] + <input type="text" name="message" id="id_message" /> + +For a field's list of errors, access the field's ``errors`` attribute. This +is a list-like object that is displayed as an HTML ``<ul class="errorlist">`` +when printed:: + + >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''} + >>> f = ContactForm(data, auto_id=False) + >>> print f['message'] + <input type="text" name="message" /> + >>> f['message'].errors + [u'This field is required.'] + >>> print f['message'].errors + <ul class="errorlist"><li>This field is required.</li></ul> + >>> f['subject'].errors + [] + >>> print f['subject'].errors + + >>> str(f['subject'].errors) + '' + +.. _binding-uploaded-files: + +Binding uploaded files to a form +-------------------------------- + +**New in Django development version** + +Dealing with forms that have ``FileField`` and ``ImageField`` fields +is a little more complicated than a normal form. + +Firstly, in order to upload files, you'll need to make sure that your +``<form>`` element correctly defines the ``enctype`` as +``"multipart/form-data"``:: + + <form enctype="multipart/form-data" method="post" action="/foo/"> + +Secondly, when you use the form, you need to bind the file data. File +data is handled separately to normal form data, so when your form +contains a ``FileField`` and ``ImageField``, you will need to specify +a second argument when you bind your form. So if we extend our +ContactForm to include an ``ImageField`` called ``mugshot``, we +need to bind the file data containing the mugshot image:: + + # Bound form with an image field + >>> from django.core.files.uploadedfile import SimpleUploadedFile + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)} + >>> f = ContactFormWithMugshot(data, file_data) + +In practice, you will usually specify ``request.FILES`` as the source +of file data (just like you use ``request.POST`` as the source of +form data):: + + # Bound form with an image field, data from the request + >>> f = ContactFormWithMugshot(request.POST, request.FILES) + +Constructing an unbound form is the same as always -- just omit both +form data *and* file data:: + + # Unbound form with a image field + >>> f = ContactFormWithMugshot() + +Testing for multipart forms +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you're writing reusable views or templates, you may not know ahead of time +whether your form is a multipart form or not. The ``is_multipart()`` method +tells you whether the form requires multipart encoding for submission:: + + >>> f = ContactFormWithMugshot() + >>> f.is_multipart() + True + +Here's an example of how you might use this in a template:: + + {% if form.is_multipart %} + <form enctype="multipart/form-data" method="post" action="/foo/"> + {% else %} + <form method="post" action="/foo/"> + {% endif %} + {{ form }} + </form> + +Subclassing forms +----------------- + +If you have multiple ``Form`` classes that share fields, you can use +subclassing to remove redundancy. + +When you subclass a custom ``Form`` class, the resulting subclass will +include all fields of the parent class(es), followed by the fields you define +in the subclass. + +In this example, ``ContactFormWithPriority`` contains all the fields from +``ContactForm``, plus an additional field, ``priority``. The ``ContactForm`` +fields are ordered first:: + + >>> class ContactFormWithPriority(ContactForm): + ... priority = forms.CharField() + >>> f = ContactFormWithPriority(auto_id=False) + >>> print f.as_ul() + <li>Subject: <input type="text" name="subject" maxlength="100" /></li> + <li>Message: <input type="text" name="message" /></li> + <li>Sender: <input type="text" name="sender" /></li> + <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> + <li>Priority: <input type="text" name="priority" /></li> + +It's possible to subclass multiple forms, treating forms as "mix-ins." In this +example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm`` +(in that order), and its field list includes the fields from the parent +classes:: + + >>> class PersonForm(Form): + ... first_name = CharField() + ... last_name = CharField() + >>> class InstrumentForm(Form): + ... instrument = CharField() + >>> class BeatleForm(PersonForm, InstrumentForm): + ... haircut_type = CharField() + >>> b = BeatleForm(auto_id=False) + >>> print b.as_ul() + <li>First name: <input type="text" name="first_name" /></li> + <li>Last name: <input type="text" name="last_name" /></li> + <li>Instrument: <input type="text" name="instrument" /></li> + <li>Haircut type: <input type="text" name="haircut_type" /></li> + +.. _form-prefix: + +Prefixes for forms +------------------ + +.. attribute:: Form.prefix + +You can put several Django forms inside one ``<form>`` tag. To give each +``Form`` its own namespace, use the ``prefix`` keyword argument:: + + >>> mother = PersonForm(prefix="mother") + >>> father = PersonForm(prefix="father") + >>> print mother.as_ul() + <li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" /></li> + <li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" /></li> + >>> print father.as_ul() + <li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li> + <li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li> diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt new file mode 100644 index 0000000000..161c550d37 --- /dev/null +++ b/docs/ref/forms/fields.txt @@ -0,0 +1,751 @@ +.. _ref-forms-fields: + +=========== +Form fields +=========== + +.. module:: django.forms.fields + :synopsis: Django's built-in form fields. + +.. currentmodule:: django.forms + +.. class:: Field(**kwargs) + +When you create a ``Form`` class, the most important part is defining the +fields of the form. Each field has custom validation logic, along with a few +other hooks. + +.. method:: Field.clean(value) + +Although the primary way you'll use ``Field`` classes is in ``Form`` classes, +you can also instantiate them and use them directly to get a better idea of +how they work. Each ``Field`` instance has a ``clean()`` method, which takes +a single argument and either raises a ``django.forms.ValidationError`` +exception or returns the clean value:: + + >>> f = forms.EmailField() + >>> f.clean('foo@example.com') + u'foo@example.com' + >>> f.clean(u'foo@example.com') + u'foo@example.com' + >>> f.clean('invalid e-mail address') + Traceback (most recent call last): + ... + ValidationError: [u'Enter a valid e-mail address.'] + +If you've used Django's old forms/validation framework, take care in noticing +this ``ValidationError`` is different than the previous ``ValidationError``. +This one lives at ``django.forms.ValidationError`` rather than +``django.core.validators.ValidationError``. + +Core field arguments +-------------------- + +Each ``Field`` class constructor takes at least these arguments. Some +``Field`` classes take additional, field-specific arguments, but the following +should *always* be accepted: + +``required`` +~~~~~~~~~~~~ + +.. attribute:: Field.required + +By default, each ``Field`` class assumes the value is required, so if you pass +an empty value -- either ``None`` or the empty string (``""``) -- then +``clean()`` will raise a ``ValidationError`` exception:: + + >>> f = forms.CharField() + >>> f.clean('foo') + u'foo' + >>> f.clean('') + Traceback (most recent call last): + ... + ValidationError: [u'This field is required.'] + >>> f.clean(None) + Traceback (most recent call last): + ... + ValidationError: [u'This field is required.'] + >>> f.clean(' ') + u' ' + >>> f.clean(0) + u'0' + >>> f.clean(True) + u'True' + >>> f.clean(False) + u'False' + +To specify that a field is *not* required, pass ``required=False`` to the +``Field`` constructor:: + + >>> f = forms.CharField(required=False) + >>> f.clean('foo') + u'foo' + >>> f.clean('') + u'' + >>> f.clean(None) + u'' + >>> f.clean(0) + u'0' + >>> f.clean(True) + u'True' + >>> f.clean(False) + u'False' + +If a ``Field`` has ``required=False`` and you pass ``clean()`` an empty value, +then ``clean()`` will return a *normalized* empty value rather than raising +``ValidationError``. For ``CharField``, this will be a Unicode empty string. +For other ``Field`` classes, it might be ``None``. (This varies from field to +field.) + +``label`` +~~~~~~~~~ + +.. attribute:: Field.label + +The ``label`` argument lets you specify the "human-friendly" label for this +field. This is used when the ``Field`` is displayed in a ``Form``. + +As explained in "Outputting forms as HTML" above, the default label for a +``Field`` is generated from the field name by converting all underscores to +spaces and upper-casing the first letter. Specify ``label`` if that default +behavior doesn't result in an adequate label. + +Here's a full example ``Form`` that implements ``label`` for two of its fields. +We've specified ``auto_id=False`` to simplify the output:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField(label='Your name') + ... url = forms.URLField(label='Your Web site', required=False) + ... comment = forms.CharField() + >>> f = CommentForm(auto_id=False) + >>> print f + <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr> + <tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + +``initial`` +~~~~~~~~~~~ + +.. attribute:: Field.initial + +The ``initial`` argument lets you specify the initial value to use when +rendering this ``Field`` in an unbound ``Form``. + +The use-case for this is when you want to display an "empty" form in which a +field is initialized to a particular value. For example:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField(initial='Your name') + ... url = forms.URLField(initial='http://') + ... comment = forms.CharField() + >>> f = CommentForm(auto_id=False) + >>> print f + <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr> + <tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + +You may be thinking, why not just pass a dictionary of the initial values as +data when displaying the form? Well, if you do that, you'll trigger validation, +and the HTML output will include any validation errors:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField() + ... url = forms.URLField() + ... comment = forms.CharField() + >>> default_data = {'name': 'Your name', 'url': 'http://'} + >>> f = CommentForm(default_data, auto_id=False) + >>> print f + <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr> + <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr> + <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr> + +This is why ``initial`` values are only displayed for unbound forms. For bound +forms, the HTML output will use the bound data. + +Also note that ``initial`` values are *not* used as "fallback" data in +validation if a particular field's value is not given. ``initial`` values are +*only* intended for initial form display:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField(initial='Your name') + ... url = forms.URLField(initial='http://') + ... comment = forms.CharField() + >>> data = {'name': '', 'url': '', 'comment': 'Foo'} + >>> f = CommentForm(data) + >>> f.is_valid() + False + # The form does *not* fall back to using the initial values. + >>> f.errors + {'url': [u'This field is required.'], 'name': [u'This field is required.']} + +``widget`` +~~~~~~~~~~ + +.. attribute:: Field.widget + +The ``widget`` argument lets you specify a ``Widget`` class to use when +rendering this ``Field``. See :ref:`ref-forms-widgets` for more information. + +``help_text`` +~~~~~~~~~~~~~ + +.. attribute:: Field.help_text + +The ``help_text`` argument lets you specify descriptive text for this +``Field``. If you provide ``help_text``, it will be displayed next to the +``Field`` when the ``Field`` is rendered by one of the convenience ``Form`` +methods (e.g., ``as_ul()``). + +Here's a full example ``Form`` that implements ``help_text`` for two of its +fields. We've specified ``auto_id=False`` to simplify the output:: + + >>> class HelpTextContactForm(forms.Form): + ... subject = forms.CharField(max_length=100, help_text='100 characters max.') + ... message = forms.CharField() + ... sender = forms.EmailField(help_text='A valid e-mail address, please.') + ... cc_myself = forms.BooleanField(required=False) + >>> f = HelpTextContactForm(auto_id=False) + >>> print f.as_table() + <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr> + <tr><th>Message:</th><td><input type="text" name="message" /></td></tr> + <tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr> + <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr> + >>> print f.as_ul() + <li>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li> + <li>Message: <input type="text" name="message" /></li> + <li>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li> + <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> + >>> print f.as_p() + <p>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p> + <p>Message: <input type="text" name="message" /></p> + <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p> + <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> + +``error_messages`` +~~~~~~~~~~~~~~~~~~ + +.. attribute:: Field.error_messages + +**New in Django development version** + +The ``error_messages`` argument lets you override the default messages that the +field will raise. Pass in a dictionary with keys matching the error messages you +want to override. For example, here is the default error message:: + + >>> generic = forms.CharField() + >>> generic.clean('') + Traceback (most recent call last): + ... + ValidationError: [u'This field is required.'] + +And here is a custom error message:: + + >>> name = forms.CharField(error_messages={'required': 'Please enter your name'}) + >>> name.clean('') + Traceback (most recent call last): + ... + ValidationError: [u'Please enter your name'] + +In the `built-in Field classes`_ section below, each ``Field`` defines the +error message keys it uses. + +Dynamic initial values +---------------------- + +The ``initial`` argument to ``Field`` (explained above) lets you hard-code the +initial value for a ``Field`` -- but what if you want to declare the initial +value at runtime? For example, you might want to fill in a ``username`` field +with the username of the current session. + +To accomplish this, use the ``initial`` argument to a ``Form``. This argument, +if given, should be a dictionary mapping field names to initial values. Only +include the fields for which you're specifying an initial value; it's not +necessary to include every field in your form. For example:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField() + ... url = forms.URLField() + ... comment = forms.CharField() + >>> f = CommentForm(initial={'name': 'your username'}, auto_id=False) + >>> print f + <tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr> + <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + >>> f = CommentForm(initial={'name': 'another username'}, auto_id=False) + >>> print f + <tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr> + <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + +Just like the ``initial`` parameter to ``Field``, these values are only +displayed for unbound forms, and they're not used as fallback values if a +particular value isn't provided. + +Finally, note that if a ``Field`` defines ``initial`` *and* you include +``initial`` when instantiating the ``Form``, then the latter ``initial`` will +have precedence. In this example, ``initial`` is provided both at the field +level and at the form instance level, and the latter gets precedence:: + + >>> class CommentForm(forms.Form): + ... name = forms.CharField(initial='class') + ... url = forms.URLField() + ... comment = forms.CharField() + >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) + >>> print f + <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr> + <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + + +Built-in ``Field`` classes +-------------------------- + +Naturally, the ``forms`` library comes with a set of ``Field`` classes that +represent common validation needs. This section documents each built-in field. + +For each field, we describe the default widget used if you don't specify +``widget``. We also specify the value returned when you provide an empty value +(see the section on ``required`` above to understand what that means). + +``BooleanField`` +~~~~~~~~~~~~~~~~ + +.. class:: BooleanField(**kwargs) + + * Default widget: ``CheckboxInput`` + * Empty value: ``False`` + * Normalizes to: A Python ``True`` or ``False`` value. + * Validates that the check box is checked (i.e. the value is ``True``) if + the field has ``required=True``. + * Error message keys: ``required`` + +**New in Django development version:** The empty value for a ``CheckboxInput`` +(and hence the standard ``BooleanField``) has changed to return ``False`` +instead of ``None`` in the development version. + +.. note:: + Since all ``Field`` subclasses have ``required=True`` by default, the + validation condition here is important. If you want to include a checkbox + in your form that can be either checked or unchecked, you must remember to + pass in ``required=False`` when creating the ``BooleanField``. + +``CharField`` +~~~~~~~~~~~~~ + +.. class:: CharField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates ``max_length`` or ``min_length``, if they are provided. + Otherwise, all inputs are valid. + * Error message keys: ``required``, ``max_length``, ``min_length`` + +Has two optional arguments for validation: + +.. attribute:: CharField.max_length +.. attribute:: CharField.min_length + If provided, these arguments ensure that the string is at most or at least + the given length. + +``ChoiceField`` +~~~~~~~~~~~~~~~ + +.. class:: ChoiceField(**kwargs) + + * Default widget: ``Select`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value exists in the list of choices. + * Error message keys: ``required``, ``invalid_choice`` + +Takes one extra required argument: + +.. attribute:: ChoiceField.choices + An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this + field. + +``DateField`` +~~~~~~~~~~~~~ + +.. class:: DateField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python ``datetime.date`` object. + * Validates that the given value is either a ``datetime.date``, + ``datetime.datetime`` or string formatted in a particular date format. + * Error message keys: ``required``, ``invalid`` + +Takes one optional argument: + +.. attribute:: DateField.input_formats + A list of formats used to attempt to convert a string to a valid + ``datetime.date`` object. + +If no ``input_formats`` argument is provided, the default input formats are:: + + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' + +``DateTimeField`` +~~~~~~~~~~~~~~~~~ + +.. class:: DateTimeField(**kwargs) + + * Default widget: ``DateTimeInput`` + * Empty value: ``None`` + * Normalizes to: A Python ``datetime.datetime`` object. + * Validates that the given value is either a ``datetime.datetime``, + ``datetime.date`` or string formatted in a particular datetime format. + * Error message keys: ``required``, ``invalid`` + +Takes one optional argument: + +.. attribute:: DateTimeField.input_formats + A list of formats used to attempt to convert a string to a valid + ``datetime.datetime`` object. + +If no ``input_formats`` argument is provided, the default input formats are:: + + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' + +**New in Django development version:** The ``DateTimeField`` used to use a +``TextInput`` widget by default. This has now changed. + +``DecimalField`` +~~~~~~~~~~~~~~~~ + +.. class:: DecimalField(**kwargs) + +**New in Django development version** + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python ``decimal``. + * Validates that the given value is a decimal. Leading and trailing + whitespace is ignored. + * Error message keys: ``required``, ``invalid``, ``max_value``, + ``min_value``, ``max_digits``, ``max_decimal_places``, + ``max_whole_digits`` + +Takes four optional arguments: + +.. attribute:: DecimalField.max_value +.. attribute:: DecimalField.min_value + These attributes define the limits for the fields value. + +.. attribute:: DecimalField.max_digits + The maximum number of digits (those before the decimal point plus those + after the decimal point, with leading zeros stripped) permitted in the + value. + +.. attribute:: DecimalField.decimal_places + The maximum number of decimal places permitted. + +``EmailField`` +~~~~~~~~~~~~~~ + +.. class:: EmailField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value is a valid e-mail address, using a + moderately complex regular expression. + * Error message keys: ``required``, ``invalid`` + +Has two optional arguments for validation, ``max_length`` and ``min_length``. +If provided, these arguments ensure that the string is at most or at least the +given length. + +``FileField`` +~~~~~~~~~~~~~ + +.. class:: FileField(**kwargs) + +**New in Django development version** + + * Default widget: ``FileInput`` + * Empty value: ``None`` + * Normalizes to: An ``UploadedFile`` object that wraps the file content + and file name into a single object. + * Validates that non-empty file data has been bound to the form. + * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` + +To learn more about the ``UploadedFile`` object, see the :ref:`file uploads +documentation <topics-file-uploads>`. + +When you use a ``FileField`` in a form, you must also remember to +:ref:`bind the file data to the form <topics-file-uploads>`. + +``FilePathField`` +~~~~~~~~~~~~~~~~~ + +.. class:: FilePathField(**kwargs) + +**New in Django development version** + + * Default widget: ``Select`` + * Empty value: ``None`` + * Normalizes to: A unicode object + * Validates that the selected choice exists in the list of choices. + * Error message keys: ``required``, ``invalid_choice`` + +The field allows choosing from files inside a certain directory. It takes three +extra arguments; only ``path`` is required: + +.. attribute:: FilePathField.path + The absolute path to the directory whose contents you want listed. This + directory must exist. + +.. attribute:: FilePathField.recursive + If ``False`` (the default) only the direct contents of ``path`` will be + offered as choices. If ``True``, the directory will be descended into + recursively and all descendants will be listed as choices. + +.. attribute:: FilePathField.match + A regular expression pattern; only files with names matching this expression + will be allowed as choices. + +``FloatField`` +~~~~~~~~~~~~~~ + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python float. + * Validates that the given value is an float. Leading and trailing + whitespace is allowed, as in Python's ``float()`` function. + * Error message keys: ``required``, ``invalid``, ``max_value``, + ``min_value`` + +Takes two optional arguments for validation, ``max_value`` and ``min_value``. +These control the range of values permitted in the field. + +``ImageField`` +~~~~~~~~~~~~~~ + +.. class:: ImageField(**kwargs) + +**New in Django development version** + + * Default widget: ``FileInput`` + * Empty value: ``None`` + * Normalizes to: An ``UploadedFile`` object that wraps the file content + and file name into a single object. + * Validates that file data has been bound to the form, and that the + file is of an image format understood by PIL. + * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, + ``invalid_image`` + +Using an ImageField requires that the `Python Imaging Library`_ is installed. + +When you use an ``ImageField`` on a form, you must also remember to +:ref:`bind the file data to the form <topics-file-uploads>`. + +.. _Python Imaging Library: http://www.pythonware.com/products/pil/ + +``IntegerField`` +~~~~~~~~~~~~~~~~ + +.. class:: IntegerField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python integer or long integer. + * Validates that the given value is an integer. Leading and trailing + whitespace is allowed, as in Python's ``int()`` function. + * Error message keys: ``required``, ``invalid``, ``max_value``, + ``min_value`` + +Takes two optional arguments for validation: + +.. attribute:: IntegerField.max_value +.. attribute:: IntegerField.min_value + These control the range of values permitted in the field. + +``IPAddressField`` +~~~~~~~~~~~~~~~~~~ + +.. class:: IPAddressField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value is a valid IPv4 address, using a regular + expression. + * Error message keys: ``required``, ``invalid`` + +``MultipleChoiceField`` +~~~~~~~~~~~~~~~~~~~~~~~ + +.. class:: MultipleChoiceField(**kwargs) + + * Default widget: ``SelectMultiple`` + * Empty value: ``[]`` (an empty list) + * Normalizes to: A list of Unicode objects. + * Validates that every value in the given list of values exists in the list + of choices. + * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` + +Takes one extra argument, ``choices``, as for ``ChoiceField``. + +``NullBooleanField`` +~~~~~~~~~~~~~~~~~~~~ + +.. class:: NullBooleanField(**kwargs) + + * Default widget: ``NullBooleanSelect`` + * Empty value: ``None`` + * Normalizes to: A Python ``True``, ``False`` or ``None`` value. + * Validates nothing (i.e., it never raises a ``ValidationError``). + +``RegexField`` +~~~~~~~~~~~~~~ + +.. class:: RegexField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value matches against a certain regular + expression. + * Error message keys: ``required``, ``invalid`` + +Takes one required argument: + +.. attribute:: RegexField.regex`` + A regular expression specified either as a string or a compiled regular + expression object. + +Also takes ``max_length`` and ``min_length``, which work just as they do for +``CharField``. + +The optional argument ``error_message`` is also accepted for backwards +compatibility. The preferred way to provide an error message is to use the +``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key +and the error message as the value. + +``TimeField`` +~~~~~~~~~~~~~ + +.. class:: TimeField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python ``datetime.time`` object. + * Validates that the given value is either a ``datetime.time`` or string + formatted in a particular time format. + * Error message keys: ``required``, ``invalid`` + +Takes one optional argument: + +.. attribute:: TimeField.input_formats + A list of formats used to attempt to convert a string to a valid + ``datetime.time`` object. + +If no ``input_formats`` argument is provided, the default input formats are:: + + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' + +``URLField`` +~~~~~~~~~~~~ + +.. class:: URLField(**kwargs) + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value is a valid URL. + * Error message keys: ``required``, ``invalid``, ``invalid_link`` + +Takes the following optional arguments: + + +.. attribute:: URLField.max_length +.. attribute:: URLField.min_length + Same as ``CharField.max_length`` and ``CharField.min_length``. + +.. attribute:: URLField.verify_exists + If ``True``, the validator will attempt to load the given URL, raising + ``ValidationError`` if the page gives a 404. Defaults to ``False``. + +.. attribute:: URLField.validator_user_agent + String used as the user-agent used when checking for a URL's existence. + Defaults to the value of the ``URL_VALIDATOR_USER_AGENT`` setting. + +Slightly complex built-in ``Field`` classes +------------------------------------------- + +The following are not yet documented. + +.. class:: ComboField(**kwargs) + +.. class:: MultiValueField(**kwargs) + +.. class:: SplitDateTimeField(**kwargs) + +Fields which handle relationships +--------------------------------- + +For representing relationships between models, two fields are +provided which can derive their choices from a ``QuerySet``: + +.. class:: ModelChoiceField(**kwargs) +.. class:: ModelMultipleChoiceField(**kwargs) + +These fields place one or more model objects into the ``cleaned_data`` +dictionary of forms in which they're used. Both of these fields have an +additional required argument: + +.. attribute:: ModelChoiceField.queryset + A ``QuerySet`` of model objects from which the choices for the + field will be derived, and which will be used to validate the + user's selection. + +``ModelChoiceField`` +~~~~~~~~~~~~~~~~~~~~ + +Allows the selection of a single model object, suitable for +representing a foreign key. + +The ``__unicode__`` method of the model will be called to generate +string representations of the objects for use in the field's choices; +to provide customized representations, subclass ``ModelChoiceField`` +and override ``label_from_instance``. This method will receive a model +object, and should return a string suitable for representing it. For +example:: + + class MyModelChoiceField(ModelChoiceField): + def label_from_instance(self, obj): + return "My Object #%i" % obj.id + +``ModelMultipleChoiceField`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Allows the selection of one or more model objects, suitable for +representing a many-to-many relation. As with ``ModelChoiceField``, +you can use ``label_from_instance`` to customize the object +representations. + +Creating custom fields +---------------------- + +If the built-in ``Field`` classes don't meet your needs, you can easily create +custom ``Field`` classes. To do this, just create a subclass of +``django.forms.Field``. Its only requirements are that it implement a +``clean()`` method and that its ``__init__()`` method accept the core arguments +mentioned above (``required``, ``label``, ``initial``, ``widget``, +``help_text``). diff --git a/docs/ref/forms/index.txt b/docs/ref/forms/index.txt new file mode 100644 index 0000000000..a9e041c2a7 --- /dev/null +++ b/docs/ref/forms/index.txt @@ -0,0 +1,14 @@ +.. _ref-forms-index: + +Forms +===== + +Detailed form API reference. For introductory material, see :ref:`topics-forms-index`. + +.. toctree:: + :maxdepth: 1 + + api + fields + widgets + validation
\ No newline at end of file diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt new file mode 100644 index 0000000000..56c0e098c3 --- /dev/null +++ b/docs/ref/forms/validation.txt @@ -0,0 +1,109 @@ +.. _ref-forms-validation: + +F and field validation +====================== + +Form validation happens when the data is cleaned. If you want to customize +this process, there are various places you can change, each one serving a +different purpose. Three types of cleaning methods are run during form +processing. These are normally executed when you call the ``is_valid()`` +method on a form. There are other things that can trigger cleaning and +validation (accessing the ``errors`` attribute or calling ``full_clean()`` +directly), but normally they won't be needed. + +In general, any cleaning method can raise ``ValidationError`` if there is a +problem with the data it is processing, passing the relevant error message to +the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the +method should return the cleaned (normalized) data as a Python object. + +If you detect multiple errors during a cleaning method and wish to signal all +of them to the form submitter, it is possible to pass a list of errors to the +``ValidationError`` constructor. + +The three types of cleaning methods are: + + * The ``clean()`` method on a Field subclass. This is responsible + for cleaning the data in a way that is generic for that type of field. + For example, a FloatField will turn the data into a Python ``float`` or + raise a ``ValidationError``. + + * The ``clean_<fieldname>()`` method in a form subclass -- where + ``<fieldname>`` is replaced with the name of the form field attribute. + This method does any cleaning that is specific to that particular + attribute, unrelated to the type of field that it is. This method is not + passed any parameters. You will need to look up the value of the field + in ``self.cleaned_data`` and remember that it will be a Python object + at this point, not the original string submitted in the form (it will be + in ``cleaned_data`` because the general field ``clean()`` method, above, + has already cleaned the data once). + + For example, if you wanted to validate that the contents of a + ``CharField`` called ``serialnumber`` was unique, + ``clean_serialnumber()`` would be the right place to do this. You don't + need a specific field (it's just a ``CharField``), but you want a + formfield-specific piece of validation and, possibly, + cleaning/normalizing the data. + + * The Form subclass's ``clean()`` method. This method can perform + any validation that requires access to multiple fields from the form at + once. This is where you might put in things to check that if field ``A`` + is supplied, field ``B`` must contain a valid e-mail address and the + like. The data that this method returns is the final ``cleaned_data`` + attribute for the form, so don't forget to return the full list of + cleaned data if you override this method (by default, ``Form.clean()`` + just returns ``self.cleaned_data``). + + Note that any errors raised by your ``Form.clean()`` override will not + be associated with any field in particular. They go into a special + "field" (called ``__all__``), which you can access via the + ``non_field_errors()`` method if you need to. + +These methods are run in the order given above, one field at a time. That is, +for each field in the form (in the order they are declared in the form +definition), the ``Field.clean()`` method (or its override) is run, then +``clean_<fieldname>()``. Finally, once those two methods are run for every +field, the ``Form.clean()`` method, or its override, is executed. + +As mentioned above, any of these methods can raise a ``ValidationError``. For +any field, if the ``Field.clean()`` method raises a ``ValidationError``, any +field-specific cleaning method is not called. However, the cleaning methods +for all remaining fields are still executed. + +The ``clean()`` method for the ``Form`` class or subclass is always run. If +that method raises a ``ValidationError``, ``cleaned_data`` will be an empty +dictionary. + +The previous paragraph means that if you are overriding ``Form.clean()``, you +should iterate through ``self.cleaned_data.items()``, possibly considering the +``_errors`` dictionary attribute on the form as well. In this way, you will +already know which fields have passed their individual validation requirements. + +A simple example +~~~~~~~~~~~~~~~~ + +Here's a simple example of a custom field that validates its input is a string +containing comma-separated e-mail addresses, with at least one address. We'll +keep it simple and assume e-mail validation is contained in a function called +``is_valid_email()``. The full class:: + + from django import forms + + class MultiEmailField(forms.Field): + def clean(self, value): + if not value: + raise forms.ValidationError('Enter at least one e-mail address.') + emails = value.split(',') + for email in emails: + if not is_valid_email(email): + raise forms.ValidationError('%s is not a valid e-mail address.' % email) + return emails + +Let's alter the ongoing ``ContactForm`` example to demonstrate how you'd use +this in a form. Simply use ``MultiEmailField`` instead of ``forms.EmailField``, +like so:: + + class ContactForm(forms.Form): + subject = forms.CharField(max_length=100) + message = forms.CharField() + senders = MultiEmailField() + cc_myself = forms.BooleanField(required=False) diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt new file mode 100644 index 0000000000..184515ec95 --- /dev/null +++ b/docs/ref/forms/widgets.txt @@ -0,0 +1,156 @@ +.. _ref-forms-widgets: + +======= +Widgets +======= + +.. module:: django.forms.widgets + :synopsis: Django's built-in form widgets. + +.. currentmodule:: django.forms + +A widget is Django's representation of a HTML input element. The widget +handles the rendering of the HTML, and the extraction of data from a GET/POST +dictionary that corresponds to the widget. + +Django provides a representation of all the basic HTML widgets, plus some +commonly used groups of widgets: + +.. class:: TextInput + Text input: ``<input type='text' ...>`` + +.. class:: PasswordInput + Password input: ``<input type='password' ...>`` + +.. class:: HiddenInput + Hidden input: ``<input type='hidden' ...>`` + +.. class:: MultipleHiddenInput + Multiple ``<input type='hidden' ...>`` widgets. + +.. class:: FileInput + File upload input: ``<input type='file' ...>`` + +.. class:: DateTimeInput + Date/time input as a simple text box: ``<input type='text' ...>`` + + **New in Django development version:** + +.. class:: Textarea + Text area: ``<textarea>...</textarea>`` + +.. class:: CheckboxInput + Checkbox: ``<input type='checkbox' ...>`` + +.. class:: Select + Select widget: ``<select><option ...>...</select>`` + +.. class:: NullBooleanSelect + Select widget with options 'Unknown', 'Yes' and 'No' + +.. class:: SelectMultiple + Select widget allowing multiple selection: ``<select + multiple='multiple'>...</select>`` + +.. class:: RadioSelect + A list of radio buttons: + + .. code-block:: html + + <ul> + <li><input type='radio' ...></li> + ... + </ul> + +.. class:: CheckboxSelectMultiple + A list of checkboxes: + + .. code-block:: html + + <ul> + <li><input type='checkbox' ...></li> + ... + </ul> + +.. class:: MultiWidget + Wrapper around multiple other widgets + +.. class:: SplitDateTimeWidget + Wrapper around two ``TextInput`` widgets: one for the date, and one for the + time. + +Specifying widgets +------------------ + +.. attribute:: Form.widget + +Whenever you specify a field on a form, Django will use a default widget +that is appropriate to the type of data that is to be displayed. To find +which widget is used on which field, see the documentation for the +built-in Field classes. + +However, if you want to use a different widget for a field, you can - +just use the 'widget' argument on the field definition. For example:: + + class CommentForm(forms.Form): + name = forms.CharField() + url = forms.URLField() + comment = forms.CharField(widget=forms.Textarea) + +This would specify a form with a comment that uses a larger Textarea widget, +rather than the default TextInput widget. + +Customizing widget instances +---------------------------- + +When Django renders a widget as HTML, it only renders the bare minimum +HTML - Django doesn't add a class definition, or any other widget-specific +attributes. This means that all 'TextInput' widgets will appear the same +on your web page. + +If you want to make one widget look different to another, you need to +specify additional attributes for each widget. When you specify a +widget, you can provide a list of attributes that will be added to the +rendered HTML for the widget. + +For example, take the following simple form:: + + class CommentForm(forms.Form): + name = forms.CharField() + url = forms.URLField() + comment = forms.CharField() + +This form will include three default TextInput widgets, with default rendering - +no CSS class, no extra attributes. This means that the input boxes provided for +each widget will be rendered exactly the same:: + + >>> f = CommentForm(auto_id=False) + >>> f.as_table() + <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> + <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> + + +On a real web page, you probably don't want every widget to look the same. You +might want a larger input element for the comment, and you might want the 'name' +widget to have some special CSS class. To do this, you use the ``attrs`` +argument when creating the widget: + +.. attribute:: Widget.attrs + +For example:: + + class CommentForm(forms.Form): + name = forms.CharField( + widget=forms.TextInput(attrs={'class':'special'})) + url = forms.URLField() + comment = forms.CharField( + widget=forms.TextInput(attrs={'size':'40'})) + +Django will then include the extra attributes in the rendered output:: + + >>> f = CommentForm(auto_id=False) + >>> f.as_table() + <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> + <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> + <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> diff --git a/docs/ref/generic-views.txt b/docs/ref/generic-views.txt new file mode 100644 index 0000000000..f92a301c2f --- /dev/null +++ b/docs/ref/generic-views.txt @@ -0,0 +1,1106 @@ +.. _ref-generic-views: + +============= +Generic views +============= + +Writing Web applications can be monotonous, because we repeat certain patterns +again and again. In Django, the most common of these patterns have been +abstracted into "generic views" that let you quickly provide common views of +an object without actually needing to write any Python code. + +Django's generic views contain the following: + + * A set of views for doing list/detail interfaces. + + * A set of views for year/month/day archive pages and associated + detail and "latest" pages (for example, the Django weblog's year_, + month_, day_, detail_, and latest_ pages). + + * A set of views for creating, editing, and deleting objects. + +.. _year: http://www.djangoproject.com/weblog/2005/ +.. _month: http://www.djangoproject.com/weblog/2005/jul/ +.. _day: http://www.djangoproject.com/weblog/2005/jul/20/ +.. _detail: http://www.djangoproject.com/weblog/2005/jul/20/autoreload/ +.. _latest: http://www.djangoproject.com/weblog/ + +All of these views are used by creating configuration dictionaries in +your URLconf files and passing those dictionaries as the third member of the +URLconf tuple for a given pattern. For example, here's the URLconf for the +simple weblog app that drives the blog on djangoproject.com:: + + from django.conf.urls.defaults import * + from django_website.apps.blog.models import Entry + + info_dict = { + 'queryset': Entry.objects.all(), + 'date_field': 'pub_date', + } + + urlpatterns = patterns('django.views.generic.date_based', + (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', info_dict), + (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict), + (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict), + (r'^(?P<year>\d{4})/$', 'archive_year', info_dict), + (r'^$', 'archive_index', info_dict), + ) + +As you can see, this URLconf defines a few options in ``info_dict``. +``'queryset'`` gives the generic view a ``QuerySet`` of objects to use (in this +case, all of the ``Entry`` objects) and tells the generic view which model is +being used. + +Documentation of each generic view follows, along with a list of all keyword +arguments that a generic view expects. Remember that as in the example above, +arguments may either come from the URL pattern (as ``month``, ``day``, +``year``, etc. do above) or from the additional-information dictionary (as for +``queryset``, ``date_field``, etc.). + +Most generic views require the ``queryset`` key, which is a ``QuerySet`` +instance; see :ref:`topics-db-queries` 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. + +"Simple" generic views +====================== + +The ``django.views.generic.simple`` module contains simple views to handle a +couple of common cases: rendering a template when no view logic is needed, +and issuing a redirect. + +``django.views.generic.simple.direct_to_template`` +-------------------------------------------------- + +**Description:** + +Renders a given template, passing it a ``{{ params }}`` template variable, +which is a dictionary of the parameters captured in the URL. + +**Required arguments:** + + * ``template``: The full name of a template to use. + +**Optional arguments:** + + * ``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. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Example:** + +Given the following URL patterns:: + + urlpatterns = patterns('django.views.generic.simple', + (r'^foo/$', 'direct_to_template', {'template': 'foo_index.html'}), + (r'^foo/(?P<id>\d+)/$', 'direct_to_template', {'template': 'foo_detail.html'}), + ) + +... a request to ``/foo/`` would render the template ``foo_index.html``, and a +request to ``/foo/15/`` would render the ``foo_detail.html`` with a context +variable ``{{ params.id }}`` that is set to ``15``. + +``django.views.generic.simple.redirect_to`` +------------------------------------------- + +**Description:** + +Redirects to a given URL. + +The given URL may contain dictionary-style string formatting, which will be +interpolated against the parameters captured in the URL. + +If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410). + +**Required arguments:** + + * ``url``: The URL to redirect to, as a string. Or ``None`` to raise a 410 + (Gone) HTTP error. + +**Example:** + +This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``:: + + urlpatterns = patterns('django.views.generic.simple', + ('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), + ) + +This example returns a 410 HTTP error for requests to ``/bar/``:: + + urlpatterns = patterns('django.views.generic.simple', + ('^bar/$', 'redirect_to', {'url': None}), + ) + +Date-based generic views +======================== + +Date-based generic views (in the module ``django.views.generic.date_based``) +are views for displaying drilldown pages for date-based data. + +``django.views.generic.date_based.archive_index`` +------------------------------------------------- + +**Description:** + +A top-level index page showing the "latest" objects, by date. Objects with +a date in the *future* are not included unless you set ``allow_future`` to +``True``. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``num_latest``: The number of latest objects to send to the template + context. By default, it's 15. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + + * **New in Django development version:** ``template_object_name``: + Designates the name of the template variable to use in the template + context. By default, this is ``'latest'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_archive.html`` by default, where: + + * ``<model_name>`` is your model's name in all lowercase. For a model + ``StaffMember``, that'd be ``staffmember``. + + * ``<app_label>`` is the right-most part of the full Python path to + your model's app. For example, if your model lives in + ``apps/blog/models.py``, that'd be ``blog``. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``date_list``: A list of ``datetime.date`` objects representing all + years that have objects available according to ``queryset``. These are + ordered in reverse. This is equivalent to + ``queryset.dates(date_field, 'year')[::-1]``. + + * ``latest``: The ``num_latest`` objects in the system, ordered descending + by ``date_field``. For example, if ``num_latest`` is ``10``, then + ``latest`` will be a list of the latest 10 objects in ``queryset``. + + **New in Django development version:** This variable's name depends on + the ``template_object_name`` parameter, which is ``'latest'`` by default. + If ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +``django.views.generic.date_based.archive_year`` +------------------------------------------------ + +**Description:** + +A yearly archive page showing all available months in a given year. Objects +with a date in the *future* are not displayed unless you set ``allow_future`` +to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``make_object_list``: A boolean specifying whether to retrieve the full + list of objects for this year and pass those to the template. If ``True``, + this list of objects will be made available to the template as + ``object_list``. (The name ``object_list`` may be different; see the docs + for ``object_list`` in the "Template context" section below.) By default, + this is ``False``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_archive_year.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``date_list``: A list of ``datetime.date`` objects representing all + months that have objects available in the given year, according to + ``queryset``, in ascending order. + + * ``year``: The given year, as a four-character string. + + * ``object_list``: If the ``make_object_list`` parameter is ``True``, this + will be set to a list of objects available for the given year, ordered by + the date field. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo_list``. + + If ``make_object_list`` is ``False``, ``object_list`` will be passed to + the template as an empty list. + +``django.views.generic.date_based.archive_month`` +------------------------------------------------- + +**Description:** + +A monthly archive page showing all objects in a given month. Objects with a +date in the *future* are not displayed unless you set ``allow_future`` to +``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``month``: The month for which the archive serves, formatted according to + the ``month_format`` argument. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_archive_month.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``month``: A ``datetime.date`` object representing the given month. + + * ``next_month``: A ``datetime.date`` object representing the first day of + the next month. If the next month is in the future, this will be + ``None``. + + * ``previous_month``: A ``datetime.date`` object representing the first day + of the previous month. Unlike ``next_month``, this will never be + ``None``. + + * ``object_list``: A list of objects available for the given month. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +.. _strftime docs: http://www.python.org/doc/current/lib/module-time.html#l2h-1941 + +``django.views.generic.date_based.archive_week`` +------------------------------------------------ + +**Description:** + +A weekly archive page showing all objects in a given week. Objects with a date +in the *future* are not displayed unless you set ``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``week``: The week of the year for which the archive serves (a string). + Weeks start with Sunday. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_archive_week.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``week``: A ``datetime.date`` object representing the first day of the + given week. + + * ``object_list``: A list of objects available for the given week. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +``django.views.generic.date_based.archive_day`` +----------------------------------------------- + +**Description:** + +A day archive page showing all objects in a given day. Days in the future throw +a 404 error, regardless of whether any objects exist for future days, unless +you set ``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``month``: The month for which the archive serves, formatted according to + the ``month_format`` argument. + + * ``day``: The day for which the archive serves, formatted according to the + ``day_format`` argument. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``day_format``: Like ``month_format``, but for the ``day`` parameter. + It defaults to ``"%d"`` (day of the month as a decimal number, 01-31). + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_archive_day.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``day``: A ``datetime.date`` object representing the given day. + + * ``next_day``: A ``datetime.date`` object representing the next day. If + the next day is in the future, this will be ``None``. + + * ``previous_day``: A ``datetime.date`` object representing the given day. + Unlike ``next_day``, this will never be ``None``. + + * ``object_list``: A list of objects available for the given day. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +``django.views.generic.date_based.archive_today`` +------------------------------------------------- + +**Description:** + +A day archive page showing all objects for *today*. This is exactly the same as +``archive_day``, except the ``year``/``month``/``day`` arguments are not used, +and today's date is used instead. + +``django.views.generic.date_based.object_detail`` +------------------------------------------------- + +**Description:** + +A page representing an individual object. If the object has a date value in the +future, the view will throw a 404 error by default, unless you set +``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The object's four-digit year (a string). + + * ``month``: The object's month , formatted according to the + ``month_format`` argument. + + * ``day``: The object's day , formatted according to the ``day_format`` + argument. + + * ``queryset``: A ``QuerySet`` that contains the object. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the generic view should use to look up the + object according to ``year``, ``month`` and ``day``. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``day_format``: Like ``month_format``, but for the ``day`` parameter. + It defaults to ``"%d"`` (day of the month as a decimal number, 01-31). + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_name_field``: The name of a field on the object whose value is + the template name to use. This lets you store template names in the data. + In other words, if your object has a field ``'the_template'`` that + contains a string ``'foo.html'``, and you set ``template_name_field`` to + ``'the_template'``, then the generic view for this object will use the + template ``'foo.html'``. + + It's a bit of a brain-bender, but it's useful in some cases. + + * ``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. 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. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_detail.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The object. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +List/detail generic views +========================= + +The list-detail generic-view framework (in the +``django.views.generic.list_detail`` module) is similar to the date-based one, +except the former simply has two views: a list of objects and an individual +object page. + +``django.views.generic.list_detail.object_list`` +------------------------------------------------ + +**Description:** + +A page representing a list of objects. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` that represents the objects. + +**Optional arguments:** + + * ``paginate_by``: An integer specifying how many objects should be + displayed per page. If this is given, the view will paginate objects with + ``paginate_by`` objects per page. The view will expect either a ``page`` + query string parameter (via ``GET``) or a ``page`` variable specified in + the URLconf. See `Notes on pagination`_ below. + + * ``page``: The current page number, as an integer, or the string + ``'last'``. This is 1-based. See `Notes on pagination`_ below. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_list.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object_list``: The list of objects. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo_list``. + + * ``is_paginated``: A boolean representing whether the results are + paginated. Specifically, this is set to ``False`` if the number of + available objects is less than or equal to ``paginate_by``. + +If the results are paginated, the context will contain these extra variables: + + * **New in Django development version:** ``paginator``: An instance of + ``django.core.paginator.Paginator``. + + * **New in Django development version:** ``page_obj``: An instance of + ``django.core.paginator.Page``. + +Notes on pagination +~~~~~~~~~~~~~~~~~~~ + +If ``paginate_by`` is specified, Django will paginate the results. You can +specify the page number in the URL in one of two ways: + + * Use the ``page`` parameter in the URLconf. For example, this is what + your URLconf might look like:: + + (r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict)) + + * Pass the page number via the ``page`` query-string parameter. For + example, a URL would look like this:: + + /objects/?page=3 + + * To loop over all the available page numbers, use the ``page_range`` + variable. You can iterate over the list provided by ``page_range`` + to create a link to every page of results. + +These values and lists are 1-based, not 0-based, so the first page would be +represented as page ``1``. + +For more on pagination, read the :ref:`pagination documentation +<topics-pagination>`. + +**New in Django development version:** + +As a special case, you are also permitted to use ``last`` as a value for +``page``:: + + /objects/?page=last + +This allows you to access the final page of results without first having to +determine how many pages there are. + +Note that ``page`` *must* be either a valid page number or the value ``last``; +any other value for ``page`` will result in a 404 error. + +``django.views.generic.list_detail.object_detail`` +-------------------------------------------------- + +A page representing an individual object. + +**Description:** + +A page representing an individual object. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` that contains the object. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_name_field``: The name of a field on the object whose value is + the template name to use. This lets you store template names in the data. + In other words, if your object has a field ``'the_template'`` that + contains a string ``'foo.html'``, and you set ``template_name_field`` to + ``'the_template'``, then the generic view for this object will use the + template ``'foo.html'``. + + It's a bit of a brain-bender, but it's useful in some cases. + + * ``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. 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. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_detail.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The object. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +Create/update/delete generic views +================================== + +The ``django.views.generic.create_update`` module contains a set of functions +for creating, editing and deleting objects. + +**Changed in Django development version:** + +``django.views.generic.create_update.create_object`` and +``django.views.generic.create_update.update_object`` now use the new :ref:`forms +library <topics-forms-index>` to build and display the form. + +``django.views.generic.create_update.create_object`` +---------------------------------------------------- + +**Description:** + +A page that displays a form for creating an object, redisplaying the form with +validation errors (if there are any) and saving the object. + +**Required arguments:** + + * Either ``form_class`` or ``model`` is required. + + If you provide ``form_class``, it should be a ``django.forms.ModelForm`` + subclass. Use this argument when you need to customize the model's form. + See the :ref:`ModelForm docs <topics-forms-modelforms>` for more + information. + + Otherwise, ``model`` should be a Django model class and the form used + will be a standard ``ModelForm`` for ``model``. + +**Optional arguments:** + + * ``post_save_redirect``: A URL to which the view will redirect after + saving the object. By default, it's ``object.get_absolute_url()``. + + ``post_save_redirect`` may contain dictionary string formatting, which + will be interpolated against the object's field attributes. For example, + you could use ``post_save_redirect="/polls/%(slug)s/"``. + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system <topics-auth>`. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_form.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``form``: A ``django.forms.ModelForm`` instance representing the form + for creating the object. This lets you refer to form fields easily in the + template system. + + For example, if the model has two fields, ``name`` and ``address``:: + + <form action="" method="post"> + <p>{{ form.name.label_tag }} {{ form.name }}</p> + <p>{{ form.address.label_tag }} {{ form.address }}</p> + </form> + + See the :ref:`forms documentation <topics-forms-index>` for more + information about using ``Form`` objects in templates. + +``django.views.generic.create_update.update_object`` +---------------------------------------------------- + +**Description:** + +A page that displays a form for editing an existing object, redisplaying the +form with validation errors (if there are any) and saving changes to the +object. This uses a form automatically generated from the object's +model class. + +**Required arguments:** + + * Either ``form_class`` or ``model`` is required. + + If you provide ``form_class``, it should be a ``django.forms.ModelForm`` + subclass. Use this argument when you need to customize the model's form. + See the :ref:`ModelForm docs <topics-forms-modelforms>` for more + information. + + Otherwise, ``model`` should be a Django model class and the form used + will be a standard ``ModelForm`` for ``model``. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``post_save_redirect``: A URL to which the view will redirect after + saving the object. By default, it's ``object.get_absolute_url()``. + + ``post_save_redirect`` may contain dictionary string formatting, which + will be interpolated against the object's field attributes. For example, + you could use ``post_save_redirect="/polls/%(slug)s/"``. + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system <topics-auth>`. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_form.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``form``: A ``django.forms.ModelForm`` instance representing the form + for editing the object. This lets you refer to form fields easily in the + template system. + + For example, if the model has two fields, ``name`` and ``address``:: + + <form action="" method="post"> + <p>{{ form.name.label_tag }} {{ form.name }}</p> + <p>{{ form.address.label_tag }} {{ form.address }}</p> + </form> + + See the :ref:`forms documentation <topics-forms-index>` for more + information about using ``Form`` objects in templates. + + * ``object``: The original object being edited. This variable's name + depends on the ``template_object_name`` parameter, which is ``'object'`` + by default. If ``template_object_name`` is ``'foo'``, this variable's + name will be ``foo``. + +``django.views.generic.create_update.delete_object`` +---------------------------------------------------- + +**Description:** + +A view that displays a confirmation page and deletes an existing object. The +given object will only be deleted if the request method is ``POST``. If this +view is fetched via ``GET``, it will display a confirmation page that should +contain a form that POSTs to the same URL. + +**Required arguments:** + + * ``model``: The Django model class of the object that the form will + create. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + + * ``post_delete_redirect``: A URL to which the view will redirect after + deleting the object. + +**Optional arguments:** + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system <topics-auth>`. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``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. 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. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``<app_label>/<model_name>_confirm_delete.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The original object that's about to be deleted. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo``. diff --git a/docs/ref/index.txt b/docs/ref/index.txt new file mode 100644 index 0000000000..ac71175abf --- /dev/null +++ b/docs/ref/index.txt @@ -0,0 +1,21 @@ +.. _ref-index: + +API Reference +============= + +.. toctree:: + :maxdepth: 1 + + contrib/index + databases + django-admin + forms/index + generic-views + middleware + models/index + request-response + settings + templates/index + unicode + files/index +
\ No newline at end of file diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt new file mode 100644 index 0000000000..48a3e81cc4 --- /dev/null +++ b/docs/ref/middleware.txt @@ -0,0 +1,200 @@ +.. _ref-middleware: + +============================= +Built-in middleware reference +============================= + +.. module:: django.middleware + :synopsis: Django's built-in middleware classes. + +This document explains all middleware components that come with Django. For +information on how how to use them and how to write your own middleware, see the +:ref:`middleware usage guide <topics-http-middleware>`. + +Available middleware +==================== + +Cache middleware +---------------- + +.. module:: django.middleware.cache + :synopsis: Middleware for the site-wide cache + +.. class:: django.middleware.cache.CacheMiddleware + +Enables the site-wide cache. If this is enabled, each Django-powered page will +be cached for as long as the :setting:`CACHE_MIDDLEWARE_SECONDS` setting +defines. See the :ref:`cache documentation <topics-cache>`. + +"Common" middleware +------------------- + +.. module:: django.middleware.common + :synopsis: Middleware adding "common" conveniences for perfectionists. + +.. class:: django.middleware.common.CommonMiddleware + +Adds a few conveniences for perfectionists: + + * Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS` + setting, which should be a list of strings. + + * Performs URL rewriting based on the :setting:`APPEND_SLASH` and + :setting:`PREPEND_WWW` settings. + + If :setting:`APPEND_SLASH` is ``True`` and the initial URL doesn't end + with a slash, and it is not found in the URLconf, then a new URL is formed + by appending a slash at the end. If this new URL is found in the URLconf, + then Django redirects the request to this new URL. Otherwise, the initial + URL is processed as usual. + + For example, ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if you + don't have a valid URL pattern for ``foo.com/bar`` but *do* have a valid + pattern for ``foo.com/bar/``. + + **New in Django development version:** The behavior of + :setting:`APPEND_SLASH` has changed slightly in the development version. + It didn't used to check whether the pattern was matched in the URLconf. + + If :setting:`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 + each URL should exist in one, and only one, place. Technically a URL + ``foo.com/bar`` is distinct from ``foo.com/bar/`` -- a search-engine + indexer would treat them as separate URLs -- so it's best practice to + normalize URLs. + + * Handles ETags based on the :setting:`USE_ETAGS` setting. If + :setting:`USE_ETAGS` is set to ``True``, Django will calculate an ETag for + each request by MD5-hashing the page content, and it'll take care of + sending ``Not Modified`` responses, if appropriate. + +View metadata middleware +------------------------ + +.. module:: django.middleware.doc + :synopsis: Middleware to help your app self-document. + +.. class:: django.middleware.doc.XViewMiddleware + +Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP +addresses defined in the :setting:`INTERNAL_IPS` setting. This is used by +Django's automatic documentation system. + +GZIP middleware +--------------- + +.. module:: django.middleware.gzip + :synopsis: Middleware to serve gziped content for performance. + +.. class:: django.middleware.gzip.GZipMiddleware + +Compresses content for browsers that understand gzip compression (all modern +browsers). + +It is suggested to place this first in the middleware list, so that the +compression of the response content is the last thing that happens. Will not +compress content bodies less than 200 bytes long, when the response code is +something other than 200, JavaScript files (for IE compatibility), or +responses that have the ``Content-Encoding`` header already specified. + +Conditional GET middleware +-------------------------- + +.. module:: django.middleware.http + :synopsis: Middleware handling advanced HTTP features. + +.. class:: django.middleware.http.ConditionalGetMiddleware + +Handles conditional GET operations. If the response has a ``ETag`` or +``Last-Modified`` header, and the request has ``If-None-Match`` or +``If-Modified-Since``, the response is replaced by an +:class:`~django.http.HttpNotModified`. + +Also sets the ``Date`` and ``Content-Length`` response-headers. + +Reverse proxy middleware +------------------------ + +.. class:: django.middleware.http.SetRemoteAddrFromForwardedFor + +Sets ``request.META['REMOTE_ADDR']`` based on +``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful +if you're sitting behind a reverse proxy that causes each request's +``REMOTE_ADDR`` to be set to ``127.0.0.1``. + +**Important note:** This does NOT validate ``HTTP_X_FORWARDED_FOR``. If you're +not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR`` automatically, do +not use this middleware. Anybody can spoof the value of +``HTTP_X_FORWARDED_FOR``, and because this sets ``REMOTE_ADDR`` based on +``HTTP_X_FORWARDED_FOR``, that means anybody can "fake" their IP address. Only +use this when you can absolutely trust the value of ``HTTP_X_FORWARDED_FOR``. + +Locale middleware +----------------- + +.. module:: django.middleware.locale + :synopsis: Middleware to enable language selection based on the request. + +.. class:: django.middleware.locale.LocaleMiddleware + +Enables language selection based on data from the request. It customizes content +for each user. See the :ref:`internationalization documentation <topics-i18n>`. + +Session middleware +------------------ + +.. module:: django.contrib.sessions.middleware + :synopsis: Session middleware. + +.. class:: django.contrib.sessions.middleware.SessionMiddleware + +Enables session support. See the :ref:`session documentation +<topics-http-sessions>`. + +Authentication middleware +------------------------- + +.. module:: django.contrib.auth.middleware + :synopsis: Authentication middleware + +.. class:: django.contrib.auth.middleware.AuthenticationMiddleware + +Adds the ``user`` attribute, representing the currently-logged-in user, to every +incoming ``HttpRequest`` object. See :ref:` Authentication in Web requests +<topics-http-auth>`. + +CSRF protection middleware +-------------------------- + +.. module:: django.contrib.csrf.middleware + :synopsis: Middleware adding protection against Cross Site Request Forgeries. + +.. class:: django.contrib.csrf.middleware.CsrfMiddleware + +**New in Django development version** + +Adds protection against Cross Site Request Forgeries by adding hidden form +fields to POST forms and checking requests for the correct value. See the +:ref:`Cross Site Request Forgery protection documentation <ref-contrib-csrf>`. + +Transaction middleware +---------------------- + +.. module:: django.middleware.transaction + :synopsis: Middleware binding a database transaction to each web request. + +.. class:: django.middleware.transaction.TransactionMiddleware + +Binds commit and rollback to the request/response phase. If a view function runs +successfully, a commit is done. If it fails with an exception, a rollback is +done. + +The order of this middleware in the stack is important: middleware modules +running outside of it run with commit-on-save - the default Django behavior. +Middleware modules running inside it (coming later in the stack) will be under +the same transaction control as the view functions. + +See the :ref:`transaction management documentation <topics-db-transactions>`. + diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt new file mode 100644 index 0000000000..f0638d1ea5 --- /dev/null +++ b/docs/ref/models/fields.txt @@ -0,0 +1,902 @@ +.. _ref-models-fields: + +===================== +Model field reference +===================== + +.. module:: django.db.models.fields + :synopsis: Built-in field types. + +This document contains all the gory details about all the `field options`_ and +`field types`_ Django's got to offer. + +.. seealso:: + + If the built-in fields don't do the trick, you can easily :ref:`write your + own custom model fields <howto-custom-model-fields>`. + +.. note:: + + Technically, these models are defined in :mod:`django.db.models.fields`, but + for convenience they're imported into :mod:`django.db.models`; the standard + convention is to use ``from django.db import models`` and refer to fields as + ``models.<Foo>Field``. + +.. _common-model-field-options: + +Field options +============= + +The following arguments are available to all field types. All are optional. + +``null`` +-------- + +.. attribute:: Field.null + +If ``True``, Django will store empty values as ``NULL`` in the database. Default +is ``False``. + +Note that empty string values will always get stored as empty strings, not as +``NULL``. Only use ``null=True`` for non-string fields such as integers, +booleans and dates. For both types of fields, you will also need to set +``blank=True`` if you wish to permit empty values in forms, as the +:attr:`~Field.null` parameter only affects database storage (see +:attr:`~Field.blank`). + +Avoid using :attr:`~Field.null` on string-based fields such as +:class:`CharField` and :class:`TextField` unless you have an excellent reason. +If a string-based field has ``null=True``, that means it has two possible values +for "no data": ``NULL``, and the empty string. In most cases, it's redundant to +have two possible values for "no data;" Django convention is to use the empty +string, not ``NULL``. + +.. note:: + + When using the Oracle database backend, the ``null=True`` option will be + coerced for string-based fields that can blank, and the value ``NULL`` will + be stored to denote the empty string. + +``blank`` +--------- + +.. attribute:: Field.blank + +If ``True``, the field is allowed to be blank. Default is ``False``. + +Note that this is different than :attr:`~Field.null`. :attr:`~Field.null` is +purely database-related, whereas :attr:`~Field.blank` is validation-related. If +a field has ``blank=True``, validation on Django's admin site will allow entry +of an empty value. If a field has ``blank=False``, the field will be required. + +``choices`` +----------- + +.. attribute:: Field.choices + +An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this +field. + +If this is given, Django's admin will use a select box instead of the standard +text field and will limit choices to the choices given. + +A choices list looks like this:: + + YEAR_IN_SCHOOL_CHOICES = ( + ('FR', 'Freshman'), + ('SO', 'Sophomore'), + ('JR', 'Junior'), + ('SR', 'Senior'), + ('GR', 'Graduate'), + ) + +The first element in each tuple is the actual value to be stored. The second +element is the human-readable name for the option. + +The choices list can be defined either as part of your model class:: + + class Foo(models.Model): + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) + +or outside your model class altogether:: + + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) + class Foo(models.Model): + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) + +You can also collect your available choices into named groups that can +be used for organizational purposes:: + + MEDIA_CHOICES = ( + ('Audio', ( + ('vinyl', 'Vinyl'), + ('cd', 'CD'), + ) + ), + ('Video', ( + ('vhs', 'VHS Tape'), + ('dvd', 'DVD'), + ) + ), + ('unknown', 'Unknown'), + ) + +The first element in each tuple is the name to apply to the group. The +second element is an iterable of 2-tuples, with each 2-tuple containing +a value and a human-readable name for an option. Grouped options may be +combined with ungrouped options within a single list (such as the +`unknown` option in this example). + +For each model field that has :attr:`~Field.choices` set, Django will add a +method to retrieve the human-readable name for the field's current value. See +:meth:`~django.db.models.Model.get_FOO_display` in the database API +documentation. + +Finally, note that choices can be any iterable object -- not necessarily a list +or tuple. This lets you construct choices dynamically. But if you find yourself +hacking :attr:`~Field.choices` to be dynamic, you're probably better off using a +proper database table with a :class:`ForeignKey`. :attr:`~Field.choices` is +meant for static data that doesn't change much, if ever. + +``core`` +-------- + +.. attribute:: Field.core + +For objects that are edited inline to a related object. + +In the Django admin, if all "core" fields in an inline-edited object are +cleared, the object will be deleted. + +It is an error to have an inline-editable relation without at least one +``core=True`` field. + +Please note that each field marked "core" is treated as a required field by the +Django admin site. Essentially, this means you should put ``core=True`` on all +required fields in your related object that is being edited inline. + +``db_column`` +------------- + +.. attribute:: Field.db_column + +The name of the database column to use for this field. If this isn't given, +Django will use the field's name. + +If your database column name is an SQL reserved word, or contains +characters that aren't allowed in Python variable names -- notably, the +hyphen -- that's OK. Django quotes column and table names behind the +scenes. + +``db_index`` +------------ + +.. attribute:: Field.db_index + +If ``True``, djadmin:`django-admin.py sqlindexes <sqlindexes>` will output a +``CREATE INDEX`` statement for this field. + +``db_tablespace`` +----------------- + +.. attribute:: Field.db_tablespace + +**New in Django development version** + +The name of the database tablespace to use for this field's index, if this field +is indexed. The default is the project's :setting:`DEFAULT_INDEX_TABLESPACE` +setting, if set, or the :attr:`~Field.db_tablespace` of the model, if any. If +the backend doesn't support tablespaces, this option is ignored. + +``default`` +----------- + +.. attribute:: Field.default + +The default value for the field. This can be a value or a callable object. If +callable it will be called every time a new object is created. + +``editable`` +------------ + +.. attribute:: Field.editable + +If ``False``, the field will not be editable in the admin or via forms +automatically generated from the model class. Default is ``True``. + +``help_text`` +------------- + +.. attribute:: Field.help_text + +Extra "help" text to be displayed under the field on the object's admin form. +It's useful for documentation even if your object doesn't have an admin form. + +Note that this value is *not* HTML-escaped when it's displayed in the admin +interface. This lets you include HTML in :attr:`~Field.help_text` if you so +desire. For example:: + + help_text="Please use the following format: <em>YYYY-MM-DD</em>." + +Alternatively you can use plain text and +``django.utils.html.escape()`` to escape any HTML special characters. + +``primary_key`` +--------------- + +.. attribute:: Field.primary_key + +If ``True``, this field is the primary key for the model. + +If you don't specify ``primary_key=True`` for any fields in your model, Django +will automatically add an :class:`IntegerField` to hold the primary key, so you +don't need to set ``primary_key=True`` on any of your fields unless you want to +override the default primary-key behavior. For more, see +:ref:`automatic-primary-key-fields`. + +``primary_key=True`` implies :attr:`null=False <Field.null>` and :attr:`unique=True <Field.unique>`. +Only one primary key is allowed on an object. + +``unique`` +---------- + +.. attribute:: Field.unique + +If ``True``, this field must be unique throughout the table. + +This is enforced at the database level and at the Django admin-form level. If +you try to save a model with a duplicate value in a :attr:`~Field.unique` +field, a :exc:`django.db.IntegrityError` will be raised by the model's +:meth:`~django.db.models.Model.save` method. + +This options is valid on all field types except :class:`ManyToManyField`. + +``unique_for_date`` +------------------- + +.. attribute:: Field.unique_for_date + +Set this to the name of a :class:`DateField` or :class:`DateTimeField` to +require that this field be unique for the value of the date field. + +For example, if you have a field ``title`` that has +``unique_for_date="pub_date"``, then Django wouldn't allow the entry of two +records with the same ``title`` and ``pub_date``. + +This is enforced at the Django admin-form level but not at the database level. + +``unique_for_month`` +-------------------- + +.. attribute:: Field.unique_for_month + +Like :attr:`~Field.unique_for_date`, but requires the field to be unique with +respect to the month. + +``unique_for_year`` +------------------- + +.. attribute:: Field.unique_for_year + +Like :attr:`~Field.unique_for_date` and :attr:`~Field.unique_for_month`. + +``validator_list`` +------------------ + +.. attribute:: Field.validator_list + +A list of extra validators to apply to the field. Each should be a callable that +takes the parameters ``field_data, all_data`` and raises +:exc:`django.core.validators.ValidationError` for errors. + +.. _model-field-types: + +Field types +=========== + +.. currentmodule:: django.db.models + +``AutoField`` +------------- + +.. class:: AutoField(**options) + +An :class:`IntegerField` that automatically increments +according to available IDs. You usually won't need to use this directly; a +primary key field will automatically be added to your model if you don't specify +otherwise. See :ref:`automatic-primary-key-fields`. + +``BooleanField`` +---------------- + +.. class:: BooleanField(**options) + +A true/false field. + +The admin represents this as a checkbox. + +``CharField`` +------------- + +.. class:: CharField(max_length=None, [**options]) + +A string field, for small- to large-sized strings. + +For large amounts of text, use :class:`~django.db.models.TextField`. + +The admin represents this as an ``<input type="text">`` (a single-line input). + +:class:`CharField` has one extra required argument: + +.. attribute:: CharField.max_length + + The maximum length (in characters) of the field. The max_length is enforced + at the database level and in Django's validation. + +``CommaSeparatedIntegerField`` +------------------------------ + +.. class:: CommaSeparatedIntegerField(max_length=None, [**options]) + +A field of integers separated by commas. As in :class:`CharField`, the +:attr:`~CharField.max_length` argument is required. + +``DateField`` +------------- + +.. class:: DateField([auto_now=False, auto_now_add=False, **options]) + +A date field. Has a few extra optional arguments: + +.. attribute:: DateField.auto_now + + Automatically set the field to now every time the object is saved. Useful + for "last-modified" timestamps. Note that the current date is *always* used; + it's not just a default value that you can override. + +.. attribute:: DateField.auto_now_add + + Automatically set the field to now when the object is first created. Useful + for creation of timestamps. Note that the current date is *always* used; + it's not just a default value that you can override. + +The admin represents this as an ``<input type="text">`` with a JavaScript +calendar, and a shortcut for "Today". The JavaScript calendar will always start +the week on a Sunday. + +``DateTimeField`` +----------------- + +.. class:: DateTimeField([auto_now=False, auto_now_add=False, **options]) + +A date and time field. Takes the same extra options as :class:`DateField`. + +The admin represents this as two ``<input type="text">`` fields, with JavaScript +shortcuts. + +``DecimalField`` +---------------- + +**New in Django development version** + +.. class:: DecimalField(max_digits=None, decimal_places=None, [**options]) + +A fixed-precision decimal number, represented in Python by a +:class:`~decimal.Decimal` instance. Has two **required** arguments: + +.. attribute:: DecimalField.max_digits + + The maximum number of digits allowed in the number + +.. attribute:: DecimalField.decimal_places + + The number of decimal places to store with the number + +For example, to store numbers up to 999 with a resolution of 2 decimal places, +you'd use:: + + models.DecimalField(..., max_digits=5, decimal_places=2) + +And to store numbers up to approximately one billion with a resolution of 10 +decimal places:: + + models.DecimalField(..., max_digits=19, decimal_places=10) + +The admin represents this as an ``<input type="text">`` (a single-line input). + +``EmailField`` +-------------- + +.. class:: EmailField([max_length=75, **options]) + +A :class:`CharField` that checks that the value is a valid e-mail address. + +In Django 0.96, this doesn't accept :attr:`~CharField.max_length`; its +:class:`~CharField.max_length` is automatically set to 75. In the Django +development version, :class:`~CharField.max_length` is set to 75 by default, but +you can specify it to override default behavior. + +``FileField`` +------------- + +.. class:: FileField(upload_to=None, [max_length=100, **options]) + +A file-upload field. Has one **required** argument: + +.. attribute:: FileField.upload_to + + A local filesystem path that will be appended to your :setting:`MEDIA_ROOT` + setting to determine the output of the ``get_<fieldname>_url()`` helper + function. + + This path may contain `strftime formatting`_, which will be replaced by the + date/time of the file upload (so that uploaded files don't fill up the given + directory). + + **New in Django development version** + + This may also be a callable, such as a function, which will be called to + obtain the upload path, including the filename. This callable must be + able to accept two arguments, and return a Unix-style path (with forward + slashes) to be passed along to the storage system. The two arguments that will + be passed are: + + ====================== =============================================== + Argument Description + ====================== =============================================== + ``instance`` An instance of the model where the + ``FileField`` is defined. More specifically, + this is the particular instance where the + current file is being attached. + + In most cases, this object will not have been + saved to the database yet, so if it uses the + default ``AutoField``, *it might not yet have a + value for its primary key field*. + + ``filename`` The filename that was originally given to the + file. This may or may not be taken into account + when determining the final destination path. + ====================== =============================================== + +Also has one optional argument: + +.. attribute:: FileField.storage + + **New in Django development version.** + + Optional. A storage object, which handles the storage and retrieval of your + files. See :ref:`topics-files` for details on how to provide this object. + +The admin represents this field as an ``<input type="file">`` (a file-upload +widget). + +Using a :class:`FileField` or an :class:`ImageField` (see below) in a model +takes a few steps: + + 1. In your settings file, you'll need to define :setting:`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 + :setting:`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 :class:`FileField` or :class:`ImageField` to your model, making + sure to define the :attr:`~FileField.upload_to` option to tell Django to + which subdirectory of :setting:`MEDIA_ROOT` it should upload files. + + 3. All that will be stored in your database is a path to the file + (relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the + convenience ``get_<fieldname>_url`` function provided by Django. For + example, if your :class:`ImageField` is called ``mug_shot``, you can get + the absolute URL to your image in a template with ``{{ + object.get_mug_shot_url }}``. + +For example, say your :setting:`MEDIA_ROOT` is set to ``'/home/media'``, and +:attr:`~FileField.upload_to` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` +part of :attr:`~FileField.upload_to` is `strftime formatting`_; ``'%Y'`` is the +four-digit year, ``'%m'`` is the two-digit month and ``'%d'`` is the two-digit +day. If you upload a file on Jan. 15, 2007, it will be saved in the directory +``/home/media/photos/2007/01/15``. + +If you want to retrieve the upload file's on-disk filename, or a URL that refers +to that file, or the file's size, you can use the ``File.name``, ``File.url`` +and ``File.size`` attributes; see :ref:`topics-files`. + +Note that whenever you deal with uploaded files, you should pay close attention +to where you're uploading them and what type of files they are, to avoid +security holes. *Validate all uploaded files* so that you're sure the files are +what you think they are. For example, if you blindly let somebody upload files, +without validation, to a directory that's within your Web server's document +root, then somebody could upload a CGI or PHP script and execute that script by +visiting its URL on your site. Don't allow that. + +**New in development version:** By default, :class:`FileField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 + +``FilePathField`` +----------------- + +.. class:: FilePathField(path=None, [match=None, recursive=False, max_length=100, **options]) + +A :class:`CharField` whose choices are limited to the filenames in a certain +directory on the filesystem. Has three special arguments, of which the first is +**required**: + +.. attribute:: FilePathField.path + + Required. The absolute filesystem path to a directory from which this + :class:`FilePathField` should get its choices. Example: ``"/home/images"``. + +.. attribute:: FilePathField.match + + Optional. A regular expression, as a string, that :class:`FilePathField` + will use to filter filenames. Note that the regex will be applied to the + base filename, not the full path. Example: ``"foo.*\.txt$"``, which will + match a file called ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``. + +.. attribute:: FilePathField.recursive + + Optional. Either ``True`` or ``False``. Default is ``False``. Specifies + whether all subdirectories of :attr:`~FilePathField.path` should be included + +Of course, these arguments can be used together. + +The one potential gotcha is that :attr:`~FilePathField.match` applies to the +base filename, not the full path. So, this example:: + + FilePathField(path="/home/images", match="foo.*", recursive=True) + +...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif`` +because the :attr:`~FilePathField.match` applies to the base filename +(``foo.gif`` and ``bar.gif``). + +**New in development version:** By default, :class:`FilePathField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +``FloatField`` +-------------- + +.. class:: FloatField([**options]) + +**Changed in Django development version** + +A floating-point number represented in Python by a ``float`` instance. + +The admin represents this as an ``<input type="text">`` (a single-line input). + +**NOTE:** The semantics of :class:`FloatField` have changed in the Django +development version. See the `Django 0.96 documentation`_ for the old behavior. + +.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield + +``ImageField`` +-------------- + +.. class:: ImageField(upload_to-None, [height_field=None, width_field=None, max_length=100, **options]) + +Like :class:`FileField`, but validates that the uploaded object is a valid +image. Has two extra optional arguments: + +.. attribute:: ImageField.height_field + + Name of a model field which will be auto-populated with the height of the + image each time the model instance is saved. + +.. attribute:: ImageField.width_field` + + Name of a model field which will be auto-populated with the width of the + image each time the model instance is saved. + +In addition to the special attributes that are available for :class:`FileField`, +an :class:`ImageField` also has ``File.height`` and ``File.width`` attributes. +See :ref:`topics-files`. + +Requires the `Python Imaging Library`_. + +.. _Python Imaging Library: http://www.pythonware.com/products/pil/ + +**New in development version:** By default, :class:`ImageField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +``IntegerField`` +---------------- + +.. class:: IntegerField([**options]) + +An integer. The admin represents this as an ``<input type="text">`` (a +single-line input). + +``IPAddressField`` +------------------ + +.. class:: IPAddressField([**options]) + +An IP address, in string format (e.g. "192.0.2.30"). The admin represents this +as an ``<input type="text">`` (a single-line input). + +``NullBooleanField`` +-------------------- + +.. class:: NullBooleanField([**options]) + +Like a :class:`BooleanField`, but allows ``NULL`` as one of the options. Use +this instead of a :class:`BooleanField` with ``null=True``. The admin represents +this as a ``<select>`` box with "Unknown", "Yes" and "No" choices. + +``PhoneNumberField`` +-------------------- + +.. class:: PhoneNumberField([**options]) + +A :class:`CharField` that checks that the value is a valid U.S.A.-style phone +number (in the format ``XXX-XXX-XXXX``). + +``PositiveIntegerField`` +------------------------ + +.. class:: PositiveIntegerField([**options]) + +Like an :class:`IntegerField`, but must be positive. + +``PositiveSmallIntegerField`` +----------------------------- + +.. class:: PositiveIntegerField([**options]) + +Like a :class:`PositiveIntegerField`, but only allows values under a certain +(database-dependent) point. + +``SlugField`` +------------- + +.. class:: SlugField([max_length=50, **options]) + +:term:`Slug` is a newspaper term. A slug is a short label for something, +containing only letters, numbers, underscores or hyphens. They're generally used +in URLs. + +Like a CharField, you can specify :attr:`~CharField.max_length`. If +:attr:`~CharField.max_length` is not specified, Django will use a default length +of 50. + +Implies setting :attr:`Field.db_index` to ``True``. + +``SmallIntegerField`` +--------------------- + +.. class:: SmallIntegerField([**options]) + +Like an :class:`IntegerField`, but only allows values under a certain +(database-dependent) point. + +``TextField`` +------------- + +.. class:: TextField([**options]) + +A large text field. The admin represents this as a ``<textarea>`` (a multi-line +input). + +``TimeField`` +------------- + +.. class:: TimeField([auto_now=False, auto_now_add=False, **options]) + +A time. Accepts the same auto-population options as :class:`DateField` and +:class:`DateTimeField`. The admin represents this as an ``<input type="text">`` +with some JavaScript shortcuts. + +``URLField`` +------------ + +.. class:: URLField([verify_exists=True, max_length=200, **options]) + +A :class:`CharField` for a URL. Has one extra optional argument: + +.. attribute:: URLField.verify_exists + + If ``True`` (the default), the URL given will be checked for existence + (i.e., the URL actually loads and doesn't give a 404 response). + +The admin represents this as an ``<input type="text">`` (a single-line input). + +Like all ::class:`CharField` subclasses, :class:`URLField` takes the optional +:attr:`~CharField.max_length`argument. If you don't specify +:attr:`~CharField.max_length`, a default of 200 is used. + +``USStateField`` +---------------- + +.. class:: USStateField([**options]) + +A two-letter U.S. state abbreviation. The admin represents this as an ``<input +type="text">`` (a single-line input). + +``XMLField`` +------------ + +.. class:: XMLField(schema_path=None, [**options]) + +A :class:`TextField` that checks that the value is valid XML that matches a +given schema. Takes one required argument: + +.. attribute:: schema_path + + The filesystem path to a RelaxNG_ schema against which to validate the + field. + +.. _RelaxNG: http://www.relaxng.org/ + +Relationship fields +=================== + +.. module:: django.db.models.fields.related + :synopsis: Related field types + +.. currentmodule:: django.db.models + +Django also defines a set of fields that represent relations. + +.. _ref-foreignkey: + +``ForeignKey`` +-------------- + +.. class:: ForeignKey(othermodel, [**options]) + +A many-to-one relationship. Requires a positional argument: the class to which +the model is related. + +.. _recursive-relationships: + +To create a recursive relationship -- an object that has a many-to-one +relationship with itself -- use ``models.ForeignKey('self')``. + +.. _lazy-relationships: + +If you need to create a relationship on a model that has not yet been defined, +you can use the name of the model, rather than the model object itself:: + + class Car(models.Model): + manufacturer = models.ForeignKey('Manufacturer') + # ... + + class Manufacturer(models.Model): + # ... + +Note, however, that this only refers to models in the same ``models.py`` file -- +you cannot use a string to reference a model defined in another application or +imported from elsewhere. + +**New in Django development version:** To refer to models defined in another +application, you must instead explicitly specify the application label. For +example, if the ``Manufacturer`` model above is defined in another application +called ``production``, you'd need to use:: + + class Car(models.Model): + manufacturer = models.ForeignKey('production.Manufacturer') + +Behind the scenes, Django appends ``"_id"`` to the field name to create its +database column name. In the above example, the database table for the ``Car`` +model will have a ``manufacturer_id`` column. (You can change this explicitly by +specifying :attr:`~Field.db_column`) However, your code should never have to +deal with the database column name, unless you write custom SQL. You'll always +deal with the field names of your model object. + +.. _foreign-key-arguments: + +:class:`ForeignKey` accepts an extra set of arguments -- all optional -- that +define the details of how the relation works. + +.. attribute:: ForeignKey.limit_choices_to + + A dictionary of lookup arguments and values (see :ref:`topics-db-queries`) + that limit the available admin choices for this object. Use this with + functions from the Python ``datetime`` module to limit choices of objects by + date. For example:: + + limit_choices_to = {'pub_date__lte': datetime.now} + + only allows the choice of related objects with a ``pub_date`` before the + current date/time to be chosen. + + Instead of a dictionary this can also be a :class:`~django.db.models.Q` + object (an object with a :meth:`get_sql` method) for more complex queries. + + ``limit_choices_to`` has no effect on the inline FormSets that are created + to display related objects in the admin. + +.. attribute:: ForeignKey.related_name + + The name to use for the relation from the related object back to this one. + See the :ref:`related objects documentation <backwards-related-objects>` for + a full explanation and example. + +.. attribute:: ForeignKey.to_field + + The field on the related object that the relation is to. By default, Django + uses the primary key of the related object. + +.. _ref-manytomany: + +``ManyToManyField`` +------------------- + +.. class:: ManyToManyField(othermodel, [**options]) + +A many-to-many relationship. Requires a positional argument: the class to which +the model is related. This works exactly the same as it does for +:class:`ForeignKey`, including all the options regarding :ref:`recursive +<recursive-relationships>` and :ref:`lazy <lazy-relationships>` relationships. + +Behind the scenes, Django creates an intermediary join table to represent the +many-to-many relationship. By default, this table name is generated using the +names of the two tables being joined. Since some databases don't support table +names above a certain length (often 32 characters), these table names will be +automatically truncated to 32 characters and a uniqueness hash will be used. +This means you might see table names like ``author_books_9cdf4``; this is +perfectly normal. You can manually provide the name of the join table using +the :attr:`~ManyToManyField.db_table` option. + +.. _manytomany-arguments: + +:class:`ManyToManyField` accepts an extra set of arguments -- all optional -- +that control how the relationship functions. + +.. attribute:: ManyToManyField.related_name + + Same as :attr:`ForeignKey.related_name`. + +.. attribute:: ManyToManyFields.limit_choices_to + + Same as :attr:`ForeignKey.limit_choices_to`. + + ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with + an intermediate table. + +.. attribute:: ManyToManyFields.symmetrical + + Only used in the definition of ManyToManyFields on self. Consider the + following model:: + + class Person(models.Model): + friends = models.ManyToManyField("self") + + When Django processes this model, it identifies that it has a + :class:`ManyToManyField` on itself, and as a result, it doesn't add a + ``person_set`` attribute to the ``Person`` class. Instead, the + :class:`ManyToManyField` is assumed to be symmetrical -- that is, if I am + your friend, then you are my friend. + + If you do not want symmetry in many-to-many relationships with ``self``, set + :attr:`~ManyToManyField.symmetrical` to ``False``. This will force Django to + add the descriptor for the reverse relationship, allowing + :class:`ManyToManyField` relationships to be non-symmetrical. + +.. attribute:: ManyToManyField.db_table + + The name of the table to create for storing the many-to-many data. If this + is not provided, Django will assume a default name based upon the names of + the two tables being joined. + +``OneToOneField`` +----------------- + +.. class:: OneToOneField(othermodel, [**options]) + +The semantics of one-to-one relationships will be changing soon, so we don't +recommend you use them. If that doesn't scare you away, however, +:class:`OneToOneField` takes the same options that :class:`ForeignKey` does, +except for the various :attr:`~ForeignKey.edit_inline`-related options. diff --git a/docs/ref/models/index.txt b/docs/ref/models/index.txt new file mode 100644 index 0000000000..0e0510d707 --- /dev/null +++ b/docs/ref/models/index.txt @@ -0,0 +1,15 @@ +.. _ref-models-index: + +Models +====== + +Model API reference. For introductory material, see :ref:`topics-db-models`. + +.. toctree:: + :maxdepth: 1 + + fields + relations + options + instances + querysets diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt new file mode 100644 index 0000000000..404d473629 --- /dev/null +++ b/docs/ref/models/instances.txt @@ -0,0 +1,430 @@ +.. _ref-models-instances: + +======================== +Model instance reference +======================== + +.. currentmodule:: django.db.models + +This document describes the details of the ``Model`` API. It builds on the +material presented in the :ref:`model <topics-db-models>` and `database query +<topics-db-queries>` guides, so you'll probably want to read and understand +those documents before reading this one. + +Throughout this reference we'll use the :ref:`example weblog models +<queryset-model-example>` presented in the :ref:`database query guide +<topics-db-queries>`. + +Creating objects +================ + +To create a new instance of a model, just instantiate it like any other Python class: + +.. class:: Model(**kwargs) + +The keyword arguments to are simply the names of the fields you've defined on +your model. Note that instantiating a model in no way touches your database; for +that, you need to ``save()``. + +Saving objects +============== + +To save an object back to the database, call ``save()``: + +.. method:: Model.save([raw=False]) + +Of course, there's some subtleties; see the sections below. + +Auto-incrementing primary keys +------------------------------ + +If a model has an ``AutoField`` -- an auto-incrementing primary key -- then +that auto-incremented value will be calculated and saved as an attribute on +your object the first time you call ``save()``:: + + >>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.') + >>> b2.id # Returns None, because b doesn't have an ID yet. + >>> b2.save() + >>> b2.id # Returns the ID of your new object. + +There's no way to tell what the value of an ID will be before you call +``save()``, because that value is calculated by your database, not by Django. + +(For convenience, each model has an ``AutoField`` named ``id`` by default +unless you explicitly specify ``primary_key=True`` on a field. See the +documentation for ``AutoField`` for more details. + +The ``pk`` property +~~~~~~~~~~~~~~~~~~~ + +**New in Django development version** + +.. attribute:: Model.pk + +Regardless of whether you define a primary key field yourself, or let Django +supply one for you, each model will have a property called ``pk``. It behaves +like a normal attribute on the model, but is actually an alias for whichever +attribute is the primary key field for the model. You can read and set this +value, just as you would for any other attribute, and it will update the +correct field in the model. + +Explicitly specifying auto-primary-key values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a model has an ``AutoField`` but you want to define a new object's ID +explicitly when saving, just define it explicitly before saving, rather than +relying on the auto-assignment of the ID:: + + >>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.') + >>> b3.id # Returns 3. + >>> b3.save() + >>> b3.id # Returns 3. + +If you assign auto-primary-key values manually, make sure not to use an +already-existing primary-key value! If you create a new object with an explicit +primary-key value that already exists in the database, Django will assume you're +changing the existing record rather than creating a new one. + +Given the above ``'Cheddar Talk'`` blog example, this example would override the +previous record in the database:: + + b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') + b4.save() # Overrides the previous blog with ID=3! + +See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this +happens. + +Explicitly specifying auto-primary-key values is mostly useful for bulk-saving +objects, when you're confident you won't have primary-key collision. + +What happens when you save? +--------------------------- + +When you save an object, Django performs the following steps: + + 1. **Emit a ``pre_save`` signal.** This provides a notification that + an object is about to be saved. You can register a listener that + will be invoked whenever this signal is emitted. (These signals are + not yet documented.) + + 2. **Pre-process the data.** Each field on the object is asked to + perform any automated data modification that the field may need + to perform. + + Most fields do *no* pre-processing -- the field data is kept as-is. + Pre-processing is only used on fields that have special behavior. + For example, if your model has a ``DateField`` with ``auto_now=True``, + the pre-save phase will alter the data in the object to ensure that + the date field contains the current date stamp. (Our documentation + doesn't yet include a list of all the fields with this "special + behavior.") + + 3. **Prepare the data for the database.** Each field is asked to provide + its current value in a data type that can be written to the database. + + Most fields require *no* data preparation. Simple data types, such as + integers and strings, are 'ready to write' as a Python object. However, + more complex data types often require some modification. + + For example, ``DateFields`` use a Python ``datetime`` object to store + data. Databases don't store ``datetime`` objects, so the field value + must be converted into an ISO-compliant date string for insertion + into the database. + + 4. **Insert the data into the database.** The pre-processed, prepared + data is then composed into an SQL statement for insertion into the + database. + + 5. **Emit a ``post_save`` signal.** As with the ``pre_save`` signal, this + is used to provide notification that an object has been successfully + saved. (These signals are not yet documented.) + +Raw saves +~~~~~~~~~ + +**New in Django development version** + +The pre-processing step (#2 in the previous section) is useful, but it modifies +the data stored in a field. This can cause problems if you're relying upon the +data you provide being used as-is. + +For example, if you're setting up conditions for a test, you'll want the test +conditions to be repeatable. If pre-processing is performed, the data used +to specify test conditions may be modified, changing the conditions for the +test each time the test is run. + +In cases such as this, you need to prevent pre-processing from being performed +when you save an object. To do this, you can invoke a **raw save** by passing +``raw=True`` as an argument to the ``save()`` method:: + + b4.save(raw=True) # Save object, but do no pre-processing + +A raw save skips the usual data pre-processing that is performed during the +save. All other steps in the save (pre-save signal, data preparation, data +insertion, and post-save signal) are performed as normal. + +.. admonition:: When to use a raw save + + Generally speaking, you shouldn't need to use a raw save. Disabling field + pre-processing is an extraordinary measure that should only be required + in extraordinary circumstances, such as setting up reliable test + conditions. + + +How Django knows to UPDATE vs. INSERT +------------------------------------- + +You may have noticed Django database objects use the same ``save()`` method +for creating and changing objects. Django abstracts the need to use ``INSERT`` +or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django +follows this algorithm: + + * If the object's primary key attribute is set to a value that evaluates to + ``True`` (i.e., a value other than ``None`` or the empty string), Django + executes a ``SELECT`` query to determine whether a record with the given + primary key already exists. + * If the record with the given primary key does already exist, Django + executes an ``UPDATE`` query. + * If the object's primary key attribute is *not* set, or if it's set but a + record doesn't exist, Django executes an ``INSERT``. + +The one gotcha here is that you should be careful not to specify a primary-key +value explicitly when saving new objects, if you cannot guarantee the +primary-key value is unused. For more on this nuance, see `Explicitly specifying +auto-primary-key values`_ above and `Forcing an INSERT or UPDATE`_ below. + +Forcing an INSERT or UPDATE +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**New in Django development version** + +In some rare circumstances, it's necessary to be able to force the ``save()`` +method to perform an SQL ``INSERT`` and not fall back to doing an ``UPDATE``. +Or vice-versa: update, if possible, but not insert a new row. In these cases +you can pass the ``force_insert=True`` or ``force_update=True`` parameters to +the ``save()`` method. Passing both parameters is an error, since you cannot +both insert *and* update at the same time. + +It should be very rare that you'll need to use these parameters. Django will +almost always do the right thing and trying to override that will lead to +errors that are difficult to track down. This feature is for advanced use +only. + +.. _model-instance-methods: + +Other model instance methods +============================ + +A few object methods have special purposes. + +``__str__`` +----------- + +.. method:: Model.__str__() + +``__str__()`` is a Python "magic method" that defines what should be returned +if you call ``str()`` on the object. Django uses ``str(obj)`` (or the related +function, ``unicode(obj)`` -- see below) in a number of places, most notably +as the value displayed to render an object in the Django admin site and as the +value inserted into a template when it displays an object. Thus, you should +always return a nice, human-readable string for the object's ``__str__``. +Although this isn't required, it's strongly encouraged (see the description of +``__unicode__``, below, before putting ``__str__`` methods everywhere). + +For example:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + + def __str__(self): + # Note use of django.utils.encoding.smart_str() here because + # first_name and last_name will be unicode strings. + return smart_str('%s %s' % (self.first_name, self.last_name)) + +``__unicode__`` +--------------- + +.. method:: Model.__unicode__() + +The ``__unicode__()`` method is called whenever you call ``unicode()`` on an +object. Since Django's database backends will return Unicode strings in your +model's attributes, you would normally want to write a ``__unicode__()`` +method for your model. The example in the previous section could be written +more simply as:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + + def __unicode__(self): + return u'%s %s' % (self.first_name, self.last_name) + +If you define a ``__unicode__()`` method on your model and not a ``__str__()`` +method, Django will automatically provide you with a ``__str__()`` that calls +``__unicode__()`` and then converts the result correctly to a UTF-8 encoded +string object. This is recommended development practice: define only +``__unicode__()`` and let Django take care of the conversion to string objects +when required. + +``get_absolute_url`` +-------------------- + +.. method:: Model.get_absolute_url() + +Define a ``get_absolute_url()`` method to tell Django how to calculate the +URL for an object. For example:: + + def get_absolute_url(self): + return "/people/%i/" % self.id + +Django uses this in its admin interface. If an object defines +``get_absolute_url()``, the object-editing page will have a "View on site" +link that will jump you directly to the object's public view, according to +``get_absolute_url()``. + +Also, a couple of other bits of Django, such as the :ref:`syndication feed +framework <ref-contrib-syndication>`, use ``get_absolute_url()`` as a +convenience to reward people who've defined the method. + +It's good practice to use ``get_absolute_url()`` in templates, instead of +hard-coding your objects' URLs. For example, this template code is bad:: + + <a href="/people/{{ object.id }}/">{{ object.name }}</a> + +But this template code is good:: + + <a href="{{ object.get_absolute_url }}">{{ object.name }}</a> + +.. note:: + The string you return from ``get_absolute_url()`` must contain only ASCII + characters (required by the URI spec, `RFC 2396`_) that have been + URL-encoded, if necessary. Code and templates using ``get_absolute_url()`` + should be able to use the result directly without needing to do any + further processing. You may wish to use the + ``django.utils.encoding.iri_to_uri()`` function to help with this if you + are using unicode strings a lot. + +.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt + +The ``permalink`` decorator +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The problem with the way we wrote ``get_absolute_url()`` above is that it +slightly violates the DRY principle: the URL for this object is defined both +in the URLConf file and in the model. + +You can further decouple your models from the URLconf using the ``permalink`` +decorator: + +.. function:: django.db.models.permalink() + +This decorator is passed the view function, a list of positional parameters and +(optionally) a dictionary of named parameters. Django then works out the correct +full URL path using the URLconf, substituting the parameters you have given into +the URL. For example, if your URLconf contained a line such as:: + + (r'^people/(\d+)/$', 'people.views.details'), + +...your model could have a ``get_absolute_url`` method that looked like this:: + + from django.db import models + + @models.permalink + def get_absolute_url(self): + return ('people.views.details', [str(self.id)]) + +Similarly, if you had a URLconf entry that looked like:: + + (r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view) + +...you could reference this using ``permalink()`` as follows:: + + @models.permalink + def get_absolute_url(self): + return ('archive_view', (), { + 'year': self.created.year, + 'month': self.created.month, + 'day': self.created.day}) + +Notice that we specify an empty sequence for the second parameter in this case, +because we only want to pass keyword parameters, not positional ones. + +In this way, you're tying the model's absolute URL to the view that is used +to display it, without repeating the URL information anywhere. You can still +use the ``get_absolute_url`` method in templates, as before. + +In some cases, such as the use of generic views or the re-use of +custom views for multiple models, specifying the view function may +confuse the reverse URL matcher (because multiple patterns point to +the same view). + +For that problem, Django has **named URL patterns**. Using a named +URL pattern, it's possible to give a name to a pattern, and then +reference the name rather than the view function. A named URL +pattern is defined by replacing the pattern tuple by a call to +the ``url`` function):: + + from django.conf.urls.defaults import * + + url(r'^people/(\d+)/$', + 'django.views.generic.list_detail.object_detail', + name='people_view'), + +...and then using that name to perform the reverse URL resolution instead +of the view name:: + + from django.db.models import permalink + + def get_absolute_url(self): + return ('people_view', [str(self.id)]) + get_absolute_url = permalink(get_absolute_url) + +More details on named URL patterns are in the :ref:`URL dispatch documentation +<topics-http-urls>`. + +Extra instance methods +====================== + +In addition to ``save()``, ``delete()``, a model object might get any or all +of the following methods: + +get_FOO_display() +----------------- + +For every field that has ``choices`` set, the object will have a +``get_FOO_display()`` method, where ``FOO`` is the name of the field. This +method returns the "human-readable" value of the field. For example, in the +following model:: + + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) + class Person(models.Model): + name = models.CharField(max_length=20) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) + +...each ``Person`` instance will have a ``get_gender_display()`` method. Example:: + + >>> p = Person(name='John', gender='M') + >>> p.save() + >>> p.gender + 'M' + >>> p.get_gender_display() + 'Male' + +get_next_by_FOO(\**kwargs) and get_previous_by_FOO(\**kwargs) +------------------------------------------------------------- + +For every ``DateField`` and ``DateTimeField`` that does not have ``null=True``, +the object will have ``get_next_by_FOO()`` and ``get_previous_by_FOO()`` +methods, where ``FOO`` is the name of the field. This returns the next and +previous object with respect to the date field, raising the appropriate +``DoesNotExist`` exception when appropriate. + +Both methods accept optional keyword arguments, which should be in the format +described in :ref:`Field lookups <field-lookups>`. + +Note that in the case of identical date values, these methods will use the ID +as a fallback check. This guarantees that no records are skipped or duplicated. diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt new file mode 100644 index 0000000000..34ec7a19ed --- /dev/null +++ b/docs/ref/models/options.txt @@ -0,0 +1,175 @@ +.. _ref-models-options: + +====================== +Model ``Meta`` options +====================== + +This document explains all the possible :ref:`metadata options <meta-options>` that you can give your model in its internal ``class Meta``. + +Available ``Meta`` options +========================== + +.. currentmodule:: django.db.models + +``db_table`` +------------ + +.. attribute:: Options.db_table + +The name of the database table to use for the model:: + + db_table = 'music_album' + +.. _table-names: + +Table names +~~~~~~~~~~~ + +To save you time, Django automatically derives the name of the database table +from the name of your model class and the app that contains it. A model's +database table name is constructed by joining the model's "app label" -- the +name you used in ``manage.py startapp`` -- to the model's class name, with an +underscore between them. + +For example, if you have an app ``bookstore`` (as created by +``manage.py startapp bookstore``), a model defined as ``class Book`` will have +a database table named ``bookstore_book``. + +To override the database table name, use the ``db_table`` parameter in +``class Meta``. + +If your database table name is an SQL reserved word, or contains characters that +aren't allowed in Python variable names -- notably, the hyphen -- that's OK. +Django quotes column and table names behind the scenes. + +``db_tablespace`` +----------------- + +.. attribute:: Options.db_tablespace + +**New in Django development version** + +The name of the database tablespace to use for the model. If the backend doesn't +support tablespaces, this option is ignored. + +``get_latest_by`` +----------------- + +.. attribute:: Options.get_latest_by + +The name of a :class:`DateField` or :class:`DateTimeField` in the model. This +specifies the default field to use in your model :class:`Manager`'s +:class:`~QuerySet.latest` method. + +Example:: + + get_latest_by = "order_date" + +See the docs for :meth:`~django.db.models.QuerySet.latest` for more. + +``order_with_respect_to`` +------------------------- + +.. attribute:: Options.order_with_respect_to + +Marks this object as "orderable" with respect to the given field. This is almost +always used with related objects to allow them to be ordered with respect to a +parent object. For example, if an ``Answer`` relates to a ``Question`` object, +and a question has more than one answer, and the order of answers matters, you'd +do this:: + + class Answer(models.Model): + question = models.ForeignKey(Question) + # ... + + class Meta: + order_with_respect_to = 'question' + +``ordering`` +------------ + +.. attribute:: Options.ordering + +The default ordering for the object, for use when obtaining lists of objects:: + + ordering = ['-order_date'] + +This is a tuple or list of strings. Each string is a field name with an optional +"-" prefix, which indicates descending order. Fields without a leading "-" will +be ordered ascending. Use the string "?" to order randomly. + +.. note:: + + Regardless of how many fields are in :attr:`~Options.ordering`, the admin + site uses only the first field. + +For example, to order by a ``pub_date`` field ascending, use this:: + + ordering = ['pub_date'] + +To order by ``pub_date`` descending, use this:: + + ordering = ['-pub_date'] + +To order by ``pub_date`` descending, then by ``author`` ascending, use this:: + + ordering = ['-pub_date', 'author'] + +``permissions`` +--------------- + +.. attribute:: Options.permissions + +Extra permissions to enter into the permissions table when creating this object. +Add, delete and change permissions are automatically created for each object +that has ``admin`` set. This example specifies an extra permission, +``can_deliver_pizzas``:: + + permissions = (("can_deliver_pizzas", "Can deliver pizzas"),) + +This is a list or tuple of 2-tuples in the format ``(permission_code, +human_readable_permission_name)``. + +``unique_together`` +------------------- + +.. attribute:: Options.unique_together + +Sets of field names that, taken together, must be unique:: + + unique_together = (("driver", "restaurant"),) + +This is a list of lists of fields that must be unique when considered together. +It's used in the Django admin and is enforced at the database level (i.e., the +appropriate ``UNIQUE`` statements are included in the ``CREATE TABLE`` +statement). + +**New in Django development version** + +For convenience, unique_together can be a single list when dealing with a single +set of fields:: + + unique_together = ("driver", "restaurant") + +``verbose_name`` +---------------- + +.. attribute:: Options.verbose_name + +A human-readable name for the object, singular:: + + verbose_name = "pizza" + +If this isn't given, Django will use a munged version of the class name: +``CamelCase`` becomes ``camel case``. + +``verbose_name_plural`` +----------------------- + +.. attribute:: Options.verbose_name_plural + +The plural name for the object:: + + verbose_name_plural = "stories" + +If this isn't given, Django will use :attr:`~Options.verbose_name` + ``"s"``. diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt new file mode 100644 index 0000000000..b5de2e3aa2 --- /dev/null +++ b/docs/ref/models/querysets.txt @@ -0,0 +1,1060 @@ +.. _ref-models-querysets: + +====================== +QuerySet API reference +====================== + +.. currentmodule:: django.db.models + +This document describes the details of the ``QuerySet`` API. It builds on the +material presented in the :ref:`model <topics-db-models>` and `database query +<topics-db-queries>` guides, so you'll probably want to read and understand +those documents before reading this one. + +Throughout this reference we'll use the :ref:`example weblog models +<queryset-model-example>` presented in the :ref:`database query guide +<topics-db-queries>`. + +.. _when-querysets-are-evaluated: + +When QuerySets are evaluated +============================ + +Internally, a ``QuerySet`` can be constructed, filter, sliced, and generally +passed around without actually hitting the database. No database activity +actually occurs until you do something to evaluate the queryset. + +You can evaluate a ``QuerySet`` in the following ways: + + * **Iteration.** A ``QuerySet`` is iterable, and it executes its database + query the first time you iterate over it. For example, this will print + the headline of all entries in the database:: + + for e in Entry.objects.all(): + print e.headline + + * **Slicing.** As explained in :ref:`limiting-querysets`, a ``QuerySet`` can + be sliced, using Python's array-slicing syntax. Usually slicing a + ``QuerySet`` returns another (unevaluated )``QuerySet``, but Django will + execute the database query if you use the "step" parameter of slice + syntax. + + * **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it. + This is for convenience in the Python interactive interpreter, so you can + immediately see your results when using the API interactively. + + * **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it. + This, as you might expect, returns the length of the result list. + + Note: *Don't* use ``len()`` on ``QuerySet``\s if all you want to do is + determine the number of records in the set. It's much more efficient to + handle a count at the database level, using SQL's ``SELECT COUNT(*)``, + and Django provides a ``count()`` method for precisely this reason. See + ``count()`` below. + + * **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on + it. For example:: + + entry_list = list(Entry.objects.all()) + + Be warned, though, that this could have a large memory overhead, because + Django will load each element of the list into memory. In contrast, + iterating over a ``QuerySet`` will take advantage of your database to + load data and instantiate objects only as you need them. + +.. _queryset-api: + +QuerySet API +============ + +Though you usually won't create one manually -- you'll go through a :class:`Manager` -- here's the formal declaration of a ``QuerySet``: + +.. class:: QuerySet([model=None]) + +Usually when you'll interact with a ``QuerySet`` you'll use it by :ref:`chaining +filters <chaining-filters>`. To make this work, most ``QuerySet`` methods return new querysets. + +QuerySet methods that return new QuerySets +------------------------------------------ + +Django provides a range of ``QuerySet`` refinement methods that modify either +the types of results returned by the ``QuerySet`` or the way its SQL query is +executed. + +``filter(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~ + +Returns a new ``QuerySet`` containing objects that match the given lookup +parameters. + +The lookup parameters (``**kwargs``) should be in the format described in +`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the +underlying SQL statement. + +``exclude(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~~ + +Returns a new ``QuerySet`` containing objects that do *not* match the given +lookup parameters. + +The lookup parameters (``**kwargs``) should be in the format described in +`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the +underlying SQL statement, and the whole thing is enclosed in a ``NOT()``. + +This example excludes all entries whose ``pub_date`` is later than 2005-1-3 +AND whose ``headline`` is "Hello":: + + Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello') + +In SQL terms, that evaluates to:: + + SELECT ... + WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello') + +This example excludes all entries whose ``pub_date`` is later than 2005-1-3 +OR whose headline is "Hello":: + + Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello') + +In SQL terms, that evaluates to:: + + SELECT ... + WHERE NOT pub_date > '2005-1-3' + AND NOT headline = 'Hello' + +Note the second example is more restrictive. + +``order_by(*fields)`` +~~~~~~~~~~~~~~~~~~~~~ + +By default, results returned by a ``QuerySet`` are ordered by the ordering +tuple given by the ``ordering`` option in the model's ``Meta``. You can +override this on a per-``QuerySet`` basis by using the ``order_by`` method. + +Example:: + + Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') + +The result above will be ordered by ``pub_date`` descending, then by +``headline`` ascending. The negative sign in front of ``"-pub_date"`` indicates +*descending* order. Ascending order is implied. To order randomly, use ``"?"``, +like so:: + + Entry.objects.order_by('?') + +Note: ``order_by('?')`` queries may be expensive and slow, depending on the +database backend you're using. + +To order by a field in a different table, add the other table's name and a dot, +like so:: + + Entry.objects.order_by('blogs_blog.name', 'headline') + +There's no way to specify whether ordering should be case sensitive. With +respect to case-sensitivity, Django will order results however your database +backend normally orders them. + +Also, note that ``reverse()`` should generally only be called on a +``QuerySet`` which has a defined ordering (e.g., when querying against +a model which defines a default ordering, or when using +``order_by()``). If no such ordering is defined for a given +``QuerySet``, calling ``reverse()`` on it has no real effect (the +ordering was undefined prior to calling ``reverse()``, and will remain +undefined afterward). + + +``distinct()`` +~~~~~~~~~~~~~~ + +Returns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This +eliminates duplicate rows from the query results. + +By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this +is rarely a problem, because simple queries such as ``Blog.objects.all()`` +don't introduce the possibility of duplicate result rows. + +However, if your query spans multiple tables, it's possible to get duplicate +results when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``. + +``values(*fields)`` +~~~~~~~~~~~~~~~~~~~ + +Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of +dictionaries instead of model-instance objects. + +Each of those dictionaries represents an object, with the keys corresponding to +the attribute names of model objects. + +This example compares the dictionaries of ``values()`` with the normal model +objects:: + + # This list contains a Blog object. + >>> Blog.objects.filter(name__startswith='Beatles') + [Beatles Blog] + + # This list contains a dictionary. + >>> Blog.objects.filter(name__startswith='Beatles').values() + [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}] + +``values()`` takes optional positional arguments, ``*fields``, which specify +field names to which the ``SELECT`` should be limited. If you specify the +fields, each dictionary will contain only the field keys/values for the fields +you specify. If you don't specify the fields, each dictionary will contain a +key and value for every field in the database table. + +Example:: + + >>> Blog.objects.values() + [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}], + >>> Blog.objects.values('id', 'name') + [{'id': 1, 'name': 'Beatles Blog'}] + +A ``ValuesQuerySet`` is useful when you know you're only going to need values +from a small number of the available fields and you won't need the +functionality of a model instance object. It's more efficient to select only +the fields you need to use. + +Finally, note a ``ValuesQuerySet`` is a subclass of ``QuerySet``, so it has all +methods of ``QuerySet``. You can call ``filter()`` on it, or ``order_by()``, or +whatever. Yes, that means these two calls are identical:: + + Blog.objects.values().order_by('id') + Blog.objects.order_by('id').values() + +The people who made Django prefer to put all the SQL-affecting methods first, +followed (optionally) by any output-affecting methods (such as ``values()``), +but it doesn't really matter. This is your chance to really flaunt your +individualism. + +``dates(field, kind, order='ASC')`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Returns a ``DateQuerySet`` -- a ``QuerySet`` that evaluates to a list of +``datetime.datetime`` objects representing all available dates of a particular +kind within the contents of the ``QuerySet``. + +``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your +model. + +``kind`` should be either ``"year"``, ``"month"`` or ``"day"``. Each +``datetime.datetime`` object in the result list is "truncated" to the given +``type``. + + * ``"year"`` returns a list of all distinct year values for the field. + * ``"month"`` returns a list of all distinct year/month values for the field. + * ``"day"`` returns a list of all distinct year/month/day values for the field. + +``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or +``'DESC'``. This specifies how to order the results. + +Examples:: + + >>> Entry.objects.dates('pub_date', 'year') + [datetime.datetime(2005, 1, 1)] + >>> Entry.objects.dates('pub_date', 'month') + [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] + >>> Entry.objects.dates('pub_date', 'day') + [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] + >>> Entry.objects.dates('pub_date', 'day', order='DESC') + [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] + >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') + [datetime.datetime(2005, 3, 20)] + +``none()`` +~~~~~~~~~~ + +**New in Django development version** + +Returns an ``EmptyQuerySet`` -- a ``QuerySet`` that always evaluates to +an empty list. This can be used in cases where you know that you should +return an empty result set and your caller is expecting a ``QuerySet`` +object (instead of returning an empty list, for example.) + +Examples:: + + >>> Entry.objects.none() + [] + +.. _select-related: + +``select_related()`` +~~~~~~~~~~~~~~~~~~~~ + +Returns a ``QuerySet`` that will automatically "follow" foreign-key +relationships, selecting that additional related-object data when it executes +its query. This is a performance booster which results in (sometimes much) +larger queries but means later use of foreign-key relationships won't require +database queries. + +The following examples illustrate the difference between plain lookups and +``select_related()`` lookups. Here's standard lookup:: + + # Hits the database. + e = Entry.objects.get(id=5) + + # Hits the database again to get the related Blog object. + b = e.blog + +And here's ``select_related`` lookup:: + + # Hits the database. + e = Entry.objects.select_related().get(id=5) + + # Doesn't hit the database, because e.blog has been prepopulated + # in the previous query. + b = e.blog + +``select_related()`` follows foreign keys as far as possible. If you have the +following models:: + + class City(models.Model): + # ... + + class Person(models.Model): + # ... + hometown = models.ForeignKey(City) + + class Book(models.Model): + # ... + author = models.ForeignKey(Person) + +...then a call to ``Book.objects.select_related().get(id=4)`` will cache the +related ``Person`` *and* the related ``City``:: + + b = Book.objects.select_related().get(id=4) + p = b.author # Doesn't hit the database. + c = p.hometown # Doesn't hit the database. + + b = Book.objects.get(id=4) # No select_related() in this example. + p = b.author # Hits the database. + c = p.hometown # Hits the database. + +Note that ``select_related()`` does not follow foreign keys that have +``null=True``. + +Usually, using ``select_related()`` can vastly improve performance because your +app can avoid many database calls. However, in situations with deeply nested +sets of relationships ``select_related()`` can sometimes end up following "too +many" relations, and can generate queries so large that they end up being slow. + +In these situations, you can use the ``depth`` argument to ``select_related()`` +to control how many "levels" of relations ``select_related()`` will actually +follow:: + + b = Book.objects.select_related(depth=1).get(id=4) + p = b.author # Doesn't hit the database. + c = p.hometown # Requires a database call. + +The ``depth`` argument is new in the Django development version. + +``extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes, the Django query syntax by itself can't easily express a complex +``WHERE`` clause. For these edge cases, Django provides the ``extra()`` +``QuerySet`` modifier -- a hook for injecting specific clauses into the SQL +generated by a ``QuerySet``. + +By definition, these extra lookups may not be portable to different database +engines (because you're explicitly writing SQL code) and violate the DRY +principle, so you should avoid them if possible. + +Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None +of the arguments is required, but you should use at least one of them. + +``select`` + The ``select`` argument lets you put extra fields in the ``SELECT`` clause. + It should be a dictionary mapping attribute names to SQL clauses to use to + calculate that attribute. + + Example:: + + Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) + + As a result, each ``Entry`` object will have an extra attribute, + ``is_recent``, a boolean representing whether the entry's ``pub_date`` is + greater than Jan. 1, 2006. + + Django inserts the given SQL snippet directly into the ``SELECT`` + statement, so the resulting SQL of the above example would be:: + + SELECT blog_entry.*, (pub_date > '2006-01-01') + FROM blog_entry; + + + The next example is more advanced; it does a subquery to give each + resulting ``Blog`` object an ``entry_count`` attribute, an integer count + of associated ``Entry`` objects:: + + Blog.objects.extra( + select={ + 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id' + }, + ) + + (In this particular case, we're exploiting the fact that the query will + already contain the ``blog_blog`` table in its ``FROM`` clause.) + + The resulting SQL of the above example would be:: + + SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) + FROM blog_blog; + + Note that the parenthesis required by most database engines around + subqueries are not required in Django's ``select`` clauses. Also note that + some database backends, such as some MySQL versions, don't support + subqueries. + + **New in Django development version** + In some rare cases, you might wish to pass parameters to the SQL fragments + in ``extra(select=...)```. For this purpose, use the ``select_params`` + parameter. Since ``select_params`` is a sequence and the ``select`` + attribute is a dictionary, some care is required so that the parameters + are matched up correctly with the extra select pieces. In this situation, + you should use a ``django.utils.datastructures.SortedDict`` for the + ``select`` value, not just a normal Python dictionary. + + This will work, for example:: + + Blog.objects.extra( + select=SortedDict([('a', '%s'), ('b', '%s')]), + select_params=('one', 'two')) + + The only thing to be careful about when using select parameters in + ``extra()`` is to avoid using the substring ``"%%s"`` (that's *two* + percent characters before the ``s``) in the select strings. Django's + tracking of parameters looks for ``%s`` and an escaped ``%`` character + like this isn't detected. That will lead to incorrect results. + +``where`` / ``tables`` + You can define explicit SQL ``WHERE`` clauses -- perhaps to perform + non-explicit joins -- by using ``where``. You can manually add tables to + the SQL ``FROM`` clause by using ``tables``. + + ``where`` and ``tables`` both take a list of strings. All ``where`` + parameters are "AND"ed to any other search criteria. + + Example:: + + Entry.objects.extra(where=['id IN (3, 4, 5, 20)']) + + ...translates (roughly) into the following SQL:: + + SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20); + + Be careful when using the ``tables`` parameter if you're specifying + tables that are already used in the query. When you add extra tables + via the ``tables`` parameter, Django assumes you want that table included + an extra time, if it is already included. That creates a problem, + since the table name will then be given an alias. If a table appears + multiple times in an SQL statement, the second and subsequent occurrences + must use aliases so the database can tell them apart. If you're + referring to the extra table you added in the extra ``where`` parameter + this is going to cause errors. + + Normally you'll only be adding extra tables that don't already appear in + the query. However, if the case outlined above does occur, there are a few + solutions. First, see if you can get by without including the extra table + and use the one already in the query. If that isn't possible, put your + ``extra()`` call at the front of the queryset construction so that your + table is the first use of that table. Finally, if all else fails, look at + the query produced and rewrite your ``where`` addition to use the alias + given to your extra table. The alias will be the same each time you + construct the queryset in the same way, so you can rely upon the alias + name to not change. + +``order_by`` + If you need to order the resulting queryset using some of the new fields + or tables you have included via ``extra()`` use the ``order_by`` parameter + to ``extra()`` and pass in a sequence of strings. These strings should + either be model fields (as in the normal ``order_by()`` method on + querysets), of the form ``table_name.column_name`` or an alias for a column + that you specified in the ``select`` parameter to ``extra()``. + + For example:: + + q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) + q = q.extra(order_by = ['-is_recent']) + + This would sort all the items for which ``is_recent`` is true to the front + of the result set (``True`` sorts before ``False`` in a descending + ordering). + + This shows, by the way, that you can make multiple calls to + ``extra()`` and it will behave as you expect (adding new constraints each + time). + +``params`` + The ``where`` parameter described above may use standard Python database + string placeholders -- ``'%s'`` to indicate parameters the database engine + should automatically quote. The ``params`` argument is a list of any extra + parameters to be substituted. + + Example:: + + Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + + Always use ``params`` instead of embedding values directly into ``where`` + because ``params`` will ensure values are quoted correctly according to + your particular backend. (For example, quotes will be escaped correctly.) + + Bad:: + + Entry.objects.extra(where=["headline='Lennon'"]) + + Good:: + + Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + +**New in Django development version** The ``select_params`` argument to +``extra()`` is new. Previously, you could attempt to pass parameters for +``select`` in the ``params`` argument, but it worked very unreliably. + +QuerySet methods that do not return QuerySets +--------------------------------------------- + +The following ``QuerySet`` methods evaluate the ``QuerySet`` and return +something *other than* a ``QuerySet``. + +These methods do not use a cache (see :ref:`caching-and-querysets`). Rather, +they query the database each time they're called. + +.. _get-kwargs: + +``get(**kwargs)`` +~~~~~~~~~~~~~~~~~ + +Returns the object matching the given lookup parameters, which should be in +the format described in `Field lookups`_. + +``get()`` raises ``AssertionError`` if more than one object was found. + +``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for the +given parameters. The ``DoesNotExist`` exception is an attribute of the model +class. Example:: + + Entry.objects.get(id='foo') # raises Entry.DoesNotExist + +The ``DoesNotExist`` exception inherits from +``django.core.exceptions.ObjectDoesNotExist``, so you can target multiple +``DoesNotExist`` exceptions. Example:: + + from django.core.exceptions import ObjectDoesNotExist + try: + e = Entry.objects.get(id=3) + b = Blog.objects.get(id=1) + except ObjectDoesNotExist: + print "Either the entry or blog doesn't exist." + +``create(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~ + +A convenience method for creating an object and saving it all in one step. Thus:: + + p = Person.objects.create(first_name="Bruce", last_name="Springsteen") + +and:: + + p = Person(first_name="Bruce", last_name="Springsteen") + p.save() + +are equivalent. + +``get_or_create(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A convenience method for looking up an object with the given kwargs, creating +one if necessary. + +Returns a tuple of ``(object, created)``, where ``object`` is the retrieved or +created object and ``created`` is a boolean specifying whether a new object was +created. + +This is meant as a shortcut to boilerplatish code and is mostly useful for +data-import scripts. For example:: + + try: + obj = Person.objects.get(first_name='John', last_name='Lennon') + except Person.DoesNotExist: + obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9)) + obj.save() + +This pattern gets quite unwieldy as the number of fields in a model goes up. +The above example can be rewritten using ``get_or_create()`` like so:: + + obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon', + defaults={'birthday': date(1940, 10, 9)}) + +Any keyword arguments passed to ``get_or_create()`` -- *except* an optional one +called ``defaults`` -- will be used in a ``get()`` call. If an object is found, +``get_or_create()`` returns a tuple of that object and ``False``. If an object +is *not* found, ``get_or_create()`` will instantiate and save a new object, +returning a tuple of the new object and ``True``. The new object will be +created according to this algorithm:: + + defaults = kwargs.pop('defaults', {}) + params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) + params.update(defaults) + obj = self.model(**params) + obj.save() + +In English, that means start with any non-``'defaults'`` keyword argument that +doesn't contain a double underscore (which would indicate a non-exact lookup). +Then add the contents of ``defaults``, overriding any keys if necessary, and +use the result as the keyword arguments to the model class. + +If you have a field named ``defaults`` and want to use it as an exact lookup in +``get_or_create()``, just use ``'defaults__exact'``, like so:: + + Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'}) + +Finally, a word on using ``get_or_create()`` in Django views. As mentioned +earlier, ``get_or_create()`` is mostly useful in scripts that need to parse +data and create new records if existing ones aren't available. But if you need +to use ``get_or_create()`` in a view, please make sure to use it only in +``POST`` requests unless you have a good reason not to. ``GET`` requests +shouldn't have any effect on data; use ``POST`` whenever a request to a page +has a side effect on your data. For more, see `Safe methods`_ in the HTTP spec. + +.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 + +``count()`` +~~~~~~~~~~~ + +Returns an integer representing the number of objects in the database matching +the ``QuerySet``. ``count()`` never raises exceptions. + +Example:: + + # Returns the total number of entries in the database. + Entry.objects.count() + + # Returns the number of entries whose headline contains 'Lennon' + Entry.objects.filter(headline__contains='Lennon').count() + +``count()`` performs a ``SELECT COUNT(*)`` behind the scenes, so you should +always use ``count()`` rather than loading all of the record into Python +objects and calling ``len()`` on the result. + +Depending on which database you're using (e.g. PostgreSQL vs. MySQL), +``count()`` may return a long integer instead of a normal Python integer. This +is an underlying implementation quirk that shouldn't pose any real-world +problems. + +``in_bulk(id_list)`` +~~~~~~~~~~~~~~~~~~~~ + +Takes a list of primary-key values and returns a dictionary mapping each +primary-key value to an instance of the object with the given ID. + +Example:: + + >>> Blog.objects.in_bulk([1]) + {1: Beatles Blog} + >>> Blog.objects.in_bulk([1, 2]) + {1: Beatles Blog, 2: Cheddar Talk} + >>> Blog.objects.in_bulk([]) + {} + +If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary. + +``iterator()`` +~~~~~~~~~~~~~~ + +Evaluates the ``QuerySet`` (by performing the query) and returns an +`iterator`_ over the results. A ``QuerySet`` typically reads all of +its results and instantiates all of the corresponding objects the +first time you access it; ``iterator()`` will instead read results and +instantiate objects in discrete chunks, yielding them one at a +time. For a ``QuerySet`` which returns a large number of objects, this +often results in better performance and a significant reduction in +memory use. + +Note that using ``iterator()`` on a ``QuerySet`` which has already +been evaluated will force it to evaluate again, repeating the query. + +.. _iterator: http://www.python.org/dev/peps/pep-0234/ + +``latest(field_name=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Returns the latest object in the table, by date, using the ``field_name`` +provided as the date field. + +This example returns the latest ``Entry`` in the table, according to the +``pub_date`` field:: + + Entry.objects.latest('pub_date') + +If your model's ``Meta`` specifies ``get_latest_by``, you can leave off the +``field_name`` argument to ``latest()``. Django will use the field specified in +``get_latest_by`` by default. + +Like ``get()``, ``latest()`` raises ``DoesNotExist`` if an object doesn't +exist with the given parameters. + +Note ``latest()`` exists purely for convenience and readability. + +.. _field-lookups: + +Field lookups +------------- + +Field lookups are how you specify the meat of an SQL ``WHERE`` clause. They're +specified as keyword arguments to the ``QuerySet`` methods ``filter()``, +``exclude()`` and ``get()``. + +For an introduction, see :ref:`field-lookups-intro`. + +exact +~~~~~ + +Exact match. If the value provided for comparison is ``None``, it will +be interpreted as an SQL ``NULL`` (See isnull_ for more details). + +Examples:: + + Entry.objects.get(id__exact=14) + Entry.objects.get(id__exact=None) + +SQL equivalents:: + + SELECT ... WHERE id = 14; + SELECT ... WHERE id IS NULL; + +**New in Django development version:** The semantics of ``id__exact=None`` have +changed in the development version. Previously, it was (intentionally) +converted to ``WHERE id = NULL`` at the SQL level, which would never match +anything. It has now been changed to behave the same as ``id__isnull=True``. + +.. admonition:: MySQL comparisons + + In MySQL, whether or not ``exact`` comparisons are case-sensitive depends + upon the collation setting of the table involved. The default is usually + ``latin1_swedish_ci`` or ``utf8_swedish_ci``, which results in + case-insensitive comparisons. Change the collation to + ``latin1_swedish_cs`` or ``utf8_bin`` for case sensitive comparisons. + + For more details, refer to the MySQL manual section about `character sets + and collations`_. + +.. _character sets and collations: http://dev.mysql.com/doc/refman/5.0/en/charset.html + +iexact +~~~~~~ + +Case-insensitive exact match. + +Example:: + + Blog.objects.get(name__iexact='beatles blog') + +SQL equivalent:: + + SELECT ... WHERE name ILIKE 'beatles blog'; + +Note this will match ``'Beatles Blog'``, ``'beatles blog'``, +``'BeAtLes BLoG'``, etc. + +contains +~~~~~~~~ + +Case-sensitive containment test. + +Example:: + + Entry.objects.get(headline__contains='Lennon') + +SQL equivalent:: + + SELECT ... WHERE headline LIKE '%Lennon%'; + +Note this will match the headline ``'Today Lennon honored'`` but not +``'today lennon honored'``. + +SQLite doesn't support case-sensitive ``LIKE`` statements; ``contains`` acts +like ``icontains`` for SQLite. + +icontains +~~~~~~~~~ + +Case-insensitive containment test. + +Example:: + + Entry.objects.get(headline__icontains='Lennon') + +SQL equivalent:: + + SELECT ... WHERE headline ILIKE '%Lennon%'; + +in +~~ + +In a given list. + +Example:: + + Entry.objects.filter(id__in=[1, 3, 4]) + +SQL equivalent:: + + SELECT ... WHERE id IN (1, 3, 4); + +You can also use a queryset to dynamically evaluate the list of values +instead of providing a list of literal values. The queryset must be +reduced to a list of individual values using the ``values()`` method, +and then converted into a query using the ``query`` attribute:: + + Entry.objects.filter(blog__in=Blog.objects.filter(name__contains='Cheddar').values('pk').query) + +This queryset will be evaluated as subselect statement:: + + SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%') + +gt +~~ + +Greater than. + +Example:: + + Entry.objects.filter(id__gt=4) + +SQL equivalent:: + + SELECT ... WHERE id > 4; + +gte +~~~ + +Greater than or equal to. + +lt +~~ + +Less than. + +lte +~~~ + +Less than or equal to. + +in +~~ + +In a given list. + +Example:: + + Entry.objects.filter(id__in=[1, 3, 4]) + +SQL equivalent:: + + SELECT ... WHERE id IN (1, 3, 4); + +startswith +~~~~~~~~~~ + +Case-sensitive starts-with. + +Example:: + + Entry.objects.filter(headline__startswith='Will') + +SQL equivalent:: + + SELECT ... WHERE headline LIKE 'Will%'; + +SQLite doesn't support case-sensitive ``LIKE`` statements; ``startswith`` acts +like ``istartswith`` for SQLite. + +istartswith +~~~~~~~~~~~ + +Case-insensitive starts-with. + +Example:: + + Entry.objects.filter(headline__istartswith='will') + +SQL equivalent:: + + SELECT ... WHERE headline ILIKE 'Will%'; + +endswith +~~~~~~~~ + +Case-sensitive ends-with. + +Example:: + + Entry.objects.filter(headline__endswith='cats') + +SQL equivalent:: + + SELECT ... WHERE headline LIKE '%cats'; + +SQLite doesn't support case-sensitive ``LIKE`` statements; ``endswith`` acts +like ``iendswith`` for SQLite. + +iendswith +~~~~~~~~~ + +Case-insensitive ends-with. + +Example:: + + Entry.objects.filter(headline__iendswith='will') + +SQL equivalent:: + + SELECT ... WHERE headline ILIKE '%will' + +range +~~~~~ + +Range test (inclusive). + +Example:: + + start_date = datetime.date(2005, 1, 1) + end_date = datetime.date(2005, 3, 31) + Entry.objects.filter(pub_date__range=(start_date, end_date)) + +SQL equivalent:: + + SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31'; + +You can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates, +numbers and even characters. + +year +~~~~ + +For date/datetime fields, exact year match. Takes a four-digit year. + +Example:: + + Entry.objects.filter(pub_date__year=2005) + +SQL equivalent:: + + SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005'; + +(The exact SQL syntax varies for each database engine.) + +month +~~~~~ + +For date/datetime fields, exact month match. Takes an integer 1 (January) +through 12 (December). + +Example:: + + Entry.objects.filter(pub_date__month=12) + +SQL equivalent:: + + SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12'; + +(The exact SQL syntax varies for each database engine.) + +day +~~~ + +For date/datetime fields, exact day match. + +Example:: + + Entry.objects.filter(pub_date__day=3) + +SQL equivalent:: + + SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3'; + +(The exact SQL syntax varies for each database engine.) + +Note this will match any record with a pub_date on the third day of the month, +such as January 3, July 3, etc. + +isnull +~~~~~~ + +Takes either ``True`` or ``False``, which correspond to SQL queries of +``IS NULL`` and ``IS NOT NULL``, respectively. + +Example:: + + Entry.objects.filter(pub_date__isnull=True) + +SQL equivalent:: + + SELECT ... WHERE pub_date IS NULL; + +.. admonition:: ``__isnull=True`` vs ``__exact=None`` + + There is an important difference between ``__isnull=True`` and + ``__exact=None``. ``__exact=None`` will *always* return an empty result + set, because SQL requires that no value is equal to ``NULL``. + ``__isnull`` determines if the field is currently holding the value + of ``NULL`` without performing a comparison. + +search +~~~~~~ + +A boolean full-text search, taking advantage of full-text indexing. This is +like ``contains`` but is significantly faster due to full-text indexing. + +Note this is only available in MySQL and requires direct manipulation of the +database to add the full-text index. + +regex +~~~~~ + +**New in Django development version** + +Case-sensitive regular expression match. + +The regular expression syntax is that of the database backend in use. In the +case of SQLite, which doesn't natively support regular-expression lookups, the +syntax is that of Python's ``re`` module. + +Example:: + + Entry.objects.get(title__regex=r'^(An?|The) +') + +SQL equivalents:: + + SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL + + SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'c'); -- Oracle + + SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL + + SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite + +Using raw strings (e.g., ``r'foo'`` instead of ``'foo'``) for passing in the +regular expression syntax is recommended. + +iregex +~~~~~~ + +**New in Django development version** + +Case-insensitive regular expression match. + +Example:: + + Entry.objects.get(title__iregex=r'^(an?|the) +') + +SQL equivalents:: + + SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL + + SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle + + SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL + + SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite + diff --git a/docs/ref/models/relations.txt b/docs/ref/models/relations.txt new file mode 100644 index 0000000000..1ee8b26258 --- /dev/null +++ b/docs/ref/models/relations.txt @@ -0,0 +1,77 @@ +.. _ref-models-relations: + +========================= +Related objects reference +========================= + +Extra methods on managers when used in a ForeignKey context +=========================================================== + +.. currentmodule:: django.db.models + +.. method:: QuerySet.add(obj1, [obj2, ...]) + + Adds the specified model objects to the related object set. + + Example:: + + >>> b = Blog.objects.get(id=1) + >>> e = Entry.objects.get(id=234) + >>> b.entry_set.add(e) # Associates Entry e with Blog b. + +.. method:: QuerySet.create(**kwargs)` + + Creates a new object, saves it and puts it in the related object set. + Returns the newly created object:: + + >>> b = Blog.objects.get(id=1) + >>> e = b.entry_set.create( + ... headline='Hello', + ... body_text='Hi', + ... pub_date=datetime.date(2005, 1, 1) + ... ) + + # No need to call e.save() at this point -- it's already been saved. + + This is equivalent to (but much simpler than):: + + >>> b = Blog.objects.get(id=1) + >>> e = Entry( + .... blog=b, + .... headline='Hello', + .... body_text='Hi', + .... pub_date=datetime.date(2005, 1, 1) + .... ) + >>> e.save() + + Note that there's no need to specify the keyword argument of the model that + defines the relationship. In the above example, we don't pass the parameter + ``blog`` to ``create()``. Django figures out that the new ``Entry`` object's + ``blog`` field should be set to ``b``. + +.. method:: QuerySet.remove(obj1, [obj2, ...]) + + Removes the specified model objects from the related object set:: + + >>> b = Blog.objects.get(id=1) + >>> e = Entry.objects.get(id=234) + >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b. + + In order to prevent database inconsistency, this method only exists on + ``ForeignKey`` objects where ``null=True``. If the related field can't be + set to ``None`` (``NULL``), then an object can't be removed from a relation + without being added to another. In the above example, removing ``e`` from + ``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because the + ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid. + +.. method:: QuerySet.clear() + + Removes all objects from the related object set:: + + >>> b = Blog.objects.get(id=1) + >>> b.entry_set.clear() + + Note this doesn't delete the related objects -- it just disassociates them. + + Just like ``remove()``, ``clear()`` is only available on ``ForeignKey``s + where ``null=True``. diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt new file mode 100644 index 0000000000..34f098b084 --- /dev/null +++ b/docs/ref/request-response.txt @@ -0,0 +1,574 @@ +.. _ref-request-response: + +============================ +Request and response objects +============================ + +.. module:: django.http + :synopsis: Classes dealing with HTTP requests and responses. + +Quick overview +============== + +Django uses request and response objects to pass state through the system. + +When a page is requested, Django creates an :class:`HttpRequest` object that +contains metadata about the request. Then Django loads the appropriate view, +passing the :class:`HttpRequest` as the first argument to the view function. Each +view is responsible for returning an :class:`HttpResponse` object. + +This document explains the APIs for :class:`HttpRequest` and :class:`HttpResponse` +objects. + +HttpRequest objects +=================== + +.. class:: HttpRequest + +Attributes +---------- + +All attributes except ``session`` should be considered read-only. + +.. attribute:: HttpRequest.path + + A string representing the full path to the requested page, not including + the domain. + + Example: ``"/music/bands/the_beatles/"`` + +.. attribute:: HttpRequest.method + + A string representing the HTTP method used in the request. This is + guaranteed to be uppercase. Example:: + + if request.method == 'GET': + do_something() + elif request.method == 'POST': + do_something_else() + +.. attribute:: HttpRequest.encoding + + **New in Django development version** + + A string representing the current encoding used to decode form submission + data (or ``None``, which means the ``DEFAULT_CHARSET`` setting is used). + You can write to this attribute to change the encoding used when accessing + the form data. Any subsequent attribute accesses (such as reading from + ``GET`` or ``POST``) will use the new ``encoding`` value. Useful if you + know the form data is not in the ``DEFAULT_CHARSET`` encoding. + +.. attribute:: HttpRequest.GET + + A dictionary-like object containing all given HTTP GET parameters. See the + ``QueryDict`` documentation below. + +.. attribute:: HttpRequest.POST + + A dictionary-like object containing all given HTTP POST parameters. See the + ``QueryDict`` documentation below. + + It's possible that a request can come in via POST with an empty ``POST`` + dictionary -- if, say, a form is requested via the POST HTTP method but + does not include form data. Therefore, you shouldn't use ``if request.POST`` + to check for use of the POST method; instead, use ``if request.method == + "POST"`` (see above). + + Note: ``POST`` does *not* include file-upload information. See ``FILES``. + +.. attribute:: HttpRequest.REQUEST + + For convenience, a dictionary-like object that searches ``POST`` first, + then ``GET``. Inspired by PHP's ``$_REQUEST``. + + For example, if ``GET = {"name": "john"}`` and ``POST = {"age": '34'}``, + ``REQUEST["name"]`` would be ``"john"``, and ``REQUEST["age"]`` would be + ``"34"``. + + It's strongly suggested that you use ``GET`` and ``POST`` instead of + ``REQUEST``, because the former are more explicit. + +.. attribute:: HttpRequest.COOKIES + + A standard Python dictionary containing all cookies. Keys and values are + strings. + +.. attribute:: HttpRequest.FILES + + .. admonition:: Changed in Django development version + + In previous versions of Django, ``request.FILES`` contained + simple ``dict`` objects representing uploaded files. This is + no longer true -- files are represented by ``UploadedFile`` + objects as described below. + + These ``UploadedFile`` objects will emulate the old-style ``dict`` + interface, but this is deprecated and will be removed in the next + release of Django. + + A dictionary-like object containing all uploaded files. Each key in + ``FILES`` is the ``name`` from the ``<input type="file" name="" />``. Each + value in ``FILES`` is an ``UploadedFile`` object containing the following + attributes: + + * ``read(num_bytes=None)`` -- Read a number of bytes from the file. + * ``file_name`` -- The name of the uploaded file. + * ``file_size`` -- The size, in bytes, of the uploaded file. + * ``chunk()`` -- A generator that yields sequential chunks of data. + + See :ref:`topics-files` for more information. + + Note that ``FILES`` will only contain data if the request method was POST + and the ``<form>`` that posted to the request had + ``enctype="multipart/form-data"``. Otherwise, ``FILES`` will be a blank + dictionary-like object. + +.. attribute:: HttpRequest.META + + A standard Python dictionary containing all available HTTP headers. + Available headers depend on the client and server, but here are some + examples: + + * ``CONTENT_LENGTH`` + * ``CONTENT_TYPE`` + * ``HTTP_ACCEPT_ENCODING`` + * ``HTTP_ACCEPT_LANGUAGE`` + * ``HTTP_HOST`` -- The HTTP Host header sent by the client. + * ``HTTP_REFERER`` -- The referring page, if any. + * ``HTTP_USER_AGENT`` -- The client's user-agent string. + * ``QUERY_STRING`` -- The query string, as a single (unparsed) string. + * ``REMOTE_ADDR`` -- The IP address of the client. + * ``REMOTE_HOST`` -- The hostname of the client. + * ``REQUEST_METHOD`` -- A string such as ``"GET"`` or ``"POST"``. + * ``SERVER_NAME`` -- The hostname of the server. + * ``SERVER_PORT`` -- The port of the server. + +.. attribute:: HttpRequest.user + + A ``django.contrib.auth.models.User`` object representing the currently + logged-in user. If the user isn't currently logged in, ``user`` will be set + to an instance of ``django.contrib.auth.models.AnonymousUser``. You + can tell them apart with ``is_authenticated()``, like so:: + + if request.user.is_authenticated(): + # Do something for logged-in users. + else: + # Do something for anonymous users. + + ``user`` is only available if your Django installation has the + ``AuthenticationMiddleware`` activated. For more, see + :ref:`topics-auth`. + +.. attribute:: HttpRequest.session + + A readable-and-writable, dictionary-like object that represents the current + session. This is only available if your Django installation has session + support activated. See the :ref:`session documentation + <topics-http-sessions>` for full details. + +.. attribute:: HttpRequest.row_post_data + + The raw HTTP POST data. This is only useful for advanced processing. Use + ``POST`` instead. + +.. attribute:: HttpRequest.urlconf + + Not defined by Django itself, but will be read if other code (e.g., a custom + middleware class) sets it. When present, this will be used as the root + URLconf for the current request, overriding the ``ROOT_URLCONF`` setting. + See :ref:`how-django-processes-a-request` for details. + +Methods +------- + +.. method:: HttpRequest.get_host() + + **New in Django development version** + + Returns the originating host of the request using information from the + ``HTTP_X_FORWARDED_HOST`` and ``HTTP_HOST`` headers (in that order). If + they don't provide a value, the method uses a combination of + ``SERVER_NAME`` and ``SERVER_PORT`` as detailed in `PEP 333`_. + + .. _PEP 333: http://www.python.org/dev/peps/pep-0333/ + + Example: ``"127.0.0.1:8000"`` + +.. method:: HttpRequest.get_full_path() + + Returns the ``path``, plus an appended query string, if applicable. + + Example: ``"/music/bands/the_beatles/?print=true"`` + +.. method:: HttpRequest.build_absolute_uri(location) + + **New in Django development version** + + Returns the absolute URI form of ``location``. If no location is provided, + the location will be set to ``request.get_full_path()``. + + If the location is already an absolute URI, it will not be altered. + Otherwise the absolute URI is built using the server variables available in + this request. + + Example: ``"http://example.com/music/bands/the_beatles/?print=true"`` + +.. method:: HttpRequest.is_secure() + + Returns ``True`` if the request is secure; that is, if it was made with + HTTPS. + +.. method:: HttpRequest.is_ajax() + + **New in Django development version** + + Returns ``True`` if the request was made via an ``XMLHttpRequest``, by checking + the ``HTTP_X_REQUESTED_WITH`` header for the string ``'XMLHttpRequest'``. The + following major JavaScript libraries all send this header: + + * jQuery + * Dojo + * MochiKit + * MooTools + * Prototype + * YUI + + If you write your own XMLHttpRequest call (on the browser side), you'll + have to set this header manually if you want ``is_ajax()`` to work. + + +QueryDict objects +----------------- + +.. class:: QueryDict + +In an :class:`HttpRequest` object, the ``GET`` and ``POST`` attributes are instances +of ``django.http.QueryDict``. :class:`QueryDict` is a dictionary-like +class customized to deal with multiple values for the same key. This is +necessary because some HTML form elements, notably +``<select multiple="multiple">``, pass multiple values for the same key. + +``QueryDict`` instances are immutable, unless you create a ``copy()`` of them. +That means you can't change attributes of ``request.POST`` and ``request.GET`` +directly. + +Methods +------- + +:class:`QueryDict` implements all the standard dictionary methods, because it's +a subclass of dictionary. Exceptions are outlined here: + +.. method:: QueryDict.__getitem__(key) + + Returns the value for the given key. If the key has more than one value, + ``__getitem__()`` returns the last value. Raises + ``django.utils.datastructure.MultiValueDictKeyError`` if the key does not + exist. (This is a subclass of Python's standard ``KeyError``, so you can + stick to catching ``KeyError``.) + +.. method:: QueryDict.__setitem__(key, value) + + Sets the given key to ``[value]`` (a Python list whose single element is + ``value``). Note that this, as other dictionary functions that have side + effects, can only be called on a mutable ``QueryDict`` (one that was created + via ``copy()``). + +.. method:: QueryDict.__contains__(key) + + Returns ``True`` if the given key is set. This lets you do, e.g., ``if "foo" + in request.GET``. + +.. method:: QueryDict.get(key, default) + + Uses the same logic as ``__getitem__()`` above, with a hook for returning a + default value if the key doesn't exist. + +.. method:: QueryDict.setdefault(key, default) + + Just like the standard dictionary ``setdefault()`` method, except it uses + ``__setitem__`` internally. + +.. method:: QueryDict.update(other_dict) + + Takes either a ``QueryDict`` or standard dictionary. Just like the standard + dictionary ``update()`` method, except it *appends* to the current + dictionary items rather than replacing them. For example:: + + >>> q = QueryDict('a=1') + >>> q = q.copy() # to make it mutable + >>> q.update({'a': '2'}) + >>> q.getlist('a') + ['1', '2'] + >>> q['a'] # returns the last + ['2'] + +.. method:: QueryDict.items() + + Just like the standard dictionary ``items()`` method, except this uses the + same last-value logic as ``__getitem()__``. For example:: + + >>> q = QueryDict('a=1&a=2&a=3') + >>> q.items() + [('a', '3')] + +.. method:: QueryDict.values() + + Just like the standard dictionary ``values()`` method, except this uses the + same last-value logic as ``__getitem()__``. For example:: + + >>> q = QueryDict('a=1&a=2&a=3') + >>> q.values() + ['3'] + +In addition, ``QueryDict`` has the following methods: + +.. method:: QueryDict.copy() + + Returns a copy of the object, using ``copy.deepcopy()`` from the Python + standard library. The copy will be mutable -- that is, you can change its + values. + +.. method:: QueryDict.getlist(key) + + Returns the data with the requested key, as a Python list. Returns an + empty list if the key doesn't exist. It's guaranteed to return a list of + some sort. + +.. method:: QueryDict.setlist(key, list_) + + Sets the given key to ``list_`` (unlike ``__setitem__()``). + +.. method:: QueryDict.appendlist(key, item) + + Appends an item to the internal list associated with key. + +.. method:: QueryDict.setlistdefault(key, default_list) + + Just like ``setdefault``, except it takes a list of values instead of a + single value. + +.. method:: QueryDict.lists() + + Like :method:items(), except it includes all values, as a list, for each + member of the dictionary. For example:: + + >>> q = QueryDict('a=1&a=2&a=3') + >>> q.lists() + [('a', ['1', '2', '3'])] + +.. method:: QueryDict.urlencode() + + Returns a string of the data in query-string format. + Example: ``"a=2&b=3&b=5"``. + +HttpResponse objects +==================== + +.. class:: HttpResponse + +In contrast to :class:`HttpRequest` objects, which are created automatically by +Django, :class:`HttpResponse` objects are your responsibility. Each view you +write is responsible for instantiating, populating and returning an +:class:`HttpResponse`. + +The :class:`HttpResponse` class lives in the ``django.http`` module. + +Usage +----- + +Passing strings +~~~~~~~~~~~~~~~ + +Typical usage is to pass the contents of the page, as a string, to the +:class:`HttpResponse` constructor:: + + >>> response = HttpResponse("Here's the text of the Web page.") + >>> response = HttpResponse("Text only, please.", mimetype="text/plain") + +But if you want to add content incrementally, you can use ``response`` as a +file-like object:: + + >>> response = HttpResponse() + >>> response.write("<p>Here's the text of the Web page.</p>") + >>> response.write("<p>Here's another paragraph.</p>") + +You can add and delete headers using dictionary syntax:: + + >>> response = HttpResponse() + >>> response['X-DJANGO'] = "It's the best." + >>> del response['X-PHP'] + >>> response['X-DJANGO'] + "It's the best." + +Note that ``del`` doesn't raise ``KeyError`` if the header doesn't exist. + +Passing iterators +~~~~~~~~~~~~~~~~~ + +Finally, you can pass ``HttpResponse`` an iterator rather than passing it +hard-coded strings. If you use this technique, follow these guidelines: + + * The iterator should return strings. + * If an :class:`HttpResponse` has been initialized with an iterator as its + content, you can't use the class:`HttpResponse` instance as a file-like + object. Doing so will raise ``Exception``. + +Setting headers +~~~~~~~~~~~~~~~ + +To set a header in your response, just treat it like a dictionary:: + + >>> response = HttpResponse() + >>> response['Pragma'] = 'no-cache' + +Telling the browser to treat the response as a file attachment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To tell the browser to treat the response as a file attachment, use the +``mimetype`` argument and set the ``Content-Disposition`` header. For example, +this is how you might return a Microsoft Excel spreadsheet:: + + >>> response = HttpResponse(my_data, mimetype='application/vnd.ms-excel') + >>> response['Content-Disposition'] = 'attachment; filename=foo.xls' + +There's nothing Django-specific about the ``Content-Disposition`` header, but +it's easy to forget the syntax, so we've included it here. + +Methods +------- + +.. method:: HttpResponse.__init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE) + + Instantiates an ``HttpResponse`` object with the given page content (a + string) and MIME type. The ``DEFAULT_CONTENT_TYPE`` is ``'text/html'``. + + ``content`` can be an iterator or a string. If it's an iterator, it should + return strings, and those strings will be joined together to form the + content of the response. + + ``status`` is the `HTTP Status code`_ for the response. + + **(New in Django development version)** ``content_type`` is an alias for + ``mimetype``. Historically, the parameter was only called ``mimetype``, + but since this is actually the value included in the HTTP ``Content-Type`` + header, it can also include the character set encoding, which makes it + more than just a MIME type specification. If ``mimetype`` is specified + (not ``None``), that value is used. Otherwise, ``content_type`` is used. If + neither is given, the ``DEFAULT_CONTENT_TYPE`` setting is used. + +.. method:: HttpResponse.__setitem__(header, value) + + Sets the given header name to the given value. Both ``header`` and + ``value`` should be strings. + +.. method:: HttpResponse.__delitem__(header) + + Deletes the header with the given name. Fails silently if the header + doesn't exist. Case-sensitive. + +.. method:: HttpResponse.__getitem__(header) + + Returns the value for the given header name. Case-sensitive. + +.. method:: HttpResponse.has_header(header) + + Returns ``True`` or ``False`` based on a case-insensitive check for a + header with the given name. + +.. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None) + + Sets a cookie. The parameters are the same as in the `cookie Morsel`_ + object in the Python standard library. + + * ``max_age`` should be a number of seconds, or ``None`` (default) if + the cookie should last only as long as the client's browser session. + * ``expires`` should be a string in the format + ``"Wdy, DD-Mon-YY HH:MM:SS GMT"``. + * Use ``domain`` if you want to set a cross-domain cookie. For example, + ``domain=".lawrence.com"`` will set a cookie that is readable by + the domains www.lawrence.com, blogs.lawrence.com and + calendars.lawrence.com. Otherwise, a cookie will only be readable by + the domain that set it. + + .. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html + +.. method:: HttpResponse.delete_cookie(key, path='/', domain=None) + + Deletes the cookie with the given key. Fails silently if the key doesn't + exist. + + Due to the way cookies work, ``path`` and ``domain`` should be the same + values you used in ``set_cookie()`` -- otherwise the cookie may not be + deleted. + +.. method:: HttpResponse.content() + + Returns the content as a Python string, encoding it from a Unicode object + if necessary. Note this is a property, not a method, so use ``r.content`` + instead of ``r.content()``. + +.. method:: HttpResponse.write(content) + + This method makes an :class:`HttpResponse` instance a file-like object. + +.. method:: HttpResponse.flush() + + This method makes an :class:`HttpResponse` instance a file-like object. + +.. method:: HttpResponse.tell() + + This method makes an :class:`HttpResponse` instance a file-like object. + +.. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 + + +HttpResponse subclasses +----------------------- + +Django includes a number of ``HttpResponse`` subclasses that handle different +types of HTTP responses. Like ``HttpResponse``, these subclasses live in +:mod:`django.http`. + +.. class:: HttpResponseRedirect + + The constructor takes a single argument -- the path to redirect to. This + can be a fully qualified URL (e.g. ``'http://www.yahoo.com/search/'``) or an + absolute URL with no domain (e.g. ``'/search/'``). Note that this returns + an HTTP status code 302. + +.. class:: HttpResponsePermanentRedirect + + Like :class:`HttpResponseRedirect`, but it returns a permanent redirect + (HTTP status code 301) instead of a "found" redirect (status code 302). + +.. class:: HttpResponseNotModified + + The constructor doesn't take any arguments. Use this to designate that a + page hasn't been modified since the user's last request (status code 304). + +.. class:: HttpResponseBadRequest + + **New in Django development version.** Acts just like :class:`HttpResponse` + but uses a 400 status code. + +.. class:: HttpResponseNotFound + + Acts just like :class:`HttpResponse` but uses a 404 status code. + +.. class:: HttpResponseForbidden + + Acts just like :class:`HttpResponse` but uses a 403 status code. + +.. class:: HttpResponseNotAllowed + + Like :class:`HttpResponse`, but uses a 405 status code. Takes a single, + required argument: a list of permitted methods (e.g. ``['GET', 'POST']``). + +.. class:: HttpResponseGone + + Acts just like :class:`HttpResponse` but uses a 410 status code. + +.. class:: HttpResponseServerError + + Acts just like :class:`HttpResponse` but uses a 500 status code. + diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt new file mode 100644 index 0000000000..72bd97c169 --- /dev/null +++ b/docs/ref/settings.txt @@ -0,0 +1,1177 @@ +.. _ref-settings: + +Available settings +================== + +Here's a full list of all available settings, in alphabetical order, and their +default values. + +.. setting:: ABSOLUTE_URL_OVERRIDES + +ABSOLUTE_URL_OVERRIDES +---------------------- + +Default: ``{}`` (Empty dictionary) + +A dictionary mapping ``"app_label.model_name"`` strings to functions that take +a model object and return its URL. This is a way of overriding +``get_absolute_url()`` methods on a per-installation basis. Example:: + + ABSOLUTE_URL_OVERRIDES = { + 'blogs.weblog': lambda o: "/blogs/%s/" % o.slug, + 'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug), + } + +Note that the model name used in this setting should be all lower-case, regardless +of the case of the actual model class name. + +.. setting:: ADMIN_FOR + +ADMIN_FOR +--------- + +Default: ``()`` (Empty tuple) + +Used for admin-site settings modules, this should be a tuple of settings +modules (in the format ``'foo.bar.baz'``) for which this site is an admin. + +The admin site uses this in its automatically-introspected documentation of +models, views and template tags. + +.. setting:: ADMIN_MEDIA_PREFIX + +ADMIN_MEDIA_PREFIX +------------------ + +Default: ``'/media/'`` + +The URL prefix for admin media -- CSS, JavaScript and images used by +the Django administrative interface. Make sure to use a trailing +slash, and to have this be different from the ``MEDIA_URL`` setting +(since the same URL cannot be mapped onto two different sets of +files). + +.. setting:: ADMINS + +ADMINS +------ + +Default: ``()`` (Empty tuple) + +A tuple that lists people who get code error notifications. When +``DEBUG=False`` and a view raises an exception, Django will e-mail these people +with the full exception information. Each member of the tuple should be a tuple +of (Full name, e-mail address). Example:: + + (('John', 'john@example.com'), ('Mary', 'mary@example.com')) + +Note that Django will e-mail *all* of these people whenever an error happens. +See :ref:`howto-error-reporting` for more information. + +.. setting:: ALLOWED_INCLUDE_ROOTS + +ALLOWED_INCLUDE_ROOTS +--------------------- + +Default: ``()`` (Empty tuple) + +A tuple of strings representing allowed prefixes for the ``{% ssi %}`` template +tag. This is a security measure, so that template authors can't access files +that they shouldn't be accessing. + +For example, if ``ALLOWED_INCLUDE_ROOTS`` is ``('/home/html', '/var/www')``, +then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}`` +wouldn't. + +.. setting:: APPEND_SLASH + +APPEND_SLASH +------------ + +Default: ``True`` + +Whether to append trailing slashes to URLs. This is only used if +``CommonMiddleware`` is installed (see :ref:`topics-http-middleware`). See also +``PREPEND_WWW``. + +.. setting:: AUTHENTICATION_BACKENDS + +AUTHENTICATION_BACKENDS +----------------------- + +Default: ``('django.contrib.auth.backends.ModelBackend',)`` + +A tuple of authentication backend classes (as strings) to use when attempting to +authenticate a user. See the :ref:`authentication backends documentation +<authentication-backends>` for details. + +.. setting:: AUTH_PROFILE_MODULE + +AUTH_PROFILE_MODULE +------------------- + +Default: Not defined + +The site-specific user profile model used by this site. See +:ref:`auth-profiles`. + +.. setting:: CACHE_BACKEND + +CACHE_BACKEND +------------- + +Default: ``'locmem://'`` + +The cache backend to use. See :ref:`topics-cache`. + +.. setting:: CACHE_MIDDLEWARE_KEY_PREFIX + +CACHE_MIDDLEWARE_KEY_PREFIX +--------------------------- + +Default: ``''`` (Empty string) + +The cache key prefix that the cache middleware should use. See +:ref:`topics-cache`. + +.. setting:: CACHE_MIDDLEWARE_SECONDS + +CACHE_MIDDLEWARE_SECONDS +------------------------ + +Default: ``600`` + +The default number of seconds to cache a page when the caching middleware or +``cache_page()`` decorator is used. + +.. setting:: DATABASE_ENGINE + +DATABASE_ENGINE +--------------- + +Default: ``''`` (Empty string) + +The database backend to use. The build-in database backends are +``'postgresql_psycopg2'``, ``'postgresql'``, ``'mysql'``, ``'sqlite3'``, and +``'oracle'``. + +In the Django development version, you can use a database backend that doesn't +ship with Django by setting ``DATABASE_ENGINE`` to a fully-qualified path (i.e. +``mypackage.backends.whatever``). Writing a whole new database backend from +scratch is left as an exercise to the reader; see the other backends for +examples. + +.. setting:: DATABASE_HOST + +DATABASE_HOST +------------- + +Default: ``''`` (Empty string) + +Which host to use when connecting to the database. An empty string means +localhost. Not used with SQLite. + +If this value starts with a forward slash (``'/'``) and you're using MySQL, +MySQL will connect via a Unix socket to the specified socket. For example:: + + DATABASE_HOST = '/var/run/mysql' + +If you're using MySQL and this value *doesn't* start with a forward slash, then +this value is assumed to be the host. + +If you're using PostgreSQL, an empty string means to use a Unix domain socket +for the connection, rather than a network connection to localhost. If you +explicitly need to use a TCP/IP connection on the local machine with +PostgreSQL, specify ``localhost`` here. + +.. setting:: DATABASE_NAME + +DATABASE_NAME +------------- + +Default: ``''`` (Empty string) + +The name of the database to use. For SQLite, it's the full path to the database +file. + +.. setting:: DATABASE_OPTIONS + +DATABASE_OPTIONS +---------------- + +Default: ``{}`` (Empty dictionary) + +Extra parameters to use when connecting to the database. Consult backend +module's document for available keywords. + +.. setting:: DATABASE_PASSWORD + +DATABASE_PASSWORD +----------------- + +Default: ``''`` (Empty string) + +The password to use when connecting to the database. Not used with SQLite. + +.. setting:: DATABASE_PORT + +DATABASE_PORT +------------- + +Default: ``''`` (Empty string) + +The port to use when connecting to the database. An empty string means the +default port. Not used with SQLite. + +.. setting:: DATABASE_USER + +DATABASE_USER +------------- + +Default: ``''`` (Empty string) + +The username to use when connecting to the database. Not used with SQLite. + +.. setting:: DATE_FORMAT + +DATE_FORMAT +----------- + +Default: ``'N j, Y'`` (e.g. ``Feb. 4, 2003``) + +The default formatting to use for date fields on Django admin change-list +pages -- and, possibly, by other parts of the system. See +:ttag:`allowed date format strings <now>`. + +See also ``DATETIME_FORMAT``, ``TIME_FORMAT``, ``YEAR_MONTH_FORMAT`` +and ``MONTH_DAY_FORMAT``. + +.. setting:: DATETIME_FORMAT + +DATETIME_FORMAT +--------------- + +Default: ``'N j, Y, P'`` (e.g. ``Feb. 4, 2003, 4 p.m.``) + +The default formatting to use for datetime fields on Django admin change-list +pages -- and, possibly, by other parts of the system. See +:ttag:`allowed date format strings <now>`. + +See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, +``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. + +.. setting:: DEBUG + +DEBUG +----- + +Default: ``False`` + +A boolean that turns on/off debug mode. + +If you define custom settings, django/views/debug.py has a ``HIDDEN_SETTINGS`` +regular expression which will hide from the DEBUG view anything that contains +``'SECRET'``, ``'PASSWORD'``, or ``'PROFANITIES'``. This allows untrusted users to +be able to give backtraces without seeing sensitive (or offensive) settings. + +Still, note that there are always going to be sections of your debug output that +are inappropriate for public consumption. File paths, configuration options, and +the like all give attackers extra information about your server. + +It is also important to remember that when running with ``DEBUG`` turned on, Django +will remember every SQL query it executes. This is useful when you are debugging, +but on a production server, it will rapidly consume memory. + +Never deploy a site into production with ``DEBUG`` turned on. + +DEBUG_PROPAGATE_EXCEPTIONS +-------------------------- + +**New in Django development version** + +Default: ``False`` + +If set to True, Django's normal exception handling of view functions +will be suppressed, and exceptions will propagate upwards. This can +be useful for some test setups, and should never be used on a live +site. + + +.. setting:: DEFAULT_CHARSET + +DEFAULT_CHARSET +--------------- + +Default: ``'utf-8'`` + +Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't +manually specified. Used with ``DEFAULT_CONTENT_TYPE`` to construct the +``Content-Type`` header. + +.. setting:: DEFAULT_CONTENT_TYPE + +DEFAULT_CONTENT_TYPE +-------------------- + +Default: ``'text/html'`` + +Default content type to use for all ``HttpResponse`` objects, if a MIME type +isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the +``Content-Type`` header. + +.. setting:: DEFAULT_FROM_EMAIL + +DEFAULT_FILE_STORAGE +-------------------- + +Default: ``django.core.files.storage.FileSystemStorage`` + +Default file storage class to be used for any file-related operations that don't +specify a particular storage system. See :ref:`topics-files`. + +DEFAULT_FROM_EMAIL +------------------ + +Default: ``'webmaster@localhost'`` + +Default e-mail address to use for various automated correspondence from the +site manager(s). + +.. setting:: DEFAULT_TABLESPACE + +DEFAULT_TABLESPACE +------------------ + +**New in Django development version** + +Default: ``''`` (Empty string) + +Default tablespace to use for models that don't specify one, if the +backend supports it. + +.. setting:: DEFAULT_INDEX_TABLESPACE + +DEFAULT_INDEX_TABLESPACE +------------------------ + +**New in Django development version** + +Default: ``''`` (Empty string) + +Default tablespace to use for indexes on fields that don't specify +one, if the backend supports it. + +.. setting:: DISALLOWED_USER_AGENTS + +DISALLOWED_USER_AGENTS +---------------------- + +Default: ``()`` (Empty tuple) + +List of compiled regular expression objects representing User-Agent strings that +are not allowed to visit any page, systemwide. Use this for bad robots/crawlers. +This is only used if ``CommonMiddleware`` is installed (see +:ref:`topics-http-middleware`). + +.. setting:: EMAIL_HOST + +EMAIL_HOST +---------- + +Default: ``'localhost'`` + +The host to use for sending e-mail. + +See also ``EMAIL_PORT``. + +.. setting:: EMAIL_HOST_PASSWORD + +EMAIL_HOST_PASSWORD +------------------- + +Default: ``''`` (Empty string) + +Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is +used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP +server. If either of these settings is empty, Django won't attempt +authentication. + +See also ``EMAIL_HOST_USER``. + +.. setting:: EMAIL_HOST_USER + +EMAIL_HOST_USER +--------------- + +Default: ``''`` (Empty string) + +Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty, +Django won't attempt authentication. + +See also ``EMAIL_HOST_PASSWORD``. + +.. setting:: EMAIL_PORT + +EMAIL_PORT +---------- + +Default: ``25`` + +Port to use for the SMTP server defined in ``EMAIL_HOST``. + +.. setting:: EMAIL_SUBJECT_PREFIX + +EMAIL_SUBJECT_PREFIX +-------------------- + +Default: ``'[Django] '`` + +Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins`` +or ``django.core.mail.mail_managers``. You'll probably want to include the +trailing space. + +.. setting:: EMAIL_USE_TLS + +EMAIL_USE_TLS +------------- + +**New in Django development version** + +Default: ``False`` + +Whether to use a TLS (secure) connection when talking to the SMTP server. + +.. setting:: FILE_CHARSET + +FILE_CHARSET +------------ + +**New in Django development version** + +Default: ``'utf-8'`` + +The character encoding used to decode any files read from disk. This includes +template files and initial SQL data files. + +FILE_UPLOAD_HANDLERS +-------------------- + +**New in Django development version** + +Default:: + + ("django.core.files.uploadhandler.MemoryFileUploadHandler", + "django.core.files.uploadhandler.TemporaryFileUploadHandler",) + +A tuple of handlers to use for uploading. See :ref:`topics-files` for details. + +FILE_UPLOAD_MAX_MEMORY_SIZE +--------------------------- + +**New in Django development version** + +Default: ``2621440`` (i.e. 2.5 MB). + +The maximum size (in bytes) that an upload will be before it gets streamed to +the file system. See :ref:`topics-files` for details. + +FILE_UPLOAD_TEMP_DIR +-------------------- + +**New in Django development version** + +Default: ``None`` + +The directory to store data temporarily while uploading files. If ``None``, +Django will use the standard temporary directory for the operating system. For +example, this will default to '/tmp' on \*nix-style operating systems. + +See :ref:`topics-files` for details. + +.. setting:: FIXTURE_DIRS + +FIXTURE_DIRS +------------- + +Default: ``()`` (Empty tuple) + +List of locations of the fixture data files, in search order. Note that +these paths should use Unix-style forward slashes, even on Windows. See +:ref:`topics-testing`. + +FORCE_SCRIPT_NAME +------------------ + +Default: ``None`` + +If not ``None``, this will be used as the value of the ``SCRIPT_NAME`` +environment variable in any HTTP request. This setting can be used to override +the server-provided value of ``SCRIPT_NAME``, which may be a rewritten version +of the preferred value or not supplied at all. + +.. setting:: IGNORABLE_404_ENDS + +IGNORABLE_404_ENDS +------------------ + +Default: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')`` + +See also ``IGNORABLE_404_STARTS`` and ``Error reporting via e-mail``. + +.. setting:: IGNORABLE_404_STARTS + +IGNORABLE_404_STARTS +-------------------- + +Default: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')`` + +A tuple of strings that specify beginnings of URLs that should be ignored by +the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS``, ``IGNORABLE_404_ENDS`` and +the :ref:`howto-error-reporting`. + +.. setting:: INSTALLED_APPS + +INSTALLED_APPS +-------------- + +Default: ``()`` (Empty tuple) + +A tuple of strings designating all applications that are enabled in this Django +installation. Each string should be a full Python path to a Python package that +contains a Django application, as created by :djadmin:`django-admin.py startapp +<startapp>`. + +.. setting:: INTERNAL_IPS + +INTERNAL_IPS +------------ + +Default: ``()`` (Empty tuple) + +A tuple of IP addresses, as strings, that: + + * See debug comments, when ``DEBUG`` is ``True`` + * Receive X headers if the ``XViewMiddleware`` is installed (see + :ref:`topics-http-middleware`) + +.. setting:: JING_PATH + +JING_PATH +--------- + +Default: ``'/usr/bin/jing'`` + +Path to the "Jing" executable. Jing is a RELAX NG validator, and Django uses it +to validate each ``XMLField`` in your models. +See http://www.thaiopensource.com/relaxng/jing.html . + +.. setting:: LANGUAGE_CODE + +LANGUAGE_CODE +------------- + +Default: ``'en-us'`` + +A string representing the language code for this installation. This should be in +standard language format. For example, U.S. English is ``"en-us"``. See +:ref:`topics-i18n`. + +.. setting:: LANGUAGE_COOKIE_NAME + +LANGUAGE_COOKIE_NAME +-------------------- + +**New in Django development version** + +Default: ``'django_language'`` + +The name of the cookie to use for the language cookie. This can be whatever you +want (but should be different from ``SESSION_COOKIE_NAME``). See +:ref:`topics-i18n`. + +.. setting:: LANGUAGES + +LANGUAGES +--------- + +Default: A tuple of all available languages. This list is continually growing +and including a copy here would inevitably become rapidly out of date. You can +see the current list of translated languages by looking in +``django/conf/global_settings.py`` (or view the `online source`_). + +.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py + +The list is a tuple of two-tuples in the format (language code, language +name) -- for example, ``('ja', 'Japanese')``. This specifies which languages +are available for language selection. See :ref:`topics-i18n`. + +Generally, the default value should suffice. Only set this setting if you want +to restrict language selection to a subset of the Django-provided languages. + +If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as +translation strings (as in the default value displayed above) -- but use a +"dummy" ``gettext()`` function, not the one in ``django.utils.translation``. +You should *never* import ``django.utils.translation`` from within your +settings file, because that module in itself depends on the settings, and that +would cause a circular import. + +The solution is to use a "dummy" ``gettext()`` function. Here's a sample +settings file:: + + gettext = lambda s: s + + LANGUAGES = ( + ('de', gettext('German')), + ('en', gettext('English')), + ) + +With this arrangement, ``django-admin.py makemessages`` will still find and +mark these strings for translation, but the translation won't happen at +runtime -- so you'll have to remember to wrap the languages in the *real* +``gettext()`` in any code that uses ``LANGUAGES`` at runtime. + +.. setting:: LOCALE_PATHS + +LOCALE_PATHS +------------ + +Default: ``()`` (Empty tuple) + +A tuple of directories where Django looks for translation files. +See :ref:`translations-in-your-own-projects`. + +.. setting:: LOGIN_REDIRECT_URL + +LOGIN_REDIRECT_URL +------------------ + +**New in Django development version** + +Default: ``'/accounts/profile/'`` + +The URL where requests are redirected after login when the +``contrib.auth.login`` view gets no ``next`` parameter. + +This is used by the :func:`~django.contrib.auth.decorators.login_required` +decorator, for example. + +.. setting:: LOGIN_URL + +LOGIN_URL +--------- + +**New in Django development version** + +Default: ``'/accounts/login/'`` + +The URL where requests are redirected for login, specially when using the +:func:`~django.contrib.auth.decorators.login_required` decorator. + +.. setting:: LOGOUT_URL + +LOGOUT_URL +---------- + +**New in Django development version** + +Default: ``'/accounts/logout/'`` + +LOGIN_URL counterpart. + +.. setting:: MANAGERS + +MANAGERS +-------- + +Default: ``()`` (Empty tuple) + +A tuple in the same format as ``ADMINS`` that specifies who should get +broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``. + +.. setting:: MEDIA_ROOT + +MEDIA_ROOT +---------- + +Default: ``''`` (Empty string) + +Absolute path to the directory that holds media for this installation. +Example: ``"/home/media/media.lawrence.com/"`` See also ``MEDIA_URL``. + +.. setting:: MEDIA_URL + +MEDIA_URL +--------- + +Default: ``''`` (Empty string) + +URL that handles the media served from ``MEDIA_ROOT``. +Example: ``"http://media.lawrence.com"`` + +Note that this should have a trailing slash if it has a path component. + +Good: ``"http://www.example.com/static/"`` +Bad: ``"http://www.example.com/static"`` + +.. setting:: MIDDLEWARE_CLASSES + +MIDDLEWARE_CLASSES +------------------ + +Default:: + + ("django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.doc.XViewMiddleware") + +A tuple of middleware classes to use. See :ref:`topics-http-middleware`. + +.. setting:: MONTH_DAY_FORMAT + +MONTH_DAY_FORMAT +---------------- + +Default: ``'F j'`` + +The default formatting to use for date fields on Django admin change-list +pages -- and, possibly, by other parts of the system -- in cases when only the +month and day are displayed. + +For example, when a Django admin change-list page is being filtered by a date +drilldown, the header for a given day displays the day and month. Different +locales have different formats. For example, U.S. English would say +"January 1," whereas Spanish might say "1 Enero." + +See :ttag:`allowed date format strings <now>`. See also ``DATE_FORMAT``, +``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``YEAR_MONTH_FORMAT``. + +.. setting:: PREPEND_WWW + +PREPEND_WWW +----------- + +Default: ``False`` + +Whether to prepend the "www." subdomain to URLs that don't have it. This is only +used if ``CommonMiddleware`` is installed (see :ref:`topics-http-middleware`). +See also ``APPEND_SLASH``. + +.. setting:: PROFANITIES_LIST + +PROFANITIES_LIST +---------------- + +A tuple of profanities, as strings, that will trigger a validation error when +the ``hasNoProfanities`` validator is called. + +We don't list the default values here, because that would be profane. To see +the default values, see the file ``django/conf/global_settings.py``. + +.. setting:: ROOT_URLCONF + +ROOT_URLCONF +------------ + +Default: Not defined + +A string representing the full Python import path to your root URLconf. For example: +``"mydjangoapps.urls"``. Can be overridden on a per-request basis by +setting the attribute ``urlconf`` on the incoming ``HttpRequest`` +object. See :ref:`how-django-processes-a-request` for details. + +.. setting:: SECRET_KEY + +SECRET_KEY +---------- + +Default: ``''`` (Empty string) + +A secret key for this particular Django installation. Used to provide a seed in +secret-key hashing algorithms. Set this to a random string -- the longer, the +better. ``django-admin.py startproject`` creates one automatically. + +.. setting:: SEND_BROKEN_LINK_EMAILS + +SEND_BROKEN_LINK_EMAILS +----------------------- + +Default: ``False`` + +Whether to send an e-mail to the ``MANAGERS`` each time somebody visits a +Django-powered page that is 404ed with a non-empty referer (i.e., a broken +link). This is only used if ``CommonMiddleware`` is installed (see +:ref:`topics-http-middleware`. See also ``IGNORABLE_404_STARTS``, +``IGNORABLE_404_ENDS`` and :ref:`howto-error-reporting`. + +.. setting:: SERIALIZATION_MODULES + +SERIALIZATION_MODULES +--------------------- + +Default: Not defined. + +A dictionary of modules containing serializer definitions (provided as +strings), keyed by a string identifier for that serialization type. For +example, to define a YAML serializer, use:: + + SERIALIZATION_MODULES = { 'yaml' : 'path.to.yaml_serializer' } + +.. setting:: SERVER_EMAIL + +SERVER_EMAIL +------------ + +Default: ``'root@localhost'`` + +The e-mail address that error messages come from, such as those sent to +``ADMINS`` and ``MANAGERS``. + +.. setting:: SESSION_ENGINE + +SESSION_ENGINE +-------------- + +**New in Django development version** + +Default: ``django.contrib.sessions.backends.db`` + +Controls where Django stores session data. Valid values are: + + * ``'django.contrib.sessions.backends.db'`` + * ``'django.contrib.sessions.backends.file'`` + * ``'django.contrib.sessions.backends.cache'`` + +See :ref:`topics-http-sessions`. + +.. setting:: SESSION_COOKIE_AGE + +SESSION_COOKIE_AGE +------------------ + +Default: ``1209600`` (2 weeks, in seconds) + +The age of session cookies, in seconds. See :ref:`topics-http-sessions`. + +.. setting:: SESSION_COOKIE_DOMAIN + +SESSION_COOKIE_DOMAIN +--------------------- + +Default: ``None`` + +The domain to use for session cookies. Set this to a string such as +``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard +domain cookie. See the :ref:`topics-http-sessions`. + +.. setting:: SESSION_COOKIE_NAME + +SESSION_COOKIE_NAME +------------------- + +Default: ``'sessionid'`` + +The name of the cookie to use for sessions. This can be whatever you want (but +should be different from ``LANGUAGE_COOKIE_NAME``). See the :ref:`topics-http-sessions`. + +.. setting:: SESSION_COOKIE_PATH + +SESSION_COOKIE_PATH +------------------- + +**New in Django development version** + +Default: ``'/'`` + +The path set on the session cookie. This should either match the URL path of your +Django installation or be parent of that path. + +This is useful if you have multiple Django instances running under the same +hostname. They can use different cookie paths, and each instance will only see +its own session cookie. + +.. setting:: SESSION_COOKIE_SECURE + +SESSION_COOKIE_SECURE +--------------------- + +Default: ``False`` + +Whether to use a secure cookie for the session cookie. If this is set to +``True``, the cookie will be marked as "secure," which means browsers may +ensure that the cookie is only sent under an HTTPS connection. +See the :ref:`topics-http-sessions`. + +.. setting:: SESSION_EXPIRE_AT_BROWSER_CLOSE + +SESSION_EXPIRE_AT_BROWSER_CLOSE +------------------------------- + +Default: ``False`` + +Whether to expire the session when the user closes his or her browser. +See the :ref:`topics-http-sessions`. + +.. setting:: SESSION_FILE_PATH + +SESSION_FILE_PATH +----------------- + +**New in Django development version** + +Default: ``/tmp/`` + +If you're using file-based session storage, this sets the directory in +which Django will store session data. See :ref:`topics-http-sessions`. + +.. setting:: SESSION_SAVE_EVERY_REQUEST + +SESSION_SAVE_EVERY_REQUEST +-------------------------- + +Default: ``False`` + +Whether to save the session data on every request. See +:ref:`topics-http-sessions`. + +.. setting:: SITE_ID + +SITE_ID +------- + +Default: Not defined + +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 :ref:`ref-contrib-sites`. + +.. _site framework docs: ../sites/ + +.. setting:: TEMPLATE_CONTEXT_PROCESSORS + +TEMPLATE_CONTEXT_PROCESSORS +--------------------------- + +Default:: + + ("django.core.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media") + +A tuple of callables that are used to populate the context in ``RequestContext``. +These callables take a request object as their argument and return a dictionary +of items to be merged into the context. + +.. setting:: TEMPLATE_DEBUG + +TEMPLATE_DEBUG +-------------- + +Default: ``False`` + +A boolean that turns on/off template debug mode. If this is ``True``, the fancy +error page will display a detailed report for any ``TemplateSyntaxError``. This +report contains the relevant snippet of the template, with the appropriate line +highlighted. + +Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so +you'll want to set that to take advantage of this setting. + +See also ``DEBUG``. + +.. setting:: TEMPLATE_DIRS + +TEMPLATE_DIRS +------------- + +Default: ``()`` (Empty tuple) + +List of locations of the template source files, in search order. Note that +these paths should use Unix-style forward slashes, even on Windows. + +See :ref:`topics-templates`.. + +.. setting:: TEMPLATE_LOADERS + +TEMPLATE_LOADERS +---------------- + +Default: + + ('django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source') + +A tuple of callables (as strings) that know how to import templates from +various sources. See :ref:`ref-templates-api`. + +.. setting:: TEMPLATE_STRING_IF_INVALID + +TEMPLATE_STRING_IF_INVALID +-------------------------- + +Default: ``''`` (Empty string) + +Output, as a string, that the template system should use for invalid (e.g. +misspelled) variables. See :ref:`invalid-template-variables`.. + +.. setting:: TEST_DATABASE_CHARSET + +TEST_DATABASE_CHARSET +--------------------- + +**New in Django development version** + +Default: ``None`` + +The character set encoding used to create the test database. The value of this +string is passed directly through to the database, so its format is +backend-specific. + +Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and MySQL_ (``mysql``) backends. + +.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html +.. _MySQL: http://www.mysql.org/doc/refman/5.0/en/charset-database.html + +.. setting:: TEST_DATABASE_COLLATION + +TEST_DATABASE_COLLATION +------------------------ + +**New in Django development version** + +Default: ``None`` + +The collation order to use when creating the test database. This value is +passed directly to the backend, so its format is backend-specific. + +Only supported for the ``mysql`` backend (see `section 10.3.2`_ of the MySQL +manual for details). + +.. _section 10.3.2: http://www.mysql.org/doc/refman/5.0/en/charset-database.html + +.. setting:: TEST_DATABASE_NAME + +TEST_DATABASE_NAME +------------------ + +Default: ``None`` + +The name of database to use when running the test suite. + +If the default value (``None``) is used with the SQLite database engine, the +tests will use a memory resident database. For all other database engines the +test database will use the name ``'test_' + settings.DATABASE_NAME``. + +See :ref:`topics-testing`. + +.. setting:: TEST_RUNNER + +TEST_RUNNER +----------- + +Default: ``'django.test.simple.run_tests'`` + +The name of the method to use for starting the test suite. See +:ref:`topics-testing`. + +.. _Testing Django Applications: ../testing/ + +.. setting:: TIME_FORMAT + +TIME_FORMAT +----------- + +Default: ``'P'`` (e.g. ``4 p.m.``) + +The default formatting to use for time fields on Django admin change-list +pages -- and, possibly, by other parts of the system. See +:ttag:`allowed date format strings <now>`. + +See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, +``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. + +.. setting:: TIME_ZONE + +TIME_ZONE +--------- + +Default: ``'America/Chicago'`` + +A string representing the time zone for this installation. `See available choices`_. +(Note that list of available choices lists more than one on the same line; +you'll want to use just one of the choices for a given time zone. For instance, +one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit +of that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.) + +Note that this is the time zone to which Django will convert all dates/times -- +not necessarily the timezone of the server. For example, one server may serve +multiple Django-powered sites, each with a separate time-zone setting. + +Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you +specify in the ``TIME_ZONE`` setting. Thus, all your views and models will +automatically operate in the correct time zone. However, if you're using the +manual configuration option (see below), Django will *not* touch the ``TZ`` +environment variable, and it'll be up to you to ensure your processes are +running in the correct environment. + +.. note:: + Django cannot reliably use alternate time zones in a Windows environment. + If you're running Django on Windows, this variable must be set to match the + system timezone. + +.. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE + +.. setting:: URL_VALIDATOR_USER_AGENT + +URL_VALIDATOR_USER_AGENT +------------------------ + +Default: ``Django/<version> (http://www.djangoproject.com/)`` + +The string to use as the ``User-Agent`` header when checking to see if URLs +exist (see the ``verify_exists`` option on :class:`~django.db.models.URLField`). + +.. setting:: USE_ETAGS + +USE_ETAGS +--------- + +Default: ``False`` + +A boolean that specifies whether to output the "Etag" header. This saves +bandwidth but slows down performance. This is only used if ``CommonMiddleware`` +is installed (see :ref:`topics-http-middleware`). + +.. setting:: USE_I18N + +USE_I18N +-------- + +Default: ``True`` + +A boolean that specifies whether Django's internationalization system should be +enabled. This provides an easy way to turn it off, for performance. If this is +set to ``False``, Django will make some optimizations so as not to load the +internationalization machinery. + +.. setting:: YEAR_MONTH_FORMAT + +YEAR_MONTH_FORMAT +----------------- + +Default: ``'F Y'`` + +The default formatting to use for date fields on Django admin change-list +pages -- and, possibly, by other parts of the system -- in cases when only the +year and month are displayed. + +For example, when a Django admin change-list page is being filtered by a date +drilldown, the header for a given month displays the month and the year. +Different locales have different formats. For example, U.S. English would say +"January 2006," whereas another locale might say "2006/January." + +See :ttag:`allowed date format strings <now>`. See also ``DATE_FORMAT``, +``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``MONTH_DAY_FORMAT``. diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt new file mode 100644 index 0000000000..c78f130972 --- /dev/null +++ b/docs/ref/templates/api.txt @@ -0,0 +1,612 @@ +.. _ref-templates-api: + +==================================================== +The Django template language: For Python programmers +==================================================== + +This document explains the Django template system from a technical +perspective -- how it works and how to extend it. If you're just looking for +reference on the language syntax, see :ref:`topics-templates`. + +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. + +.. _configuration: `configuring the template system in standalone mode`_ + +Basics +====== + +A **template** is a text document, or a normal Python string, that is marked-up +using the Django template language. A template can contain **block tags** or +**variables**. + +A **block tag** is a symbol within a template that does something. + +This definition is deliberately vague. For example, a block tag can output +content, serve as a control structure (an "if" statement or "for" loop), grab +content from a database or enable access to other template tags. + +Block tags are surrounded by ``"{%"`` and ``"%}"``. + +Example template with block tags:: + + {% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %} + +A **variable** is a symbol within a template that outputs a value. + +Variable tags are surrounded by ``"{{"`` and ``"}}"``. + +Example template with variables:: + + My first name is {{ first_name }}. My last name is {{ last_name }}. + +A **context** is a "variable name" -> "variable value" mapping that is passed +to a template. + +A template **renders** a context by replacing the variable "holes" with values +from the context and executing all block tags. + +Using the template system +========================= + +Using the template system in Python is a two-step process: + + * First, you compile the raw template code into a ``Template`` object. + * Then, you call the ``render()`` method of the ``Template`` object with a + given context. + +Compiling a string +------------------ + +The easiest way to create a ``Template`` object is by instantiating it +directly. The class lives at ``django.template.Template``. The constructor +takes one argument -- the raw template code:: + + >>> from django.template import Template + >>> t = Template("My name is {{ my_name }}.") + >>> print t + <django.template.Template instance> + +.. admonition:: Behind the scenes + + The system only parses your raw template code once -- when you create the + ``Template`` object. From then on, it's stored internally as a "node" + structure for performance. + + Even the parsing itself is quite fast. Most of the parsing happens via a + single call to a single, short, regular expression. + +Rendering a context +------------------- + +Once you have a compiled ``Template`` object, you can render a context -- or +multiple contexts -- with it. The ``Context`` class lives at +``django.template.Context``, and the constructor takes one (optional) +argument: a dictionary mapping variable names to variable values. Call the +``Template`` object's ``render()`` method with the context to "fill" the +template:: + + >>> from django.template import Context, Template + >>> t = Template("My name is {{ my_name }}.") + + >>> c = Context({"my_name": "Adrian"}) + >>> t.render(c) + "My name is Adrian." + + >>> c = Context({"my_name": "Dolores"}) + >>> t.render(c) + "My name is Dolores." + +Variable names must consist of any letter (A-Z), any digit (0-9), an underscore +or a dot. + +Dots have a special meaning in template rendering. A dot in a variable name +signifies **lookup**. Specifically, when the template system encounters a dot +in a variable name, it tries the following lookups, in this order: + + * Dictionary lookup. Example: ``foo["bar"]`` + * Attribute lookup. Example: ``foo.bar`` + * Method call. Example: ``foo.bar()`` + * List-index lookup. Example: ``foo[bar]`` + +The template system uses the first lookup type that works. It's short-circuit +logic. + +Here are a few examples:: + + >>> from django.template import Context, Template + >>> t = Template("My name is {{ person.first_name }}.") + >>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}} + >>> t.render(Context(d)) + "My name is Joe." + + >>> class PersonClass: pass + >>> p = PersonClass() + >>> p.first_name = "Ron" + >>> p.last_name = "Nasty" + >>> t.render(Context({"person": p})) + "My name is Ron." + + >>> class PersonClass2: + ... def first_name(self): + ... return "Samantha" + >>> p = PersonClass2() + >>> t.render(Context({"person": p})) + "My name is Samantha." + + >>> t = Template("The first stooge in the list is {{ stooges.0 }}.") + >>> c = Context({"stooges": ["Larry", "Curly", "Moe"]}) + >>> t.render(c) + "The first stooge in the list is Larry." + +Method lookups are slightly more complex than the other lookup types. Here are +some things to keep in mind: + + * If, during the method lookup, a method raises an exception, the exception + will be propagated, unless the exception has an attribute + ``silent_variable_failure`` whose value is ``True``. If the exception + *does* have a ``silent_variable_failure`` attribute, the variable will + render as an empty string. Example:: + + >>> t = Template("My name is {{ person.first_name }}.") + >>> class PersonClass3: + ... def first_name(self): + ... raise AssertionError, "foo" + >>> p = PersonClass3() + >>> t.render(Context({"person": p})) + Traceback (most recent call last): + ... + AssertionError: foo + + >>> class SilentAssertionError(Exception): + ... silent_variable_failure = True + >>> class PersonClass4: + ... def first_name(self): + ... raise SilentAssertionError + >>> p = PersonClass4() + >>> t.render(Context({"person": p})) + "My name is ." + + Note that ``django.core.exceptions.ObjectDoesNotExist``, which is the + base class for all Django database API ``DoesNotExist`` exceptions, has + ``silent_variable_failure = True``. So if you're using Django templates + with Django model objects, any ``DoesNotExist`` exception will fail + silently. + + * A method call will only work if the method has no required arguments. + Otherwise, the system will move to the next lookup type (list-index + lookup). + + * Obviously, some methods have side effects, and it'd be either foolish or + a security hole to allow the template system to access them. + + A good example is the ``delete()`` method on each Django model object. + The template system shouldn't be allowed to do something like this:: + + I will now delete this valuable data. {{ data.delete }} + + To prevent this, set a function attribute ``alters_data`` on the method. + The template system won't execute a method if the method has + ``alters_data=True`` set. The dynamically-generated ``delete()`` and + ``save()`` methods on Django model objects get ``alters_data=True`` + automatically. Example:: + + def sensitive_function(self): + self.database_record.delete() + sensitive_function.alters_data = True + +.. _invalid-template-variables: + +How invalid variables are handled +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Generally, if a variable doesn't exist, the template system inserts the +value of the :setting:`TEMPLATE_STRING_IF_INVALID` setting, which is set to +``''`` (the empty string) by default. + +Filters that are applied to an invalid variable will only be applied if +:setting:`TEMPLATE_STRING_IF_INVALID` is set to ``''`` (the empty string). If +:setting:`TEMPLATE_STRING_IF_INVALID` is set to any other value, variable +filters will be ignored. + +This behavior is slightly different for the ``if``, ``for`` and ``regroup`` +template tags. If an invalid variable is provided to one of these template +tags, the variable will be interpreted as ``None``. Filters are always +applied to invalid variables within these template tags. + +If :setting:`TEMPLATE_STRING_IF_INVALID` contains a ``'%s'``, the format marker will +be replaced with the name of the invalid variable. + +.. admonition:: For debug purposes only! + + While :setting:`TEMPLATE_STRING_IF_INVALID` can be a useful debugging tool, + it is a bad idea to turn it on as a 'development default'. + + Many templates, including those in the Admin site, rely upon the + silence of the template system when a non-existent variable is + encountered. If you assign a value other than ``''`` to + :setting:`TEMPLATE_STRING_IF_INVALID`, you will experience rendering + problems with these templates and sites. + + Generally, :setting:`TEMPLATE_STRING_IF_INVALID` should only be enabled + in order to debug a specific template problem, then cleared + once debugging is complete. + +Playing with Context objects +---------------------------- + +Most of the time, you'll instantiate ``Context`` objects by passing in a +fully-populated dictionary to ``Context()``. But you can add and delete items +from a ``Context`` object once it's been instantiated, too, using standard +dictionary syntax:: + + >>> c = Context({"foo": "bar"}) + >>> c['foo'] + 'bar' + >>> del c['foo'] + >>> c['foo'] + '' + >>> c['newvariable'] = 'hello' + >>> c['newvariable'] + 'hello' + +A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it. +If you ``pop()`` too much, it'll raise +``django.template.ContextPopException``:: + + >>> c = Context() + >>> c['foo'] = 'first level' + >>> c.push() + >>> c['foo'] = 'second level' + >>> c['foo'] + 'second level' + >>> c.pop() + >>> c['foo'] + 'first level' + >>> c['foo'] = 'overwritten' + >>> c['foo'] + 'overwritten' + >>> c.pop() + Traceback (most recent call last): + ... + django.template.ContextPopException + +Using a ``Context`` as a stack comes in handy in some custom template tags, as +you'll see below. + +.. _subclassing-context-requestcontext: + +Subclassing Context: RequestContext +----------------------------------- + +Django comes with a special ``Context`` class, +``django.template.RequestContext``, that acts slightly differently than the +normal ``django.template.Context``. The first difference is that it takes an +:class:`~django.http.HttpRequest` as its first argument. For example:: + + c = RequestContext(request, { + 'foo': 'bar', + } + +The second difference is that it automatically populates the context with a few +variables, according to your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting`. + +The :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting is a tuple of callables -- +called **context processors** -- that take a request object as their argument +and return a dictionary of items to be merged into the context. By default, +:setting:`TEMPLATE_CONTEXT_PROCESSORS` is set to:: + + ("django.core.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media") + +Each processor is applied in order. That means, if one processor adds a +variable to the context and a second processor adds a variable with the same +name, the second will override the first. The default processors are explained +below. + +Also, you can give ``RequestContext`` a list of additional processors, using the +optional, third positional argument, ``processors``. In this example, the +``RequestContext`` instance gets a ``ip_address`` variable:: + + def ip_address_processor(request): + return {'ip_address': request.META['REMOTE_ADDR']} + + def some_view(request): + # ... + c = RequestContext(request, { + 'foo': 'bar', + }, [ip_address_processor]) + return t.render(c) + +.. note:: + If you're using Django's ``render_to_response()`` shortcut to populate a + template with the contents of a dictionary, your template will be passed a + ``Context`` instance by default (not a ``RequestContext``). To use a + ``RequestContext`` in your template rendering, pass an optional third + argument to ``render_to_response()``: a ``RequestContext`` + instance. Your code might look like this:: + + def some_view(request): + # ... + return render_to_response('my_template.html', + my_data_dictionary, + context_instance=RequestContext(request)) + +Here's what each of the default processors does: + +django.core.context_processors.auth +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every +``RequestContext`` will contain these three variables: + + * ``user`` -- An ``auth.User`` instance representing the currently + logged-in user (or an ``AnonymousUser`` instance, if the client isn't + logged in). + + * ``messages`` -- A list of messages (as strings) for the currently + logged-in user. Behind the scenes, this calls + ``request.user.get_and_delete_messages()`` for every request. That method + collects the user's messages and deletes them from the database. + + Note that messages are set with ``user.message_set.create``. + + * ``perms`` -- An instance of + ``django.core.context_processors.PermWrapper``, representing the + permissions that the currently logged-in user has. + +django.core.context_processors.debug +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every +``RequestContext`` will contain these two variables -- but only if your +:setting:`DEBUG` setting is set to ``True`` and the request's IP address +(``request.META['REMOTE_ADDR']``) is in the :setting:`INTERNAL_IPS` setting: + + * ``debug`` -- ``True``. You can use this in templates to test whether + you're in :setting:`DEBUG` mode. + * ``sql_queries`` -- A list of ``{'sql': ..., 'time': ...}`` dictionaries, + representing every SQL query that has happened so far during the request + and how long it took. The list is in order by query. + +django.core.context_processors.i18n +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every +``RequestContext`` will contain these two variables: + + * ``LANGUAGES`` -- The value of the :setting:`LANGUAGES` setting. + * ``LANGUAGE_CODE`` -- ``request.LANGUAGE_CODE``, if it exists. Otherwise, + the value of the :setting:`LANGUAGE_CODE` setting`. + +See :ref:`topics-i18n` for more. + +django.core.context_processors.media +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**New in Django development version** + +If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every +``RequestContext`` will contain a variable ``MEDIA_URL``, providing the +value of the :setting:`MEDIA_URL` setting. + +django.core.context_processors.request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every +``RequestContext`` will contain a variable ``request``, which is the current +:class:`~django.http.HttpRequest`. Note that this processor is not enabled by default; +you'll have to activate it. + +Writing your own context processors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A context processor has a very simple interface: It's just a Python function +that takes one argument, an ``HttpRequest`` object, and returns a dictionary +that gets added to the template context. Each context processor *must* return +a dictionary. + +Custom context processors can live anywhere in your code base. All Django cares +about is that your custom context processors are pointed-to by your +:setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. + +Loading templates +----------------- + +Generally, you'll store templates in files on your filesystem rather than using +the low-level ``Template`` API yourself. Save templates in a directory +specified as a **template directory**. + +Django searches for template directories in a number of places, depending on +your template-loader settings (see "Loader types" below), but the most basic +way of specifying template directories is by using the :setting:`TEMPLATE_DIRS` +setting. + +The TEMPLATE_DIRS setting +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tell Django what your template directories are by using the +:setting:`TEMPLATE_DIRS` setting in your settings file. This should be set to a +list or tuple of strings that contain full paths to your template +directory(ies). Example:: + + TEMPLATE_DIRS = ( + "/home/html/templates/lawrence.com", + "/home/html/templates/default", + ) + +Your templates can go anywhere you want, as long as the directories and +templates are readable by the Web server. They can have any extension you want, +such as ``.html`` or ``.txt``, or they can have no extension at all. + +Note that these paths should use Unix-style forward slashes, even on Windows. + +.. _ref-templates-api-the-python-api: + +The Python API +~~~~~~~~~~~~~~ + +Django has two ways to load templates from files: + +``django.template.loader.get_template(template_name)`` + ``get_template`` returns the compiled template (a ``Template`` object) for + the template with the given name. If the template doesn't exist, it raises + ``django.template.TemplateDoesNotExist``. + +``django.template.loader.select_template(template_name_list)`` + ``select_template`` is just like ``get_template``, except it takes a list + of template names. Of the list, it returns the first template that exists. + +For example, if you call ``get_template('story_detail.html')`` and have the +above :setting:`TEMPLATE_DIRS` setting, here are the files Django will look for, +in order: + + * ``/home/html/templates/lawrence.com/story_detail.html`` + * ``/home/html/templates/default/story_detail.html`` + +If you call ``select_template(['story_253_detail.html', 'story_detail.html'])``, +here's what Django will look for: + + * ``/home/html/templates/lawrence.com/story_253_detail.html`` + * ``/home/html/templates/default/story_253_detail.html`` + * ``/home/html/templates/lawrence.com/story_detail.html`` + * ``/home/html/templates/default/story_detail.html`` + +When Django finds a template that exists, it stops looking. + +.. admonition:: Tip + + You can use ``select_template()`` for super-flexible "templatability." For + example, if you've written a news story and want some stories to have + custom templates, use something like + ``select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])``. + That'll allow you to use a custom template for an individual story, with a + fallback template for stories that don't have custom templates. + +Using subdirectories +~~~~~~~~~~~~~~~~~~~~ + +It's possible -- and preferable -- to organize templates in subdirectories of +the template directory. The convention is to make a subdirectory for each +Django app, with subdirectories within those subdirectories as needed. + +Do this for your own sanity. Storing all templates in the root level of a +single directory gets messy. + +To load a template that's within a subdirectory, just use a slash, like so:: + + get_template('news/story_detail.html') + +Using the same :setting:`TEMPLATE_DIRS` setting from above, this example +``get_template()`` call will attempt to load the following templates: + + * ``/home/html/templates/lawrence.com/news/story_detail.html`` + * ``/home/html/templates/default/news/story_detail.html`` + +.. _template-loaders: + +Loader types +~~~~~~~~~~~~ + +By default, Django uses a filesystem-based template loader, but Django comes +with a few other template loaders, which know how to load templates from other +sources. + +These other loaders are disabled by default, but you can activate them by +editing your :setting:`TEMPLATE_LOADERS` setting. :setting:`TEMPLATE_LOADERS` +should be a tuple of strings, where each string represents a template loader. +Here are the template loaders that come with Django: + +``django.template.loaders.filesystem.load_template_source`` + Loads templates from the filesystem, according to :setting:`TEMPLATE_DIRS`. + +``django.template.loaders.app_directories.load_template_source`` + Loads templates from Django apps on the filesystem. For each app in + :setting:`INSTALLED_APPS`, the loader looks for a ``templates`` subdirectory. If + the directory exists, Django looks for templates in there. + + This means you can store templates with your individual apps. This also + makes it easy to distribute Django apps with default templates. + + For example, for this setting:: + + INSTALLED_APPS = ('myproject.polls', 'myproject.music') + + ...then ``get_template('foo.html')`` will look for templates in these + directories, in this order: + + * ``/path/to/myproject/polls/templates/foo.html`` + * ``/path/to/myproject/music/templates/foo.html`` + + Note that the loader performs an optimization when it is first imported: + It caches a list of which :setting:`INSTALLED_APPS` packages have a ``templates`` + subdirectory. + +``django.template.loaders.eggs.load_template_source`` + Just like ``app_directories`` above, but it loads templates from Python + eggs rather than from the filesystem. + +Django uses the template loaders in order according to the :setting:`TEMPLATE_LOADERS` +setting. It uses each loader until a loader finds a match. + +The ``render_to_string()`` shortcut +=================================== + +To cut down on the repetitive nature of loading and rendering +templates, Django provides a shortcut function which largely +automates the process: ``render_to_string()`` in +``django.template.loader``, which loads a template, renders it and +returns the resulting string:: + + from django.template.loader import render_to_string + rendered = render_to_string('my_template.html', { 'foo': 'bar' }) + +The ``render_to_string`` shortcut takes one required argument -- +``template_name``, which should be the name of the template to load +and render -- and two optional arguments:: + + dictionary + A dictionary to be used as variables and values for the + template's context. This can also be passed as the second + positional argument. + + context_instance + An instance of ``Context`` or a subclass (e.g., an instance of + ``RequestContext``) to use as the template's context. This can + also be passed as the third positional argument. + +See also the :func:`~django.shortcuts.render_to_response()` shortcut, which +calls ``render_to_string`` and feeds the result into an ``HttpResponse`` +suitable for returning directly from a view. + +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're 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 :setting:`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 :ref:`settings-without-django-settings-module`. 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 +:setting:`TEMPLATE_DIRS` (if you're going to use template loaders), +:setting:`DEFAULT_CHARSET` (although the default of ``utf-8`` is probably fine) +and :setting:`TEMPLATE_DEBUG`. All available settings are described in the +:ref:`settings documentation <ref-settings>`, and any setting starting with +``TEMPLATE_`` is of obvious interest. diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt new file mode 100644 index 0000000000..feca435ffe --- /dev/null +++ b/docs/ref/templates/builtins.txt @@ -0,0 +1,1549 @@ +.. _ref-templates-builtins: + +================================== +Built-in template tags and filters +================================== + +This document describes Django's built-in template tags and filters. It is +recommended that you use the :ref:`automatic documentation +<template-built-in-reference>`, if available, as this will also include +documentation for any custom tags or filters installed. + +.. _ref-templates-builtins-tags: + +Built-in tag reference +---------------------- + +.. templatetag:: autoescape + +autoescape +~~~~~~~~~~ + +**New in Django development version** + +Control the current auto-escaping behavior. This tag takes either ``on`` or +``off`` as an argument and that determines whether auto-escaping is in effect +inside the block. + +When auto-escaping is in effect, all variable content has HTML escaping applied +to it before placing the result into the output (but after any filters have +been applied). This is equivalent to manually applying the ``escape`` filter +to each variable. + +The only exceptions are variables that are already marked as "safe" from +escaping, either by the code that populated the variable, or because it has had +the ``safe`` or ``escape`` filters applied. + +.. templatetag:: block + +block +~~~~~ + +Define a block that can be overridden by child templates. See +:ref:`Template inheritance <template-inheritance>` for more information. + +.. templatetag:: comment + +comment +~~~~~~~ + +Ignore everything between ``{% comment %}`` and ``{% endcomment %}`` + +.. templatetag:: cycle + +cycle +~~~~~ + +**Changed in Django development version** +Cycle among the given strings or variables each time this tag is encountered. + +Within a loop, cycles among the given strings/variables each time through the +loop:: + + {% for o in some_list %} + <tr class="{% cycle 'row1' 'row2' rowvar %}"> + ... + </tr> + {% endfor %} + +Outside of a loop, give the values a unique name the first time you call it, +then use that name each successive time through:: + + <tr class="{% cycle 'row1' 'row2' rowvar as rowcolors %}">...</tr> + <tr class="{% cycle rowcolors %}">...</tr> + <tr class="{% cycle rowcolors %}">...</tr> + +You can use any number of values, separated by spaces. Values enclosed in +single (') or double quotes (") are treated as string literals, while values +without quotes are assumed to refer to context variables. + +You can also separate values with commas:: + + {% cycle row1,row2,row3 %} + +In this syntax, each value will be interpreted as literal text. The +comma-based syntax exists for backwards-compatibility, and should not be +used for new projects. + +.. templatetag:: debug + +debug +~~~~~ + +Output a whole load of debugging information, including the current context and +imported modules. + +.. templatetag:: extends + +extends +~~~~~~~ + +Signal that this template extends a parent template. + +This tag can be used in two ways: + + * ``{% extends "base.html" %}`` (with quotes) uses the literal value + ``"base.html"`` as the name of the parent template to extend. + + * ``{% extends variable %}`` uses the value of ``variable``. If the variable + evaluates to a string, Django will use that string as the name of the + parent template. If the variable evaluates to a ``Template`` object, + Django will use that object as the parent template. + +See :ref:`template-inheritance` for more information. + +.. templatetag:: filter + +filter +~~~~~~ + +Filter the contents of the variable through variable filters. + +Filters can also be piped through each other, and they can have arguments -- +just like in variable syntax. + +Sample usage:: + + {% filter force_escape|lower %} + This text will be HTML-escaped, and will appear in all lowercase. + {% endfilter %} + +.. templatetag:: firstof + +firstof +~~~~~~~ + +Outputs the first variable passed that is not False. Outputs nothing if all the +passed variables are False. + +Sample usage:: + + {% firstof var1 var2 var3 %} + +This is equivalent to:: + + {% if var1 %} + {{ var1 }} + {% else %}{% if var2 %} + {{ var2 }} + {% else %}{% if var3 %} + {{ var3 }} + {% endif %}{% endif %}{% endif %} + +You can also use a literal string as a fallback value in case all +passed variables are False:: + + {% firstof var1 var2 var3 "fallback value" %} + +.. templatetag:: for + +for +~~~ + +Loop over each item in an array. For example, to display a list of athletes +provided in ``athlete_list``:: + + <ul> + {% for athlete in athlete_list %} + <li>{{ athlete.name }}</li> + {% endfor %} + </ul> + +You can loop over a list in reverse by using ``{% for obj in list reversed %}``. + +**New in Django development version** +If you need to loop over a list of lists, you can unpack the values +in each sub-list into individual variables. For example, if your context +contains a list of (x,y) coordinates called ``points``, you could use the +following to output the list of points:: + + {% for x, y in points %} + There is a point at {{ x }},{{ y }} + {% endfor %} + +This can also be useful if you need to access the items in a dictionary. +For example, if your context contained a dictionary ``data``, the following +would display the keys and values of the dictionary:: + + {% for key, value in data.items %} + {{ key }}: {{ value }} + {% endfor %} + +The for loop sets a number of variables available within the loop: + + ========================== ================================================ + Variable Description + ========================== ================================================ + ``forloop.counter`` The current iteration of the loop (1-indexed) + ``forloop.counter0`` The current iteration of the loop (0-indexed) + ``forloop.revcounter`` The number of iterations from the end of the + loop (1-indexed) + ``forloop.revcounter0`` The number of iterations from the end of the + loop (0-indexed) + ``forloop.first`` True if this is the first time through the loop + ``forloop.last`` True if this is the last time through the loop + ``forloop.parentloop`` For nested loops, this is the loop "above" the + current one + ========================== ================================================ + +.. templatetag:: if + +if +~~ + +The ``{% if %}`` tag evaluates a variable, and if that variable is "true" (i.e. +exists, is not empty, and is not a false boolean value) the contents of the +block are output:: + + {% if athlete_list %} + Number of athletes: {{ athlete_list|length }} + {% else %} + No athletes. + {% endif %} + +In the above, if ``athlete_list`` is not empty, the number of athletes will be +displayed by the ``{{ athlete_list|length }}`` variable. + +As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that +will be displayed if the test fails. + +``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or +to negate a given variable:: + + {% if athlete_list and coach_list %} + Both athletes and coaches are available. + {% endif %} + + {% if not athlete_list %} + There are no athletes. + {% endif %} + + {% if athlete_list or coach_list %} + There are some athletes or some coaches. + {% endif %} + + {% if not athlete_list or coach_list %} + There are no athletes or there are some coaches (OK, so + writing English translations of boolean logic sounds + stupid; it's not our fault). + {% endif %} + + {% if athlete_list and not coach_list %} + There are some athletes and absolutely no coaches. + {% endif %} + +``if`` tags don't allow ``and`` and ``or`` clauses within the same tag, because +the order of logic would be ambiguous. For example, this is invalid:: + + {% if athlete_list and coach_list or cheerleader_list %} + +If you need to combine ``and`` and ``or`` to do advanced logic, just use nested +``if`` tags. For example:: + + {% if athlete_list %} + {% if coach_list or cheerleader_list %} + We have athletes, and either coaches or cheerleaders! + {% endif %} + {% endif %} + +Multiple uses of the same logical operator are fine, as long as you use the +same operator. For example, this is valid:: + + {% if athlete_list or coach_list or parent_list or teacher_list %} + +.. templatetag:: ifchanged + +ifchanged +~~~~~~~~~ + +Check if a value has changed from the last iteration of a loop. + +The 'ifchanged' block tag is used within a loop. It has two possible uses. + +1. Checks its own rendered contents against its previous state and only + displays the content if it has changed. For example, this displays a list of + days, only displaying the month if it changes:: + + <h1>Archive for {{ year }}</h1> + + {% for date in days %} + {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %} + <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> + {% endfor %} + +2. If given a variable, check whether that variable has changed. For + example, the following shows the date every time it changes, but + only shows the hour if both the hour and the date has changed:: + + {% for date in days %} + {% ifchanged date.date %} {{ date.date }} {% endifchanged %} + {% ifchanged date.hour date.date %} + {{ date.hour }} + {% endifchanged %} + {% endfor %} + +.. templatetag:: ifequal + +ifequal +~~~~~~~ + +Output the contents of the block if the two arguments equal each other. + +Example:: + + {% ifequal user.id comment.user_id %} + ... + {% endifequal %} + +As in the ``{% if %}`` tag, an ``{% else %}`` clause is optional. + +The arguments can be hard-coded strings, so the following is valid:: + + {% ifequal user.username "adrian" %} + ... + {% endifequal %} + +It is only possible to compare an argument to template variables or strings. +You cannot check for equality with Python objects such as ``True`` or +``False``. If you need to test if something is true or false, use the ``if`` +tag instead. + +.. templatetag:: ifnotequal + +ifnotequal +~~~~~~~~~~ + +Just like ``ifequal``, except it tests that the two arguments are not equal. + +.. templatetag:: include + +include +~~~~~~~ + +Loads a template and renders it with the current context. This is a way of +"including" other templates within a template. + +The template name can either be a variable or a hard-coded (quoted) string, +in either single or double quotes. + +This example includes the contents of the template ``"foo/bar.html"``:: + + {% include "foo/bar.html" %} + +This example includes the contents of the template whose name is contained in +the variable ``template_name``:: + + {% include template_name %} + +An included template is rendered with the context of the template that's +including it. This example produces the output ``"Hello, John"``: + + * Context: variable ``person`` is set to ``"john"``. + * Template:: + + {% include "name_snippet.html" %} + + * The ``name_snippet.html`` template:: + + Hello, {{ person }} + +See also: ``{% ssi %}``. + +.. templatetag:: load + +load +~~~~ + +Load a custom template tag set. + +See :ref:`Custom tag and filter libraries <howto-custom-template-tags>` for more information. + +.. templatetag:: now + +now +~~~ + +Display the date, formatted according to the given string. + +Uses the same format as PHP's ``date()`` function (http://php.net/date) +with some custom extensions. + +Available format strings: + + ================ ======================================== ===================== + Format character Description Example output + ================ ======================================== ===================== + a ``'a.m.'`` or ``'p.m.'`` (Note that ``'a.m.'`` + this is slightly different than PHP's + output, because this includes periods + to match Associated Press style.) + A ``'AM'`` or ``'PM'``. ``'AM'`` + b Month, textual, 3 letters, lowercase. ``'jan'`` + B Not implemented. + d Day of the month, 2 digits with ``'01'`` to ``'31'`` + leading zeros. + D Day of the week, textual, 3 letters. ``'Fri'`` + f Time, in 12-hour hours and minutes, ``'1'``, ``'1:30'`` + with minutes left off if they're zero. + Proprietary extension. + F Month, textual, long. ``'January'`` + g Hour, 12-hour format without leading ``'1'`` to ``'12'`` + zeros. + G Hour, 24-hour format without leading ``'0'`` to ``'23'`` + zeros. + h Hour, 12-hour format. ``'01'`` to ``'12'`` + H Hour, 24-hour format. ``'00'`` to ``'23'`` + i Minutes. ``'00'`` to ``'59'`` + I Not implemented. + j Day of the month without leading ``'1'`` to ``'31'`` + zeros. + l Day of the week, textual, long. ``'Friday'`` + L Boolean for whether it's a leap year. ``True`` or ``False`` + m Month, 2 digits with leading zeros. ``'01'`` to ``'12'`` + M Month, textual, 3 letters. ``'Jan'`` + n Month without leading zeros. ``'1'`` to ``'12'`` + N Month abbreviation in Associated Press ``'Jan.'``, ``'Feb.'``, ``'March'``, ``'May'`` + style. Proprietary extension. + O Difference to Greenwich time in hours. ``'+0200'`` + P Time, in 12-hour hours, minutes and ``'1 a.m.'``, ``'1:30 p.m.'``, ``'midnight'``, ``'noon'``, ``'12:30 p.m.'`` + 'a.m.'/'p.m.', with minutes left off + if they're zero and the special-case + strings 'midnight' and 'noon' if + appropriate. Proprietary extension. + r RFC 2822 formatted date. ``'Thu, 21 Dec 2000 16:01:07 +0200'`` + s Seconds, 2 digits with leading zeros. ``'00'`` to ``'59'`` + S English ordinal suffix for day of the ``'st'``, ``'nd'``, ``'rd'`` or ``'th'`` + month, 2 characters. + t Number of days in the given month. ``28`` to ``31`` + T Time zone of this machine. ``'EST'``, ``'MDT'`` + U Not implemented. + w Day of the week, digits without ``'0'`` (Sunday) to ``'6'`` (Saturday) + leading zeros. + W ISO-8601 week number of year, with ``1``, ``53`` + weeks starting on Monday. + y Year, 2 digits. ``'99'`` + Y Year, 4 digits. ``'1999'`` + z Day of the year. ``0`` to ``365`` + Z Time zone offset in seconds. The ``-43200`` to ``43200`` + offset for timezones west of UTC is + always negative, and for those east of + UTC is always positive. + ================ ======================================== ===================== + +Example:: + + It is {% now "jS F Y H:i" %} + +Note that you can backslash-escape a format string if you want to use the +"raw" value. In this example, "f" is backslash-escaped, because otherwise +"f" is a format string that displays the time. The "o" doesn't need to be +escaped, because it's not a format character:: + + It is the {% now "jS o\f F" %} + +This would display as "It is the 4th of September". + +.. templatetag:: regroup + +regroup +~~~~~~~ + +Regroup a list of alike objects by a common attribute. + +This complex tag is best illustrated by use of an example: say that ``people`` +is a list of people represented by dictionaries with ``first_name``, +``last_name``, and ``gender`` keys:: + + people = [ + {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'}, + {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'}, + {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'}, + {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'}, + {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'}, + ] + +...and you'd like to display a hierarchical list that is ordered by gender, +like this: + + * Male: + * George Bush + * Bill Clinton + * Female: + * Margaret Thatcher + * Condoleezza Rice + * Unknown: + * Pat Smith + +You can use the ``{% regroup %}`` tag to group the list of people by gender. +The following snippet of template code would accomplish this:: + + {% regroup people by gender as gender_list %} + + <ul> + {% for gender in gender_list %} + <li>{{ gender.grouper }} + <ul> + {% for item in gender.list %} + <li>{{ item.first_name }} {{ item.last_name }}</li> + {% endfor %} + </ul> + </li> + {% endfor %} + </ul> + +Let's walk through this example. ``{% regroup %}`` takes three arguments: the +list you want to regroup, the attribute to group by, and the name of the +resulting list. Here, we're regrouping the ``people`` list by the ``gender`` +attribute and calling the result ``gender_list``. + +``{% regroup %}`` produces a list (in this case, ``gender_list``) of +**group objects**. Each group object has two attributes: + + * ``grouper`` -- the item that was grouped by (e.g., the string "Male" or + "Female"). + * ``list`` -- a list of all items in this group (e.g., a list of all people + with gender='Male'). + +Note that ``{% regroup %}`` does not order its input! Our example relies on +the fact that the ``people`` list was ordered by ``gender`` in the first place. +If the ``people`` list did *not* order its members by ``gender``, the regrouping +would naively display more than one group for a single gender. For example, +say the ``people`` list was set to this (note that the males are not grouped +together):: + + people = [ + {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'}, + {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'}, + {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'}, + {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'}, + {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'}, + ] + +With this input for ``people``, the example ``{% regroup %}`` template code +above would result in the following output: + + * Male: + * Bill Clinton + * Unknown: + * Pat Smith + * Female: + * Margaret Thatcher + * Male: + * George Bush + * Female: + * Condoleezza Rice + +The easiest solution to this gotcha is to make sure in your view code that the +data is ordered according to how you want to display it. + +Another solution is to sort the data in the template using the ``dictsort`` +filter, if your data is in a list of dictionaries:: + + {% regroup people|dictsort:"gender" by gender as gender_list %} + +.. templatetag:: spaceless + +spaceless +~~~~~~~~~ + +Removes whitespace between HTML tags. This includes tab +characters and newlines. + +Example usage:: + + {% spaceless %} + <p> + <a href="foo/">Foo</a> + </p> + {% endspaceless %} + +This example would return this HTML:: + + <p><a href="foo/">Foo</a></p> + +Only space between *tags* is removed -- not space between tags and text. In +this example, the space around ``Hello`` won't be stripped:: + + {% spaceless %} + <strong> + Hello + </strong> + {% endspaceless %} + +.. templatetag:: ssi + +ssi +~~~ + +Output the contents of a given file into the page. + +Like a simple "include" tag, ``{% ssi %}`` includes the contents of another +file -- which must be specified using an absolute path -- in the current +page:: + + {% ssi /home/html/ljworld.com/includes/right_generic.html %} + +If the optional "parsed" parameter is given, the contents of the included +file are evaluated as template code, within the current context:: + + {% ssi /home/html/ljworld.com/includes/right_generic.html parsed %} + +Note that if you use ``{% ssi %}``, you'll need to define +:setting:`ALLOWED_INCLUDE_ROOTS` in your Django settings, as a security measure. + +See also: ``{% include %}``. + +.. templatetag:: templatetag + +templatetag +~~~~~~~~~~~ + +Output one of the syntax characters used to compose template tags. + +Since the template system has no concept of "escaping", to display one of the +bits used in template tags, you must use the ``{% templatetag %}`` tag. + +The argument tells which template bit to output: + + ================== ======= + Argument Outputs + ================== ======= + ``openblock`` ``{%`` + ``closeblock`` ``%}`` + ``openvariable`` ``{{`` + ``closevariable`` ``}}`` + ``openbrace`` ``{`` + ``closebrace`` ``}`` + ``opencomment`` ``{#`` + ``closecomment`` ``#}`` + ================== ======= + +.. templatetag:: url + +url +~~~ + +**Note that the syntax for this tag may change in the future, as we make it more robust.** + +Returns an absolute URL (i.e., a URL without the domain name) matching a given +view function and optional parameters. This is a way to output links without +violating the DRY principle by having to hard-code URLs in your templates:: + + {% url path.to.some_view arg1,arg2,name1=value1 %} + +The first argument is a path to a view function in the format +``package.package.module.function``. Additional arguments are optional and +should be comma-separated values that will be used as positional and keyword +arguments in the URL. All arguments required by the URLconf should be present. + +For example, suppose you have a view, ``app_views.client``, whose URLconf +takes a client ID (here, ``client()`` is a method inside the views file +``app_views.py``). The URLconf line might look like this:: + + ('^client/(\d+)/$', 'app_views.client') + +If this app's URLconf is included into the project's URLconf under a path +such as this:: + + ('^clients/', include('project_name.app_name.urls')) + +...then, in a template, you can create a link to this view like this:: + + {% url app_views.client client.id %} + +The template tag will output the string ``/clients/client/123/``. + +**New in development version:** If you're using :ref:`named URL patterns +<naming-url-patterns>`, you can refer to the name of the pattern in the ``url`` +tag instead of using the path to the view. + +.. templatetag:: widthratio + +widthratio +~~~~~~~~~~ + +For creating bar charts and such, this tag calculates the ratio of a given value +to a maximum value, and then applies that ratio to a constant. + +For example:: + + <img src="bar.gif" height="10" width="{% widthratio this_value max_value 100 %}" /> + +Above, if ``this_value`` is 175 and ``max_value`` is 200, the image in the +above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5 +which is rounded up to 88). + +.. templatetag:: with + +with +~~~~ + +**New in Django development version** + +Caches a complex variable under a simpler name. This is useful when accessing +an "expensive" method (e.g., one that hits the database) multiple times. + +For example:: + + {% with business.employees.count as total %} + {{ total }} employee{{ total|pluralize }} + {% endwith %} + +The populated variable (in the example above, ``total``) is only available +between the ``{% with %}`` and ``{% endwith %}`` tags. + +.. _ref-templates-builtins-filters: + +Built-in filter reference +------------------------- + +.. templatefilter:: add + +add +~~~ + +Adds the argument to the value. + +For example:: + + {{ value|add:"2" }} + +If ``value`` is ``4``, then the output will be ``6``. + +.. templatefilter:: addslashes + +addslashes +~~~~~~~~~~ + +Adds slashes before quotes. Useful for escaping strings in CSV, for example. + +**New in Django development version**: For escaping data in JavaScript strings, +use the `escapejs`_ filter instead. + +.. templatefilter:: capfirst + +capfirst +~~~~~~~~ + +Capitalizes the first character of the value. + +.. templatefilter:: center + +center +~~~~~~ + +Centers the value in a field of a given width. + +.. templatefilter:: cut + +cut +~~~ + +Removes all values of arg from the given string. + +For example:: + + {{ value|cut:" "}} + +If ``value`` is ``"String with spaces"``, the output will be ``"Stringwithspaces"``. + +.. templatefilter:: date + +date +~~~~ + +Formats a date according to the given format (same as the `now`_ tag). + +For example:: + + {{ value|date:"D d M Y" }} + +If ``value`` is a ``datetime`` object (e.g., the result of +``datetime.datetime.now()``), the output will be the string +``'Wed 09 Jan 2008'``. + +.. templatefilter:: default + +default +~~~~~~~ + +If value evaluates to ``False``, use given default. Otherwise, use the value. + +For example:: + + {{ value|default:"nothing" }} + +If ``value`` is ``""`` (the empty string), the output will be ``nothing``. + +.. templatefilter:: default_if_none + +default_if_none +~~~~~~~~~~~~~~~ + +If (and only if) value is ``None``, use given default. Otherwise, use the +value. + +Note that if an empty string is given, the default value will *not* be used. +Use the ``default`` filter if you want to fallback for empty strings. + +For example:: + + {{ value|default_if_none:"nothing" }} + +If ``value`` is ``None``, the output will be the string ``"nothing"``. + +.. templatefilter:: dictsort + +dictsort +~~~~~~~~ + +Takes a list of dictionaries and returns that list sorted by the key given in +the argument. + +For example:: + + {{ value|dictsort:"name" }} + +If ``value`` is:: + + [ + {'name': 'zed', 'age': 19}, + {'name': 'amy', 'age': 22}, + {'name': 'joe', 'age': 31}, + ] + +then the output would be:: + + [ + {'name': 'amy', 'age': 22}, + {'name': 'joe', 'age': 31}, + {'name': 'zed', 'age': 19}, + ] + +.. templatefilter:: dictsortreversed + +dictsortreversed +~~~~~~~~~~~~~~~~ + +Takes a list of dictionaries and returns that list sorted in reverse order by +the key given in the argument. This works exactly the same as the above filter, +but the returned value will be in reverse order. + +.. templatefilter:: divisibleby + +divisibleby +~~~~~~~~~~~ + +Returns ``True`` if the value is divisible by the argument. + +For example:: + + {{ value|divisibleby:"3" }} + +If ``value`` is ``21``, the output would be ``True``. + +.. templatefilter:: escape + +escape +~~~~~~ + +Escapes a string's HTML. Specifically, it makes these replacements: + + * ``<`` is converted to ``<`` + * ``>`` is converted to ``>`` + * ``'`` (single quote) is converted to ``'`` + * ``"`` (double quote) is converted to ``"`` + * ``&`` is converted to ``&`` + +The escaping is only applied when the string is output, so it does not matter +where in a chained sequence of filters you put ``escape``: it will always be +applied as though it were the last filter. If you want escaping to be applied +immediately, use the ``force_escape`` filter. + +Applying ``escape`` to a variable that would normally have auto-escaping +applied to the result will only result in one round of escaping being done. So +it is safe to use this function even in auto-escaping environments. If you want +multiple escaping passes to be applied, use the ``force_escape`` filter. + +**New in Django development version:** Due to auto-escaping, the behavior of +this filter has changed slightly. The replacements are only made once, after +all other filters are applied -- including filters before and after it. + +.. templatefilter:: escapejs + +escapejs +~~~~~~~~ + +**New in Django development version** + +Escapes characters for use in JavaScript strings. This does *not* make the +string safe for use in HTML, but does protect you from syntax errors when using +templates to generate JavaScript/JSON. + +.. templatefilter:: filesizeformat + +filesizeformat +~~~~~~~~~~~~~~ + +Format the value like a 'human-readable' file size (i.e. ``'13 KB'``, +``'4.1 MB'``, ``'102 bytes'``, etc). + +For example:: + + {{ value|filesizeformat }} + +If ``value`` is 123456789, the output would be ``117.7 MB``. + +.. templatefilter:: first + +first +~~~~~ + +Returns the first item in a list. + +For example:: + + {{ value|first }} + +If ``value`` is the list ``['a', 'b', 'c']``, the output will be ``'a'``. + +.. templatefilter:: fix_ampersands + +fix_ampersands +~~~~~~~~~~~~~~ + +Replaces ampersands with ``&`` entities. + +For example:: + + {{ value|fix_ampersands }} + +If ``value`` is ``Tom & Jerry``, the output will be ``Tom & Jerry``. + +**New in Django development version**: This filter generally is no longer +useful, because ampersands are automatically escaped in templates. See escape_ +for more on how auto-escaping works. + +.. templatefilter:: floatformat + +floatformat +~~~~~~~~~~~ + +When used without an argument, rounds a floating-point number to one decimal +place -- but only if there's a decimal part to be displayed. For example: + +============ =========================== ======== +``value`` Template Output +============ =========================== ======== +``34.23234`` ``{{ value|floatformat }}`` ``34.2`` +``34.00000`` ``{{ value|floatformat }}`` ``34`` +``34.26000`` ``{{ value|floatformat }}`` ``34.3`` +============ =========================== ======== + +If used with a numeric integer argument, ``floatformat`` rounds a number to +that many decimal places. For example: + +============ ============================= ========== +``value`` Template Output +============ ============================= ========== +``34.23234`` ``{{ value|floatformat:3 }}`` ``34.232`` +``34.00000`` ``{{ value|floatformat:3 }}`` ``34.000`` +``34.26000`` ``{{ value|floatformat:3 }}`` ``34.260`` +============ ============================= ========== + +If the argument passed to ``floatformat`` is negative, it will round a number +to that many decimal places -- but only if there's a decimal part to be +displayed. For example: + +============ ================================ ========== +``value`` Template Output +============ ================================ ========== +``34.23234`` ``{{ value|floatformat:"-3" }}`` ``34.232`` +``34.00000`` ``{{ value|floatformat:"-3" }}`` ``34`` +``34.26000`` ``{{ value|floatformat:"-3" }}`` ``34.260`` +============ ================================ ========== + +Using ``floatformat`` with no argument is equivalent to using ``floatformat`` +with an argument of ``-1``. + +.. templatefilter:: force_escape + +force_escape +~~~~~~~~~~~~ + +**New in Django development version** + +Applies HTML escaping to a string (see the ``escape`` filter for details). +This filter is applied *immediately* and returns a new, escaped string. This +is useful in the rare cases where you need multiple escaping or want to apply +other filters to the escaped results. Normally, you want to use the ``escape`` +filter. + +.. templatefilter:: get_digit + +get_digit +~~~~~~~~~ + +Given a whole number, returns the requested digit, where 1 is the right-most +digit, 2 is the second-right-most digit, etc. Returns the original value for +invalid input (if input or argument is not an integer, or if argument is less +than 1). Otherwise, output is always an integer. + +For example:: + + {{ value|get_digit:"2" }} + +If ``value`` is ``123456789``, the output will be ``8``. + +.. templatefilter:: iriendcode + +iriencode +~~~~~~~~~ + +Converts an IRI (Internationalized Resource Identifier) to a string that is +suitable for including in a URL. This is necessary if you're trying to use +strings containing non-ASCII characters in a URL. + +It's safe to use this filter on a string that has already gone through the +``urlencode`` filter. + +.. templatefilter:: join + +join +~~~~ + +Joins a list with a string, like Python's ``str.join(list)`` + +For example:: + + {{ value|join:" // " }} + +If ``value`` is the list ``['a', 'b', 'c']``, the output will be the string +``"a // b // c"``. + +.. templatefilter:: last + +last +~~~~ + +**New in Django development version.** + +Returns the last item in a list. + +For example:: + + {{ value|last }} + +If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output will be the string +``"d"``. + +.. templatefilter:: length + +length +~~~~~~ + +Returns the length of the value. This works for both strings and lists. + +For example:: + + {{ value|length }} + +If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``. + +.. templatefilter:: length_is + +length_is +~~~~~~~~~ + +Returns ``True`` if the value's length is the argument, or ``False`` otherwise. + +For example:: + + {{ value|length_is:"4" }} + +If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``True``. + +.. templatefilter:: linebreaks + +linebreaks +~~~~~~~~~~ + +Replaces line breaks in plain text with appropriate HTML; a single +newline becomes an HTML line break (``<br />``) and a new line +followed by a blank line becomes a paragraph break (``</p>``). + +For example:: + + {{ value|linebreaks }} + +If ``value`` is ``Joel\nis a slug``, the output will be ``<p>Joel<br>is a +slug</p>``. + +.. templatefilter:: linebreaksbr + +linebreaksbr +~~~~~~~~~~~~ + +Converts all newlines in a piece of plain text to HTML line breaks +(``<br />``). + +.. templatefilter:: linenumbers + +linenumbers +~~~~~~~~~~~ + +Displays text with line numbers. + +.. templatefilter:: ljust + +ljust +~~~~~ + +Left-aligns the value in a field of a given width. + +**Argument:** field size + +.. templatefilter:: lower + +lower +~~~~~ + +Converts a string into all lowercase. + +For example:: + + {{ value|lower }} + +If ``value`` is ``Still MAD At Yoko``, the output will be ``still mad at yoko``. + +.. templatefilter:: make_list + +make_list +~~~~~~~~~ + +Returns the value turned into a list. For an integer, it's a list of +digits. For a string, it's a list of characters. + +For example:: + + {{ value|make_list }} + +If ``value`` is the string ``"Joel"``, the output would be the list +``[u'J', u'o', u'e', u'l']``. If ``value`` is ``123``, the output will be the +list ``[1, 2, 3]``. + +.. templatefilter:: phone2numeric + +phone2numeric +~~~~~~~~~~~~~ + +Converts a phone number (possibly containing letters) to its numerical +equivalent. For example, ``'800-COLLECT'`` will be converted to +``'800-2655328'``. + +The input doesn't have to be a valid phone number. This will happily convert +any string. + +.. templatefilter:: pluralize + +pluralize +~~~~~~~~~ + +Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``. + +Example:: + + You have {{ num_messages }} message{{ num_messages|pluralize }}. + +For words that require a suffix other than ``'s'``, you can provide an alternate +suffix as a parameter to the filter. + +Example:: + + You have {{ num_walruses }} walrus{{ num_walrus|pluralize:"es" }}. + +For words that don't pluralize by simple suffix, you can specify both a +singular and plural suffix, separated by a comma. + +Example:: + + You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}. + +.. templatefilter:: pprint + +pprint +~~~~~~ + +A wrapper around `pprint.pprint`__ -- for debugging, really. + +__ http://www.python.org/doc/2.5/lib/module-pprint.html + +.. templatefilter:: random + +random +~~~~~~ + +Returns a random item from the given list. + +For example:: + + {{ value|random }} + +If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output could be ``"b"``. + +.. templatefilter:: removetags + +removetags +~~~~~~~~~~ + +Removes a space-separated list of [X]HTML tags from the output. + +For example:: + + {{ value|removetags:"b span"|safe }} + +If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"`` the +output will be ``"Joel <button>is</button> a slug"``. + +.. templatefilter:: rjust + +rjust +~~~~~ + +Right-aligns the value in a field of a given width. + +**Argument:** field size + +.. templatefilter:: safe + +safe +~~~~ + +Marks a string as not requiring further HTML escaping prior to output. When +autoescaping is off, this filter has no effect. + +.. templatefilter:: slice + +slice +~~~~~ + +Returns a slice of the list. + +Uses the same syntax as Python's list slicing. See +http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice +for an introduction. + +Example: ``{{ some_list|slice:":2" }}`` + +.. templatefilter:: slugify + +slugify +~~~~~~~ + +Converts to lowercase, removes non-word characters (alphanumerics and +underscores) and converts spaces to hyphens. Also strips leading and trailing +whitespace. + +For example:: + + {{ value|slugify }} + +If ``value`` is ``"Joel is a slug"``, the output will be ``"joel-is-a-slug"``. + +.. templatefilter:: stringformat + +stringformat +~~~~~~~~~~~~ + +Formats the variable according to the argument, a string formatting specifier. +This specifier uses Python string formatting syntax, with the exception that +the leading "%" is dropped. + +See http://docs.python.org/lib/typesseq-strings.html for documentation of +Python string formatting + +For example:: + + {{ value|stringformat:"s" }} + +If ``value`` is ``"Joel is a slug"``, the output will be ``"Joel is a slug"``. + +.. templatefilter:: striptags + +striptags +~~~~~~~~~ + +Strips all [X]HTML tags. + +For example:: + + {{ value|striptags }} + +If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"``, the +output will be ``"Joel is a slug"``. + +.. templatefilter:: time + +time +~~~~ + +Formats a time according to the given format (same as the `now`_ tag). +The time filter will only accept parameters in the format string that relate +to the time of day, not the date (for obvious reasons). If you need to +format a date, use the `date`_ filter. + +For example:: + + {{ value|time:"H:i" }} + +If ``value`` is equivalent to ``datetime.datetime.now()``, the output will be +the string ``"01:23"``. + +.. templatefilter:: timesince + +timesince +~~~~~~~~~ + +Formats a date as the time since that date (e.g., "4 days, 6 hours"). + +Takes an optional argument that is a variable containing the date to use as +the comparison point (without the argument, the comparison point is *now*). +For example, if ``blog_date`` is a date instance representing midnight on 1 +June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006, +then ``{{ comment_date|timesince:blog_date }}`` would return "8 hours". + +Minutes is the smallest unit used, and "0 minutes" will be returned for any +date that is in the future relative to the comparison point. + +.. templatefilter:: timeuntil + +timeuntil +~~~~~~~~~ + +Similar to ``timesince``, except that it measures the time from now until the +given date or datetime. For example, if today is 1 June 2006 and +``conference_date`` is a date instance holding 29 June 2006, then +``{{ conference_date|timeuntil }}`` will return "4 weeks". + +Takes an optional argument that is a variable containing the date to use as +the comparison point (instead of *now*). If ``from_date`` contains 22 June +2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "1 week". + +Minutes is the smallest unit used, and "0 minutes" will be returned for any +date that is in the past relative to the comparison point. + +.. templatefilter:: title + +title +~~~~~ + +Converts a string into titlecase. + +.. templatefilter:: truncatewords + +truncatewords +~~~~~~~~~~~~~ + +Truncates a string after a certain number of words. + +**Argument:** Number of words to truncate after + +For example:: + + {{ value|truncatewords:2 }} + +If ``value`` is ``"Joel is a slug"``, the output will be ``"Joel is ..."``. + +.. templatefilter:: truncatewords_html + +truncatewords_html +~~~~~~~~~~~~~~~~~~ + +Similar to ``truncatewords``, except that it is aware of HTML tags. Any tags +that are opened in the string and not closed before the truncation point, are +closed immediately after the truncation. + +This is less efficient than ``truncatewords``, so should only be used when it +is being passed HTML text. + +.. templatefilter:: unordered_list + +unordered_list +~~~~~~~~~~~~~~ + +Recursively takes a self-nested list and returns an HTML unordered list -- +WITHOUT opening and closing <ul> tags. + +**New in Django development version:** The format accepted by +``unordered_list`` has changed to be easier to understand. + +The list is assumed to be in the proper format. For example, if ``var`` contains +``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then +``{{ var|unordered_list }}`` would return:: + + <li>States + <ul> + <li>Kansas + <ul> + <li>Lawrence</li> + <li>Topeka</li> + </ul> + </li> + <li>Illinois</li> + </ul> + </li> + +Note: the previous more restrictive and verbose format is still supported: +``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``, + +.. templatefilter:: upper + +upper +~~~~~ + +Converts a string into all uppercase. + +For example:: + + {{ value|upper }} + +If ``value`` is ``"Joel is a slug"``, the output will be ``"JOEL IS A SLUG"``. + +.. templatefilter:: urlencode + +urlencode +~~~~~~~~~ + +Escapes a value for use in a URL. + +.. templatefilter:: urlize + +urlize +~~~~~~ + +Converts URLs in plain text into clickable links. + +Note that if ``urlize`` is applied to text that already contains HTML markup, +things won't work as expected. Apply this filter only to *plain* text. + +For example:: + + {{ value|urlize }} + +If ``value`` is ``"Check out www.djangoproject.com"``, the output will be +``"Check out <a +href="http://www.djangoproject.com">www.djangoproject.com</a>"``. + +.. templatefilter:: urlizetrunc + +urlizetrunc +~~~~~~~~~~~ + +Converts URLs into clickable links, truncating URLs longer than the given +character limit. + +As with urlize_, this filter should only be applied to *plain* text. + +**Argument:** Length to truncate URLs to + +For example:: + + {{ value|urlizetrunc:15 }} + +If ``value`` is ``"Check out www.djangoproject.com"``, the output would be +``'Check out <a +href="http://www.djangoproject.com">www.djangopr...</a>'``. + +.. templatefilter:: wordcount + +wordcount +~~~~~~~~~ + +Returns the number of words. + +.. templatefilter:: wordwrap + +wordwrap +~~~~~~~~ + +Wraps words at specified line length. + +**Argument:** number of characters at which to wrap the text + +For example:: + + {{ value|wordwrap:5 }} + +If ``value`` is ``Joel is a slug``, the output would be:: + + Joel + is a + slug + +.. templatefilter:: yesno + +yesno +~~~~~ + +Given a string mapping values for true, false and (optionally) None, +returns one of those strings according to the value: + +========== ====================== ================================== +Value Argument Outputs +========== ====================== ================================== +``True`` ``"yeah,no,maybe"`` ``yeah`` +``False`` ``"yeah,no,maybe"`` ``no`` +``None`` ``"yeah,no,maybe"`` ``maybe`` +``None`` ``"yeah,no"`` ``"no"`` (converts None to False + if no mapping for None is given) +========== ====================== ================================== + +Other tags and filter libraries +=============================== + +Django comes with a couple of other template-tag libraries that you have to +enable explicitly in your ``INSTALLED_APPS`` setting and enable in your +template with the ``{% load %}`` tag. + +django.contrib.humanize +----------------------- + +A set of Django template filters useful for adding a "human touch" to data. See +:ref:`ref-contrib-humanize`. + +django.contrib.markup +--------------------- + +A collection of template filters that implement these common markup languages: + + * Textile + * Markdown + * ReST (ReStructured Text) + +See :ref:`ref-contrib-markup`. + +django.contrib.webdesign +------------------------ + +A collection of template tags that can be useful while designing a website, +such as a generator of Lorem Ipsum text. See :ref:`ref-contrib-webdesign`. diff --git a/docs/ref/templates/index.txt b/docs/ref/templates/index.txt new file mode 100644 index 0000000000..d7bf99aa8c --- /dev/null +++ b/docs/ref/templates/index.txt @@ -0,0 +1,20 @@ +.. _ref-templates-index: + +Template reference +================== + +Django's template engine provides a powerful mini-language for defining the +user-facing layer of your application, encouraging a clean separation of +application and presentation logic. Templates can be maintained by anyone with +an understanding of HTML; no knowledge of Python is required. + +.. toctree:: + :maxdepth: 2 + + builtins + api + +.. seealso:: + + For information on writing your own custom tags and filters, see + :ref:`howto-custom-template-tags`.
\ No newline at end of file diff --git a/docs/ref/unicode.txt b/docs/ref/unicode.txt new file mode 100644 index 0000000000..985ab15096 --- /dev/null +++ b/docs/ref/unicode.txt @@ -0,0 +1,364 @@ +.. _ref-unicode: + +====================== +Unicode data in Django +====================== + +**New in Django development version** + +Django natively supports Unicode data everywhere. Providing your database can +somehow store the data, you can safely pass around Unicode strings to +templates, models and the database. + +This document tells you what you need to know if you're writing applications +that use data or templates that are encoded in something other than ASCII. + +Creating the database +===================== + +Make sure your database is configured to be able to store arbitrary string +data. Normally, this means giving it an encoding of UTF-8 or UTF-16. If you use +a more restrictive encoding -- for example, latin1 (iso8859-1) -- you won't be +able to store certain characters in the database, and information will be lost. + + * MySQL users, refer to the `MySQL manual`_ (section 10.3.2 for MySQL 5.1) for + details on how to set or alter the database character set encoding. + + * PostgreSQL users, refer to the `PostgreSQL manual`_ (section 21.2.2 in + PostgreSQL 8) for details on creating databases with the correct encoding. + + * SQLite users, there is nothing you need to do. SQLite always uses UTF-8 + for internal encoding. + +.. _MySQL manual: http://www.mysql.org/doc/refman/5.1/en/charset-database.html +.. _PostgreSQL manual: http://www.postgresql.org/docs/8.2/static/multibyte.html#AEN24104 + +All of Django's database backends automatically convert Unicode strings into +the appropriate encoding for talking to the database. They also automatically +convert strings retrieved from the database into Python Unicode strings. You +don't even need to tell Django what encoding your database uses: that is +handled transparently. + +For more, see the section "The database API" below. + +General string handling +======================= + +Whenever you use strings with Django -- e.g., in database lookups, template +rendering or anywhere else -- you have two choices for encoding those strings. +You can use Unicode strings, or you can use normal strings (sometimes called +"bytestrings") that are encoded using UTF-8. + +.. admonition:: Warning + + A bytestring does not carry any information with it about its encoding. + For that reason, we have to make an assumption, and Django assumes that all + bytestrings are in UTF-8. + + If you pass a string to Django that has been encoded in some other format, + things will go wrong in interesting ways. Usually, Django will raise a + ``UnicodeDecodeError`` at some point. + +If your code only uses ASCII data, it's safe to use your normal strings, +passing them around at will, because ASCII is a subset of UTF-8. + +Don't be fooled into thinking that if your :setting:`DEFAULT_CHARSET` setting is set +to something other than ``'utf-8'`` you can use that other encoding in your +bytestrings! :setting:`DEFAULT_CHARSET` only applies to the strings generated as +the result of template rendering (and e-mail). Django will always assume UTF-8 +encoding for internal bytestrings. The reason for this is that the +:setting:`DEFAULT_CHARSET` setting is not actually under your control (if you are the +application developer). It's under the control of the person installing and +using your application -- and if that person chooses a different setting, your +code must still continue to work. Ergo, it cannot rely on that setting. + +In most cases when Django is dealing with strings, it will convert them to +Unicode strings before doing anything else. So, as a general rule, if you pass +in a bytestring, be prepared to receive a Unicode string back in the result. + +Translated strings +------------------ + +Aside from Unicode strings and bytestrings, there's a third type of string-like +object you may encounter when using Django. The framework's +internationalization features introduce the concept of a "lazy translation" -- +a string that has been marked as translated but whose actual translation result +isn't determined until the object is used in a string. This feature is useful +in cases where the translation locale is unknown until the string is used, even +though the string might have originally been created when the code was first +imported. + +Normally, you won't have to worry about lazy translations. Just be aware that +if you examine an object and it claims to be a +``django.utils.functional.__proxy__`` object, it is a lazy translation. +Calling ``unicode()`` with the lazy translation as the argument will generate a +Unicode string in the current locale. + +For more details about lazy translation objects, refer to the +:ref:`internationalization <topics-i18n>` documentation. + +Useful utility functions +------------------------ + +Because some string operations come up again and again, Django ships with a few +useful functions that should make working with Unicode and bytestring objects +a bit easier. + +Conversion functions +~~~~~~~~~~~~~~~~~~~~ + +The ``django.utils.encoding`` module contains a few functions that are handy +for converting back and forth between Unicode and bytestrings. + + * ``smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')`` + converts its input to a Unicode string. The ``encoding`` parameter + specifies the input encoding. (For example, Django uses this internally + when processing form input data, which might not be UTF-8 encoded.) The + ``strings_only`` parameter, if set to True, will result in Python + numbers, booleans and ``None`` not being converted to a string (they keep + their original types). The ``errors`` parameter takes any of the values + that are accepted by Python's ``unicode()`` function for its error + handling. + + If you pass ``smart_unicode()`` an object that has a ``__unicode__`` + method, it will use that method to do the conversion. + + * ``force_unicode(s, encoding='utf-8', strings_only=False, + errors='strict')`` is identical to ``smart_unicode()`` in almost all + cases. The difference is when the first argument is a :ref:`lazy + translation <lazy-translations>` instance. While ``smart_unicode()`` + preserves lazy translations, ``force_unicode()`` forces those objects to a + Unicode string (causing the translation to occur). Normally, you'll want + to use ``smart_unicode()``. However, ``force_unicode()`` is useful in + template tags and filters that absolutely *must* have a string to work + with, not just something that can be converted to a string. + + * ``smart_str(s, encoding='utf-8', strings_only=False, errors='strict')`` + is essentially the opposite of ``smart_unicode()``. It forces the first + argument to a bytestring. The ``strings_only`` parameter has the same + behavior as for ``smart_unicode()`` and ``force_unicode()``. This is + slightly different semantics from Python's builtin ``str()`` function, + but the difference is needed in a few places within Django's internals. + +Normally, you'll only need to use ``smart_unicode()``. Call it as early as +possible on any input data that might be either Unicode or a bytestring, and +from then on, you can treat the result as always being Unicode. + +URI and IRI handling +~~~~~~~~~~~~~~~~~~~~ + +Web frameworks have to deal with URLs (which are a type of IRI_). One +requirement of URLs is that they are encoded using only ASCII characters. +However, in an international environment, you might need to construct a +URL from an IRI_ -- very loosely speaking, a URI that can contain Unicode +characters. Quoting and converting an IRI to URI can be a little tricky, so +Django provides some assistance. + + * The function ``django.utils.encoding.iri_to_uri()`` implements the + conversion from IRI to URI as required by the specification (`RFC + 3987`_). + + * The functions ``django.utils.http.urlquote()`` and + ``django.utils.http.urlquote_plus()`` are versions of Python's standard + ``urllib.quote()`` and ``urllib.quote_plus()`` that work with non-ASCII + characters. (The data is converted to UTF-8 prior to encoding.) + +These two groups of functions have slightly different purposes, and it's +important to keep them straight. Normally, you would use ``urlquote()`` on the +individual portions of the IRI or URI path so that any reserved characters +such as '&' or '%' are correctly encoded. Then, you apply ``iri_to_uri()`` to +the full IRI and it converts any non-ASCII characters to the correct encoded +values. + +.. note:: + Technically, it isn't correct to say that ``iri_to_uri()`` implements the + full algorithm in the IRI specification. It doesn't (yet) perform the + international domain name encoding portion of the algorithm. + +The ``iri_to_uri()`` function will not change ASCII characters that are +otherwise permitted in a URL. So, for example, the character '%' is not +further encoded when passed to ``iri_to_uri()``. This means you can pass a +full URL to this function and it will not mess up the query string or anything +like that. + +An example might clarify things here:: + + >>> urlquote(u'Paris & Orléans') + u'Paris%20%26%20Orl%C3%A9ans' + >>> iri_to_uri(u'/favorites/François/%s' % urlquote(u'Paris & Orléans')) + '/favorites/Fran%C3%A7ois/Paris%20%26%20Orl%C3%A9ans' + +If you look carefully, you can see that the portion that was generated by +``urlquote()`` in the second example was not double-quoted when passed to +``iri_to_uri()``. This is a very important and useful feature. It means that +you can construct your IRI without worrying about whether it contains +non-ASCII characters and then, right at the end, call ``iri_to_uri()`` on the +result. + +The ``iri_to_uri()`` function is also idempotent, which means the following is +always true:: + + iri_to_uri(iri_to_uri(some_string)) = iri_to_uri(some_string) + +So you can safely call it multiple times on the same IRI without risking +double-quoting problems. + +.. _URI: http://www.ietf.org/rfc/rfc2396.txt +.. _IRI: http://www.ietf.org/rfc/rfc3987.txt +.. _RFC 3987: IRI_ + +Models +====== + +Because all strings are returned from the database as Unicode strings, model +fields that are character based (CharField, TextField, URLField, etc) will +contain Unicode values when Django retrieves data from the database. This +is *always* the case, even if the data could fit into an ASCII bytestring. + +You can pass in bytestrings when creating a model or populating a field, and +Django will convert it to Unicode when it needs to. + +Choosing between ``__str__()`` and ``__unicode__()`` +---------------------------------------------------- + +One consequence of using Unicode by default is that you have to take some care +when printing data from the model. + +In particular, rather than giving your model a ``__str__()`` method, we +recommended you implement a ``__unicode__()`` method. In the ``__unicode__()`` +method, you can quite safely return the values of all your fields without +having to worry about whether they fit into a bytestring or not. (The way +Python works, the result of ``__str__()`` is *always* a bytestring, even if you +accidentally try to return a Unicode object). + +You can still create a ``__str__()`` method on your models if you want, of +course, but you shouldn't need to do this unless you have a good reason. +Django's ``Model`` base class automatically provides a ``__str__()`` +implementation that calls ``__unicode__()`` and encodes the result into UTF-8. +This means you'll normally only need to implement a ``__unicode__()`` method +and let Django handle the coercion to a bytestring when required. + +Taking care in ``get_absolute_url()`` +------------------------------------- + +URLs can only contain ASCII characters. If you're constructing a URL from +pieces of data that might be non-ASCII, be careful to encode the results in a +way that is suitable for a URL. The ``django.db.models.permalink()`` decorator +handles this for you automatically. + +If you're constructing a URL manually (i.e., *not* using the ``permalink()`` +decorator), you'll need to take care of the encoding yourself. In this case, +use the ``iri_to_uri()`` and ``urlquote()`` functions that were documented +above_. For example:: + + from django.utils.encoding import iri_to_uri + from django.utils.http import urlquote + + def get_absolute_url(self): + url = u'/person/%s/?x=0&y=0' % urlquote(self.location) + return iri_to_uri(url) + +This function returns a correctly encoded URL even if ``self.location`` is +something like "Jack visited Paris & Orléans". (In fact, the ``iri_to_uri()`` +call isn't strictly necessary in the above example, because all the +non-ASCII characters would have been removed in quoting in the first line.) + +.. _above: `URI and IRI handling`_ + +The database API +================ + +You can pass either Unicode strings or UTF-8 bytestrings as arguments to +``filter()`` methods and the like in the database API. The following two +querysets are identical:: + + qs = People.objects.filter(name__contains=u'Å') + qs = People.objects.filter(name__contains='\xc3\85') # UTF-8 encoding of Å + +Templates +========= + +You can use either Unicode or bytestrings when creating templates manually:: + + from django.template import Template + t1 = Template('This is a bytestring template.') + t2 = Template(u'This is a Unicode template.') + +But the common case is to read templates from the filesystem, and this creates +a slight complication: not all filesystems store their data encoded as UTF-8. +If your template files are not stored with a UTF-8 encoding, set the :setting:`FILE_CHARSET` +setting to the encoding of the files on disk. When Django reads in a template +file, it will convert the data from this encoding to Unicode. (:setting:`FILE_CHARSET` +is set to ``'utf-8'`` by default.) + +The :setting:`DEFAULT_CHARSET` setting controls the encoding of rendered templates. +This is set to UTF-8 by default. + +Template tags and filters +------------------------- + +A couple of tips to remember when writing your own template tags and filters: + + * Always return Unicode strings from a template tag's ``render()`` method + and from template filters. + + * Use ``force_unicode()`` in preference to ``smart_unicode()`` in these + places. Tag rendering and filter calls occur as the template is being + rendered, so there is no advantage to postponing the conversion of lazy + translation objects into strings. It's easier to work solely with Unicode + strings at that point. + +E-mail +====== + +Django's e-mail framework (in ``django.core.mail``) supports Unicode +transparently. You can use Unicode data in the message bodies and any headers. +However, you're still obligated to respect the requirements of the e-mail +specifications, so, for example, e-mail addresses should use only ASCII +characters. + +The following code example demonstrates that everything except e-mail addresses +can be non-ASCII:: + + from django.core.mail import EmailMessage + + subject = u'My visit to Sør-Trøndelag' + sender = u'Arnbjörg Ráðormsdóttir <arnbjorg@example.com>' + recipients = ['Fred <fred@example.com'] + body = u'...' + EmailMessage(subject, body, sender, recipients).send() + +Form submission +=============== + +HTML form submission is a tricky area. There's no guarantee that the +submission will include encoding information, which means the framework might +have to guess at the encoding of submitted data. + +Django adopts a "lazy" approach to decoding form data. The data in an +``HttpRequest`` object is only decoded when you access it. In fact, most of +the data is not decoded at all. Only the ``HttpRequest.GET`` and +``HttpRequest.POST`` data structures have any decoding applied to them. Those +two fields will return their members as Unicode data. All other attributes and +methods of ``HttpRequest`` return data exactly as it was submitted by the +client. + +By default, the :setting:`DEFAULT_CHARSET` setting is used as the assumed encoding +for form data. If you need to change this for a particular form, you can set +the ``encoding`` attribute on an ``HttpRequest`` instance. For example:: + + def some_view(request): + # We know that the data must be encoded as KOI8-R (for some reason). + request.encoding = 'koi8-r' + ... + +You can even change the encoding after having accessed ``request.GET`` or +``request.POST``, and all subsequent accesses will use the new encoding. + +Most developers won't need to worry about changing form encoding, but this is +a useful feature for applications that talk to legacy systems whose encoding +you cannot control. + +Django does not decode the data of file uploads, because that data is normally +treated as collections of bytes, rather than strings. Any automatic decoding +there would alter the meaning of the stream of bytes. |
