diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/authentication.txt | 2 | ||||
| -rw-r--r-- | docs/contributing.txt | 6 | ||||
| -rw-r--r-- | docs/custom_model_fields.txt | 4 | ||||
| -rw-r--r-- | docs/db-api.txt | 4 | ||||
| -rw-r--r-- | docs/form_wizard.txt | 304 | ||||
| -rw-r--r-- | docs/generic_views.txt | 17 | ||||
| -rw-r--r-- | docs/i18n.txt | 7 | ||||
| -rw-r--r-- | docs/install.txt | 14 | ||||
| -rw-r--r-- | docs/model-api.txt | 30 | ||||
| -rw-r--r-- | docs/modelforms.txt | 10 | ||||
| -rw-r--r-- | docs/newforms.txt | 82 | ||||
| -rw-r--r-- | docs/pagination.txt | 133 | ||||
| -rw-r--r-- | docs/request_response.txt | 27 | ||||
| -rw-r--r-- | docs/sessions.txt | 8 | ||||
| -rw-r--r-- | docs/settings.txt | 16 | ||||
| -rw-r--r-- | docs/syndication_feeds.txt | 7 | ||||
| -rw-r--r-- | docs/templates.txt | 277 | ||||
| -rw-r--r-- | docs/tutorial04.txt | 6 | ||||
| -rw-r--r-- | docs/url_dispatch.txt | 8 |
19 files changed, 889 insertions, 73 deletions
diff --git a/docs/authentication.txt b/docs/authentication.txt index 212e17ac62..c24d1ef62d 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -309,7 +309,7 @@ with that ``User``. For more information, see `Chapter 12 of the Django book`_. -.. _Chapter 12 of the Django book: http://www.djangobook.com/en/beta/chapter12/#cn226 +.. _Chapter 12 of the Django book: http://www.djangobook.com/en/1.0/chapter12/#cn222 Authentication in Web requests ============================== diff --git a/docs/contributing.txt b/docs/contributing.txt index 37c9196467..885f5159b9 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -328,8 +328,12 @@ incorrect translation, or if you'd like to add a language that isn't yet translated, here's what to do: * Join the `Django i18n mailing list`_ and introduce yourself. - * Create and submit translations using the methods described in the + * Create translations using the methods described in the `i18n documentation`_. + * Create a diff of the ``.po`` file against the current Subversion trunk. + * Make sure that `` bin/compile-messages.py -l <lang>`` runs without + producing any warnings. + * Attach the patch to a ticket in Django's ticket system. .. _Django i18n mailing list: http://groups.google.com/group/django-i18n/ .. _i18n documentation: ../i18n/ diff --git a/docs/custom_model_fields.txt b/docs/custom_model_fields.txt index 923b331a95..2b344921ef 100644 --- a/docs/custom_model_fields.txt +++ b/docs/custom_model_fields.txt @@ -401,8 +401,8 @@ For example:: # ... def get_db_prep_save(self, value): - return ''.join([''.join(l) for l in (self.north, - self.east, self.south, self.west)]) + return ''.join([''.join(l) for l in (value.north, + value.east, value.south, value.west)]) ``pre_save(self, model_instance, add)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/db-api.txt b/docs/db-api.txt index 80f8a2d60b..e9b5c05f6b 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -1372,7 +1372,7 @@ equivalent:: Entry.objects.filter(blog__pk=3) # __pk implies __id__exact Lookups that span relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------- Django offers a powerful and intuitive way to "follow" relationships in lookups, taking care of the SQL ``JOIN``\s for you automatically, behind the @@ -1396,7 +1396,7 @@ whose ``headline`` contains ``'Lennon'``:: Blog.objects.filter(entry__headline__contains='Lennon') Escaping percent signs and underscores in LIKE statements -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--------------------------------------------------------- The field lookups that equate to ``LIKE`` SQL statements (``iexact``, ``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith`` diff --git a/docs/form_wizard.txt b/docs/form_wizard.txt new file mode 100644 index 0000000000..cd9e58ded1 --- /dev/null +++ b/docs/form_wizard.txt @@ -0,0 +1,304 @@ +=========== +Form wizard +=========== + +**New in Django development version.** + +Django comes with an optional "form wizard" application that splits forms_ +across multiple Web pages. It maintains state in hashed HTML +``<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: ../newforms/ + +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 ``<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 ``django.newforms`` ``Form`` classes -- one per wizard + page. + 2. Create a ``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 ``FormWizard`` class. + +Defining ``Form`` classes +========================= + +The first step in creating a form wizard is to create the ``Form`` classes. +These should be standard ``django.newforms`` ``Form`` classes, covered in the +`newforms documentation`_. + +These classes can live anywhere in your codebase, but convention is to put them +in a file called ``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 ``forms.py`` might look like:: + + from django import newforms as 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 ``FileField`` in any form except the +last one. + +.. _newforms documentation: ../newforms/ + +Creating a ``FormWizard`` class +=============================== + +The next step is to create a ``FormWizard`` class, which should be a subclass +of ``django.contrib.formtools.wizard.FormWizard``. + +As your ``Form`` classes, this ``FormWizard`` class can live anywhere in your +codebase, but convention is to put it in ``forms.py``. + +The only requirement on this subclass is that it implement a ``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 HttpRequest_ object + * ``form_list`` -- a list of ``django.newforms`` ``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 +``FormWizard`` hooks. + +.. _HttpRequest: request_response/#httprequest-objects + +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 ``forms/wizard.html``. (You can +change this template name by overriding ``FormWizard.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 ``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 ``safe`` template filter, to + prevent auto-escaping, because it's raw HTML. + +It will also be passed any objects in ``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 ``extra_context`` attribute on your ``FormWizard`` subclass to a + dictionary. + + * Pass ``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 ``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 +=============================== + +Aside from the ``done()`` method, ``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``.) + +``prefix_for_step`` +~~~~~~~~~~~~~~~~~~~ + +Given the step, returns a ``Form`` prefix to use. By default, this simply uses +the step itself. For more, see the `form prefix documentation`_. + +Default implementation:: + + def prefix_for_step(self, step): + return str(step) + +.. _form prefix documentation: ../newforms/#prefixes-for-forms + +``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.'}) + +``security_hash`` +~~~~~~~~~~~~~~~~~ + +Calculates the security hash for the given request object and ``Form`` instance. + +By default, this uses an MD5 hash of the form data and your +`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) + +.. _SECRET_KEY setting: ../settings/#secret-key + +``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] + +``get_template`` +~~~~~~~~~~~~~~~~ + +Returns the name of the template that should be used for the given step. + +By default, this returns ``'forms/wizard.html'``, regardless of step. + +Example:: + + def get_template(self, step): + return 'myapp/wizard_%s.html' % step + +If ``get_template`` returns a list of strings, then the wizard will use the +template system's ``select_template()`` function, `explained in the template docs`_. +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 + +``render_template`` +~~~~~~~~~~~~~~~~~~~ + +Renders the template for the given step, returning an ``HttpResponse`` 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 +``get_template()`` instead. + +The template will be rendered with the context documented in the +"Creating templates for the forms" section above. + +``process_step`` +~~~~~~~~~~~~~~~~ + +Hook for modifying the wizard's internal state, given a fully validated ``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/generic_views.txt b/docs/generic_views.txt index 17187894c0..b7beb0b4be 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -751,6 +751,19 @@ In addition to ``extra_context``, the template's context will be: 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``. + +In older versions of Django, before ``paginator`` and ``page_obj`` were added +to this template's context, the template included several other variables +related to pagination. Note that you should *NOT* use these variables anymore; +use ``paginator`` and ``page_obj`` instead, because they let you do everything +these old variables let you do (and more!). But for legacy installations, +here's a list of those old template variables: + * ``results_per_page``: The number of objects per page. (Same as the ``paginate_by`` parameter.) @@ -777,8 +790,8 @@ If the results are paginated, the context will contain these extra variables: * ``hits``: The total number of objects across *all* pages, not just this page. - * **New in Django development version:** ``page_range``: A list of the - page numbers that are available. This is 1-based. + * ``page_range``: A list of the page numbers that are available. This is + 1-based. Notes on pagination ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/i18n.txt b/docs/i18n.txt index bb6cf74ded..8da19cd242 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -547,7 +547,7 @@ following this algorithm: * First, it looks for a ``django_language`` key in the the current user's `session`_. - * Failing that, it looks for a cookie that is named according to your ``LANGUAGE_COOKIE_NAME`` setting (the default name is: ``django_language``). + * Failing that, it looks for a cookie that is named according to your ``LANGUAGE_COOKIE_NAME`` setting. (The default name is ``django_language``, and this setting is new in the Django development version. In Django version 0.96 and before, the cookie's name is hard-coded to ``django_language``.) * Failing that, it looks at the ``Accept-Language`` HTTP header. This header is sent by your browser and tells the server which language(s) you prefer, in order by priority. Django tries each language in the header @@ -719,8 +719,9 @@ Activate this view by adding the following line to your URLconf:: The view expects to be called via the ``POST`` method, with a ``language`` parameter set in request. If session support is enabled, the view saves the language choice in the user's session. Otherwise, it saves the -language choice in a cookie that is by default named ``django_language`` -(the name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting). +language choice in a cookie that is by default named ``django_language``. +(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting if you're +using the Django development version.) After setting the language choice, Django redirects the user, following this algorithm: diff --git a/docs/install.txt b/docs/install.txt index 542036e2af..341c4280e8 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -167,6 +167,20 @@ These commands will install Django in your Python installation's Installing the development version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. admonition:: Tracking Django development + + If you decide to use the latest development version of Django, + you'll want to pay close attention to `the development timeline`_, + and you'll want to keep an eye on `the list of + backwards-incompatible changes`_; this will help you stay on top + of any new features you might want to use, as well as any changes + you'll need to make to your code when updating your copy of Django + (for stable releases, any necessary changes are documented in the + release notes). + +.. _the development timeline: http://code.djangoproject.com/timeline +.. _the list of backwards-incompatible changes: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges + If you'd like to be able to update your Django code occasionally with the latest bug fixes and improvements, follow these instructions: diff --git a/docs/model-api.txt b/docs/model-api.txt index 66fa63e3c6..f73c5aadf7 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -626,7 +626,8 @@ option is ignored. ``default`` ~~~~~~~~~~~ -The default value for the field. +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`` ~~~~~~~~~~~~ @@ -788,10 +789,10 @@ 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 explicitially specify the application label. That -is, if the ``Manufacturer`` model above is defined in another application called -``production``, you'd need to use:: +**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') @@ -1022,6 +1023,8 @@ See the `One-to-one relationship model example`_ for a full example. Custom field types ------------------ +**New in Django development version** + If one of the existing model fields cannot be used to fit your purposes, or if you wish to take advantage of some less common database column types, you can create your own field class. Full coverage of creating your own fields is @@ -1786,14 +1789,15 @@ For example:: This example allows you to request ``Person.men.all()``, ``Person.women.all()``, and ``Person.people.all()``, yielding predictable results. -If you use custom ``Manager`` objects, take note that the first ``Manager`` -Django encounters (in order by which they're defined in the model) has a -special status. Django interprets the first ``Manager`` defined in a class as -the "default" ``Manager``. Certain operations -- such as Django's admin site -- -use the default ``Manager`` to obtain lists of objects, so it's generally a -good idea for the first ``Manager`` to be relatively unfiltered. In the last -example, the ``people`` ``Manager`` is defined first -- so it's the default -``Manager``. +If you use custom ``Manager`` objects, take note that the first +``Manager`` Django encounters (in the order in which they're defined +in the model) has a special status. Django interprets this first +``Manager`` defined in a class as the "default" ``Manager``, and +several parts of Django (though not the admin application) will use +that ``Manager`` exclusively for that model. As a result, it's often a +good idea to be careful in your choice of default manager, in order to +avoid a situation where overriding of ``get_query_set()`` results in +an inability to retrieve objects you'd like to work with. Model methods ============= diff --git a/docs/modelforms.txt b/docs/modelforms.txt index 47eaa9a769..05f9b1b3d4 100644 --- a/docs/modelforms.txt +++ b/docs/modelforms.txt @@ -231,6 +231,16 @@ For example:: # Create and save the new author instance. There's no need to do anything else. >>> new_author = f.save() +Other than the ``save()`` and ``save_m2m()`` methods, a ``ModelForm`` +works exactly the same way as any other ``newforms`` form. For +example, the ``is_valid()`` method is used to check for validity, the +``is_multipart()`` method is used to determine whether a form requires +multipart file upload (and hence whether ``request.FILES`` must be +passed to the form), etc.; see `the standard newforms documentation`_ +for more information. + +.. _the standard newforms documentation: ../newforms/ + Using a subset of fields on the form ------------------------------------ diff --git a/docs/newforms.txt b/docs/newforms.txt index 229f704ca7..4f59400949 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -1336,13 +1336,14 @@ given length. An ``UploadedFile`` object has two attributes: - ====================== ===================================================== - Argument Description - ====================== ===================================================== + ====================== ==================================================== + Attribute Description + ====================== ==================================================== ``filename`` The name of the file, provided by the uploading client. + ``content`` The array of bytes comprising the file content. - ====================== ===================================================== + ====================== ==================================================== The string representation of an ``UploadedFile`` is the same as the filename attribute. @@ -1352,6 +1353,38 @@ When you use a ``FileField`` on a form, you must also remember to .. _`bind the file data to the form`: `Binding uploaded files to a form`_ +``FilePathField`` +~~~~~~~~~~~~~~~~~ + +**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: + + ============== ========== =============================================== + Argument Required? Description + ============== ========== =============================================== + ``path`` Yes The absolute path to the directory whose + contents you want listed. This directory must + exist. + + ``recursive`` No 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. + + ``match`` No A regular expression pattern; only files with + names matching this expression will be allowed + as choices. + ============== ========== =============================================== + ``ImageField`` ~~~~~~~~~~~~~~ @@ -1502,6 +1535,41 @@ the bottom of this document, for examples of their use. ``SplitDateTimeField`` ~~~~~~~~~~~~~~~~~~~~~~ +Fields which handle relationships +--------------------------------- + +For representing relationships between models, two fields are +provided which can derive their choices from a ``QuerySet``, and which +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: + +``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 method receives an object as an argument and must return a +string to represent it. + +The labels for the choice field call the ``__unicode__`` method of the model to +generate string representations. To provide custom labels, subclass ``ModelChoiceField`` and override ``label_for_model``:: + + 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 labels. + Creating custom fields ---------------------- @@ -1572,9 +1640,9 @@ The three types of cleaning methods are: 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 it's override) is run, then +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 it's override, is executed. +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 @@ -1696,7 +1764,7 @@ For example, take the following simple form:: comment = forms.CharField() This form will include three default TextInput widgets, with default rendering - -no CSS class, no extra attributes. This means that the inputs boxes provided for +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) diff --git a/docs/pagination.txt b/docs/pagination.txt new file mode 100644 index 0000000000..486c92264b --- /dev/null +++ b/docs/pagination.txt @@ -0,0 +1,133 @@ +========== +Pagination +========== + +**New in Django development version** + +Django provides a few classes that help you manage paginated data -- that is, +data that's split across several pages, with "Previous/Next" links. These +classes live in the module ``django/core/paginator.py``. + +Example +======= + +Give ``Paginator`` a list of objects, plus the number of items you'd like to +have on each page, and it gives you methods for accessing the items for each +page:: + + >>> from django.core.paginator import Paginator + >>> objects = ['john', 'paul', 'george', 'ringo'] + >>> p = Paginator(objects, 2) + + >>> p.count + 4 + >>> p.num_pages + 2 + >>> p.page_range + [1, 2] + + >>> page1 = p.page(1) + >>> page1 + <Page 1 of 2> + >>> page1.object_list + ['john', 'paul'] + + >>> page2 = p.page(2) + >>> page2.object_list + ['george', 'ringo'] + >>> page2.has_next() + False + >>> page2.has_previous() + True + >>> page2.has_other_pages() + True + >>> page2.next_page_number() + 3 + >>> page2.previous_page_number() + 1 + >>> page2.start_index() # The 1-based index of the first item on this page + 3 + >>> page2.end_index() # The 1-based index of the last item on this page + 4 + + >>> p.page(0) + Traceback (most recent call last): + ... + InvalidPage + >>> p.page(3) + Traceback (most recent call last): + ... + InvalidPage + +``Paginator`` objects +===================== + +Methods +------- + +``page(number)`` -- Returns a ``Page`` object with the given 1-based index. +Raises ``InvalidPage`` if the given page number doesn't exist. + +Attributes +---------- + +``count`` -- The total number of objects, across all pages. + +``num_pages`` -- The total number of pages. + +``page_range`` -- A 1-based range of page numbers, e.g., ``[1, 2, 3, 4]``. + +``Page`` objects +================ + +Methods +------- + +``has_next()`` -- Returns ``True`` if there's a next page. + +``has_previous()`` -- Returns ``True`` if there's a previous page. + +``has_other_pages()`` -- Returns ``True`` if there's a next *or* previous page. + +``next_page_number()`` -- Returns the next page number. Note that this is +"dumb" and will return the next page number regardless of whether a subsequent +page exists. + +``previous_page_number()`` -- Returns the previous page number. Note that this +is "dumb" and will return the previous page number regardless of whether a +previous page exists. + +``start_index()`` -- Returns the 1-based index of the first object on the page, +relative to all of the objects in the paginator's list. For example, when +paginating a list of 5 objects with 2 objects per page, the second page's +``start_index()`` would return ``3``. + +``end_index()`` -- Returns the 1-based index of the last object on the page, +relative to all of the objects in the paginator's list. For example, when +paginating a list of 5 objects with 2 objects per page, the second page's +``end_index()`` would return ``4``. + +Attributes +---------- + +``object_list`` -- The list of objects on this page. + +``number`` -- The 1-based page number for this page. + +``paginator`` -- The associated ``Paginator`` object. + +``QuerySetPaginator`` objects +============================= + +Use ``QuerySetPaginator`` instead of ``Paginator`` if you're paginating across +a ``QuerySet`` from Django's database API. This is slightly more efficient, and +there are no API differences between the two classes. + +The legacy ``ObjectPaginator`` class +==================================== + +The ``Paginator`` and ``Page`` classes are new in the Django development +version, as of revision 7306. In previous versions, Django provided an +``ObjectPaginator`` class that offered similar functionality but wasn't as +convenient. This class still exists, for backwards compatibility, but Django +now issues a ``DeprecationWarning`` if you try to use it. diff --git a/docs/request_response.txt b/docs/request_response.txt index e50cfc5ea3..0e0f046a2d 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -141,6 +141,16 @@ All attributes except ``session`` should be considered read-only. The raw HTTP POST data. This is only useful for advanced processing. Use ``POST`` instead. +``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 `How Django processes a + request`_ for details. + +.. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request + + Methods ------- @@ -189,6 +199,23 @@ Methods Returns ``True`` if the request is secure; that is, if it was made with HTTPS. +``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 will + have to set this header manually to use this method. + QueryDict objects ----------------- diff --git a/docs/sessions.txt b/docs/sessions.txt index 6355524d2e..d8bac5b8d4 100644 --- a/docs/sessions.txt +++ b/docs/sessions.txt @@ -48,10 +48,10 @@ Using file-based sessions To use file-based sessions, set the ``SESSION_ENGINE`` setting to ``"django.contrib.sessions.backends.file"``. -You might also want to set the ``SESSION_FILE_PATH`` setting (which -defaults to ``/tmp``) to control where Django stores session files. Be -sure to check that your Web server has permissions to read and write to -this location. +You might also want to set the ``SESSION_FILE_PATH`` setting (which defaults +to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to control +where Django stores session files. Be sure to check that your Web server has +permissions to read and write to this location. Using cache-based sessions -------------------------- diff --git a/docs/settings.txt b/docs/settings.txt index ace893f1b5..fb2e04f1ea 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -185,8 +185,11 @@ ADMIN_MEDIA_PREFIX Default: ``'/media/'`` -The URL prefix for admin media -- CSS, JavaScript and images. Make sure to use -a trailing slash. +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). ADMINS ------ @@ -582,13 +585,14 @@ in standard language format. For example, U.S. English is ``"en-us"``. See the 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 the +you want (but should be different from ``SESSION_COOKIE_NAME``). See the `internationalization docs`_ for details. - LANGUAGES --------- @@ -753,7 +757,9 @@ ROOT_URLCONF Default: Not defined A string representing the full Python import path to your root URLconf. For example: -``"mydjangoapps.urls"``. See `How Django processes a request`_. +``"mydjangoapps.urls"``. Can be overridden on a per-request basis by +setting the attribute ``urlconf`` on the incoming ``HttpRequest`` +object. See `How Django processes a request`_ for details. .. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt index ebd6af26f8..f86acfe54d 100644 --- a/docs/syndication_feeds.txt +++ b/docs/syndication_feeds.txt @@ -245,6 +245,13 @@ request to the URL ``/rss/beats/0613/``: subclass of ``ObjectDoesNotExist``. Raising ``ObjectDoesNotExist`` in ``get_object()`` tells Django to produce a 404 error for that request. + **New in Django development version:** The ``get_object()`` method also + has a chance to handle the ``/rss/beats/`` url. In this case, ``bits`` + will be an empty list. In our example, ``len(bits) != 1`` and an + ``ObjectDoesNotExist`` exception will be raised, so ``/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 ``title()``, ``link()`` and ``description()`` methods. In the previous example, they were simple string class attributes, but this diff --git a/docs/templates.txt b/docs/templates.txt index d473a6f06f..ea9f3fb6b2 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -429,8 +429,9 @@ all block tags. For example:: # base.html {% autoescape off %} - <h1>{% block title %}</h1> + <h1>{% block title %}{% endblock %}</h1> {% block content %} + {% endblock %} {% endautoescape %} @@ -438,10 +439,11 @@ all block tags. For example:: {% extends "base.html" %} {% block title %}This & that{% endblock %} - {% block content %}<b>Hello!</b>{% endblock %} + {% block content %}{{ greeting }}{% endblock %} Because auto-escaping is turned off in the base template, it will also be -turned off in the child template, resulting in the following rendered HTML:: +turned off in the child template, resulting in the following rendered +HTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``:: <h1>This & that</h1> <b>Hello!</b> @@ -1222,14 +1224,20 @@ Built-in filter reference add ~~~ -Adds the arg to the value. +Adds the argument to the value. + +For example:: + + {{ value|add:"2" }} + +If ``value`` is ``4``, then the output will be ``6``. addslashes ~~~~~~~~~~ Adds slashes before quotes. Useful for escaping strings in CSV, for example. -**New in Django development version**: for escaping data in JavaScript strings, +**New in Django development version**: For escaping data in JavaScript strings, use the `escapejs`_ filter instead. capfirst @@ -1247,45 +1255,98 @@ 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"``. + 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'``. + default ~~~~~~~ -If value is unavailable, use given 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``. default_if_none ~~~~~~~~~~~~~~~ -If value is ``None``, use given default. +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"``. dictsort ~~~~~~~~ -Takes a list of dictionaries, returns that list sorted by the key given in +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}, + ] + dictsortreversed ~~~~~~~~~~~~~~~~ -Takes a list of dictionaries, returns that list sorted in reverse order by the -key given in the argument. +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. divisibleby ~~~~~~~~~~~ -Returns true if the value is divisible by the argument. +Returns ``True`` if the value is divisible by the argument. + +For example:: + + {{ value|divisibleby:"3" }} + +If ``value`` is ``21``, the output would be ``True``. escape ~~~~~~ -**New in Django development version:** The behaviour of this filter has -changed slightly in the development version (the affects are only applied -once, after all other filters). - Escapes a string's HTML. Specifically, it makes these replacements: * ``<`` is converted to ``<`` @@ -1304,6 +1365,10 @@ 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. + escapejs ~~~~~~~~ @@ -1319,16 +1384,38 @@ 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``. + 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'``. + 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. + floatformat ~~~~~~~~~~~ @@ -1383,10 +1470,16 @@ filter. get_digit ~~~~~~~~~ -Given a whole number, returns the requested digit of it, 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. +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``. iriencode ~~~~~~~~~ @@ -1401,7 +1494,14 @@ It's safe to use this filter on a string that has already gone through the join ~~~~ -Joins a list with a string, like Python's ``str.join(list)``. +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"``. last ~~~~ @@ -1410,15 +1510,34 @@ last 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"``. + length ~~~~~~ -Returns the length of the value. Useful for lists. +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``. length_is ~~~~~~~~~ -Returns a boolean of whether the value's length is the argument. +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``. linebreaks ~~~~~~~~~~ @@ -1427,6 +1546,13 @@ 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>Joe<br>is a +slug</p>``. + linebreaksbr ~~~~~~~~~~~~ @@ -1450,12 +1576,26 @@ 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``. + 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 ``"Joe"``, the output would be the list +``[u'J', u'o', u'e']``. If ``value`` is ``123``, the output will be the list +``[1, 2, 3]``. + phone2numeric ~~~~~~~~~~~~~ @@ -1492,17 +1632,32 @@ Example:: pprint ~~~~~~ -A wrapper around pprint.pprint -- for debugging, really. +A wrapper around `pprint.pprint`__ -- for debugging, really. + +__ http://www.python.org/doc/2.5/lib/module-pprint.html random ~~~~~~ -Returns a random item from the list. +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"``. removetags ~~~~~~~~~~ -Removes a space separated list of [X]HTML tags from the output. +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"``. rjust ~~~~~ @@ -1535,6 +1690,12 @@ 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"``. + stringformat ~~~~~~~~~~~~ @@ -1545,11 +1706,24 @@ 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"``. + 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"``. + time ~~~~ @@ -1558,10 +1732,17 @@ 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"``. + timesince ~~~~~~~~~ -Formats a date as the time since that date (i.e. "4 days, 6 hours"). +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*). @@ -1599,6 +1780,12 @@ 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 ..."``. + truncatewords_html ~~~~~~~~~~~~~~~~~~ @@ -1615,10 +1802,8 @@ unordered_list Recursively takes a self-nested list and returns an HTML unordered list -- WITHOUT opening and closing <ul> tags. -**Changed in Django development version** - -The format accepted by ``unordered_list`` has changed to an easier to -understand format. +**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 @@ -1644,6 +1829,12 @@ 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"``. + urlencode ~~~~~~~~~ @@ -1657,6 +1848,14 @@ 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>"``. + urlizetrunc ~~~~~~~~~~~ @@ -1667,6 +1866,14 @@ 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>'``. + wordcount ~~~~~~~~~ @@ -1679,6 +1886,16 @@ 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 + yesno ~~~~~ diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt index bd16fa2924..473fba1ef8 100644 --- a/docs/tutorial04.txt +++ b/docs/tutorial04.txt @@ -37,6 +37,12 @@ A quick rundown: form will alter data server-side. Whenever you create a form that alters data server-side, use ``method="post"``. This tip isn't specific to Django; it's just good Web development practice. + + * ``forloop.counter`` indicates how many times the ``for`` tag has + gone through its loop; for more information, see `the + documentation for the "for" tag`_. + +.. _the documentation for the "for" tag: ../templates/#for Now, let's create a Django view that handles the submitted data and does something with it. Remember, in `Tutorial 3`_, we created a URLconf for the diff --git a/docs/url_dispatch.txt b/docs/url_dispatch.txt index 789399de8d..053ee954a3 100644 --- a/docs/url_dispatch.txt +++ b/docs/url_dispatch.txt @@ -32,9 +32,11 @@ How Django processes a request When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute: - 1. Django looks at the ``ROOT_URLCONF`` setting in your `settings file`_. - This should be a string representing the full Python import path to your - URLconf. For example: ``"mydjangoapps.urls"``. + 1. Django determines the root URLConf module to use; ordinarily + this is the value of the ``ROOT_URLCONF`` setting in your + `settings file`_, but if the incoming ``HttpRequest`` object + has an attribute called ``urlconf``, its value will be used in + place of the ``ROOT_URLCONF`` setting. 2. Django loads that Python module and looks for the variable ``urlpatterns``. This should be a Python list, in the format returned by the function ``django.conf.urls.defaults.patterns()``. |
