diff options
| author | Honza Král <honza.kral@gmail.com> | 2009-07-15 07:19:10 +0000 |
|---|---|---|
| committer | Honza Král <honza.kral@gmail.com> | 2009-07-15 07:19:10 +0000 |
| commit | d0c3e19de5bf9d79f5436f8ddeccf9bea98d9306 (patch) | |
| tree | 5975afb05ef971945dd9afb9a977d5a59b04eaf4 /docs | |
| parent | f662801023605ff6fe44416271e39839894e7962 (diff) | |
[soc2009/model-validation] Merget to trunk at r11229
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@11233 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/_ext/djangodocs.py | 53 | ||||
| -rw-r--r-- | docs/_templates/layout.html | 2 | ||||
| -rw-r--r-- | docs/faq/admin.txt | 19 | ||||
| -rw-r--r-- | docs/howto/custom-model-fields.txt | 2 | ||||
| -rw-r--r-- | docs/howto/deployment/modpython.txt | 25 | ||||
| -rw-r--r-- | docs/howto/error-reporting.txt | 10 | ||||
| -rw-r--r-- | docs/ref/contrib/admin/index.txt | 34 | ||||
| -rw-r--r-- | docs/ref/contrib/contenttypes.txt | 4 | ||||
| -rw-r--r-- | docs/ref/databases.txt | 2 | ||||
| -rw-r--r-- | docs/ref/templates/builtins.txt | 27 | ||||
| -rw-r--r-- | docs/topics/http/urls.txt | 36 | ||||
| -rw-r--r-- | docs/topics/i18n.txt | 81 | ||||
| -rw-r--r-- | docs/topics/testing.txt | 29 |
13 files changed, 259 insertions, 65 deletions
diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py index 65a823e10b..af07a84f32 100644 --- a/docs/_ext/djangodocs.py +++ b/docs/_ext/djangodocs.py @@ -6,10 +6,16 @@ import docutils.nodes import docutils.transforms import sphinx import sphinx.addnodes -import sphinx.builder +try: + from sphinx import builders +except ImportError: + import sphinx.builder as builders import sphinx.directives import sphinx.environment -import sphinx.htmlwriter +try: + import sphinx.writers.html as sphinx_htmlwriter +except ImportError: + import sphinx.htmlwriter as sphinx_htmlwriter import sphinx.roles from docutils import nodes @@ -44,7 +50,7 @@ def setup(app): directivename = "django-admin-option", rolename = "djadminopt", indextemplate = "pair: %s; django-admin command-line option", - parse_node = lambda env, sig, signode: sphinx.directives.parse_option_desc(signode, sig), + parse_node = parse_django_adminopt_node, ) app.add_config_value('django_next_version', '0.0', True) app.add_directive('versionadded', parse_version_directive, 1, (1, 1, 1)) @@ -102,7 +108,7 @@ class SuppressBlockquotes(docutils.transforms.Transform): if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes): node.replace_self(node.children[0]) -class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator): +class DjangoHTMLTranslator(sphinx_htmlwriter.SmartyPantsHTMLTranslator): """ Django-specific reST to HTML tweaks. """ @@ -125,10 +131,10 @@ class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator): # def visit_literal_block(self, node): self.no_smarty += 1 - sphinx.htmlwriter.SmartyPantsHTMLTranslator.visit_literal_block(self, node) - + sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_literal_block(self, node) + def depart_literal_block(self, node): - sphinx.htmlwriter.SmartyPantsHTMLTranslator.depart_literal_block(self, node) + sphinx_htmlwriter.SmartyPantsHTMLTranslator.depart_literal_block(self, node) self.no_smarty -= 1 # @@ -162,7 +168,7 @@ class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator): # Give each section a unique ID -- nice for custom CSS hooks # This is different on docutils 0.5 vs. 0.4... - if hasattr(sphinx.htmlwriter.SmartyPantsHTMLTranslator, 'start_tag_with_title') and sphinx.__version__ == '0.4.2': + if hasattr(sphinx_htmlwriter.SmartyPantsHTMLTranslator, 'start_tag_with_title') and sphinx.__version__ == '0.4.2': def start_tag_with_title(self, node, tagname, **atts): node = { 'classes': node.get('classes', []), @@ -176,7 +182,7 @@ class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator): node['ids'] = ['s-' + i for i in old_ids] if sphinx.__version__ != '0.4.2': node['ids'].extend(old_ids) - sphinx.htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node) + sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node) node['ids'] = old_ids def parse_django_admin_node(env, sig, signode): @@ -186,6 +192,25 @@ def parse_django_admin_node(env, sig, signode): signode += sphinx.addnodes.desc_name(title, title) return sig +def parse_django_adminopt_node(env, sig, signode): + """A copy of sphinx.directives.CmdoptionDesc.parse_signature()""" + from sphinx import addnodes + from sphinx.directives.desc import option_desc_re + count = 0 + firstname = '' + for m in option_desc_re.finditer(sig): + optname, args = m.groups() + if count: + signode += addnodes.desc_addname(', ', ', ') + signode += addnodes.desc_name(optname, optname) + signode += addnodes.desc_addname(args, args) + if not count: + firstname = optname + count += 1 + if not firstname: + raise ValueError + return firstname + def monkeypatch_pickle_builder(): import shutil from os import path @@ -214,12 +239,12 @@ def monkeypatch_pickle_builder(): # copy the environment file from the doctree dir to the output dir # as needed by the web app - shutil.copyfile(path.join(self.doctreedir, sphinx.builder.ENV_PICKLE_FILENAME), - path.join(self.outdir, sphinx.builder.ENV_PICKLE_FILENAME)) + shutil.copyfile(path.join(self.doctreedir, builders.ENV_PICKLE_FILENAME), + path.join(self.outdir, builders.ENV_PICKLE_FILENAME)) # touch 'last build' file, used by the web application to determine # when to reload its environment and clear the cache - open(path.join(self.outdir, sphinx.builder.LAST_BUILD_FILENAME), 'w').close() + open(path.join(self.outdir, builders.LAST_BUILD_FILENAME), 'w').close() + + builders.PickleHTMLBuilder.handle_finish = handle_finish - sphinx.builder.PickleHTMLBuilder.handle_finish = handle_finish - diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index eb42298ab3..5bf1da6a37 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,6 +1,6 @@ {% extends "!layout.html" %} -{%- macro secondnav %} +{%- macro secondnav() %} {%- if prev %} « <a href="{{ prev.link|e }}" title="{{ prev.title|e }}">previous</a> {{ reldelim2 }} diff --git a/docs/faq/admin.txt b/docs/faq/admin.txt index c23bdd1fe9..4c7b570f00 100644 --- a/docs/faq/admin.txt +++ b/docs/faq/admin.txt @@ -37,20 +37,19 @@ Set the :setting:`CACHE_MIDDLEWARE_ANONYMOUS_ONLY` setting to ``True``. See the How do I automatically set a field's value to the user who last edited the object in the admin? ----------------------------------------------------------------------------------------------- -At this point, Django doesn't have an official way to do this. But it's an oft-requested -feature, so we're discussing how it can be implemented. The problem is we don't want to couple -the model layer with the admin layer with the request layer (to get the current user). It's a -tricky problem. - -One person hacked up a `solution that doesn't require patching Django`_, but note that it's an -unofficial solution, and there's no guarantee it won't break at some point. - -.. _solution that doesn't require patching Django: http://lukeplant.me.uk/blog.php?id=1107301634 +The :class:`ModelAdmin` class provides customization hooks that allow you to transform +an object as it saved, using details from the request. By extracting the current user +from the request, and customizing the :meth:`ModelAdmin.save_model` hook, you can update +an object to reflect the user that edited it. See :ref:`the documentation on ModelAdmin +methods <model-admin-methods>` for an example. How do I limit admin access so that objects can only be edited by the users who created them? --------------------------------------------------------------------------------------------- -See the answer to the previous question. +The :class:`ModelAdmin` class also provides customization hooks that allow you to control the +visibility and editability of objects in the admin. Using the same trick of extracting the +user from the request, the :meth:`ModelAdmin.queryset` and :meth:`ModelAdmin.has_change_permission` +can be used to control the visibility and editability of objects in the admin. My admin-site CSS and images showed up fine using the development server, but they're not displaying when using mod_python. --------------------------------------------------------------------------------------------------------------------------- diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt index 709ea49b87..9f798f14d5 100644 --- a/docs/howto/custom-model-fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -464,7 +464,7 @@ should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a list when you were expecting an object, for example) or a ``TypeError`` if your field does not support that type of lookup. For many fields, you can get by with handling the lookup types that need special handling for your field -and pass the rest of the :meth:`get_db_prep_lookup` method of the parent class. +and pass the rest to the :meth:`get_db_prep_lookup` method of the parent class. If you needed to implement ``get_db_prep_save()``, you will usually need to implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be diff --git a/docs/howto/deployment/modpython.txt b/docs/howto/deployment/modpython.txt index 9ba1c2f9fb..8b9a4d3696 100644 --- a/docs/howto/deployment/modpython.txt +++ b/docs/howto/deployment/modpython.txt @@ -6,8 +6,8 @@ How to use Django with Apache and mod_python .. highlight:: apache -The `mod_python`_ module for Apache_ can be used to deploy Django to a -production server, although it has been mostly superseded by the simpler +The `mod_python`_ module for Apache_ can be used to deploy Django to a +production server, although it has been mostly superseded by the simpler :ref:`mod_wsgi deployment option <howto-deployment-modwsgi>`. mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within @@ -378,3 +378,24 @@ as necessary. .. _Expat Causing Apache Crash: http://www.dscpl.com.au/articles/modpython-006.html .. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp .. _Getting mod_python Working: http://www.dscpl.com.au/articles/modpython-001.html + +If you get a UnicodeEncodeError +=============================== + +If you're taking advantage of the internationalization features of Django (see +:ref:`topics-i18n`) and you intend to allow users to upload files, you must +ensure that the environment used to start Apache is configured to accept +non-ASCII file names. If your environment is not correctly configured, you +will trigger ``UnicodeEncodeError`` exceptions when calling functions like +``os.path()`` on filenames that contain non-ASCII characters. + +To avoid these problems, the environment used to start Apache should contain +settings analogous to the following:: + + export LANG='en_US.UTF-8' + export LC_ALL='en_US.UTF-8' + +Consult the documentation for your operating system for the appropriate syntax +and location to put these configuration items; ``/etc/apache2/envvars`` is a +common location on Unix platforms. Once you have added these statements +to your environment, restart Apache. diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt index e0750ce327..246e7445d0 100644 --- a/docs/howto/error-reporting.txt +++ b/docs/howto/error-reporting.txt @@ -23,6 +23,10 @@ administrators immediate notification of any errors. The :setting:`ADMINS` will get a description of the error, a complete Python traceback, and details about the HTTP request that caused the error. +By default, Django will send email from root@localhost. However, some mail +providers reject all email from this address. To use a different sender +address, modify the :setting:`SERVER_EMAIL` setting. + To disable this behavior, just remove all entries from the :setting:`ADMINS` setting. @@ -33,12 +37,12 @@ Django can also be configured to email errors about broken links (404 "page not found" errors). Django sends emails about 404 errors when: * :setting:`DEBUG` is ``False`` - + * :setting:`SEND_BROKEN_LINK_EMAILS` is ``True`` - + * Your :setting:`MIDDLEWARE_CLASSES` setting includes ``CommonMiddleware`` (which it does by default). - + If those conditions are met, Django will e-mail the users listed in the :setting:`MANAGERS` setting whenever your code raises a 404 and the request has a referer. (It doesn't bother to e-mail for 404s that don't have a referer -- diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 64d9c52492..f0f5621fe6 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -704,6 +704,8 @@ objects. Templates can override or extend base admin templates as described in If you don't specify this attribute, a default template shipped with Django that provides the standard appearance is used. +.. _model-admin-methods: + ``ModelAdmin`` methods ---------------------- @@ -760,12 +762,19 @@ documented in :ref:`topics-http-urls`:: anything, so you'll usually want to prepend your custom URLs to the built-in ones. -Note, however, that the ``self.my_view`` function registered above will *not* -have any permission check done; it'll be accessible to the general public. Since -this is usually not what you want, Django provides a convience wrapper to check -permissions. This wrapper is :meth:`AdminSite.admin_view` (i.e. -``self.admin_site.admin_view`` inside a ``ModelAdmin`` instance); use it like -so:: +However, the ``self.my_view`` function registered above suffers from two +problems: + + * It will *not* perform and permission checks, so it will be accessible to + the general public. + * It will *not* provide any header details to prevent caching. This means if + the page retrieves data from the database, and caching middleware is + active, the page could show outdated information. + +Since this is usually not what you want, Django provides a convenience wrapper +to check permissions and mark the view as non-cacheable. This wrapper is +:meth:`AdminSite.admin_view` (i.e. ``self.admin_site.admin_view`` inside a +``ModelAdmin`` instance); use it like so: class MyModelAdmin(admin.ModelAdmin): def get_urls(self): @@ -779,7 +788,14 @@ Notice the wrapped view in the fifth line above:: (r'^my_view/$', self.admin_site.admin_view(self.my_view)) -This wrapping will protect ``self.my_view`` from unauthorized access. +This wrapping will protect ``self.my_view`` from unauthorized access and will +apply the ``django.views.decorators.cache.never_cache`` decorator to make sure +it is not cached if the cache middleware is active. + +If the page is cacheable, but you still want the permission check to be performed, +you can pass a ``cacheable=True`` argument to :meth:`AdminSite.admin_view`:: + + (r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True)) .. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs) @@ -792,7 +808,7 @@ return a subset of objects for this foreign key field based on the user:: class MyModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "car": - kwargs["queryset"] = Car.object.filter(owner=request.user) + kwargs["queryset"] = Car.objects.filter(owner=request.user) return db_field.formfield(**kwargs) return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) @@ -847,7 +863,7 @@ provided some extra mapping data that would not otherwise be available:: 'osm_data': self.get_osm_info(), } return super(MyModelAdmin, self).change_view(request, object_id, - extra_context=my_context)) + extra_context=my_context) ``ModelAdmin`` media definitions -------------------------------- diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt index 94900b3892..8a926afc97 100644 --- a/docs/ref/contrib/contenttypes.txt +++ b/docs/ref/contrib/contenttypes.txt @@ -177,9 +177,9 @@ The ``ContentTypeManager`` .. method:: models.ContentTypeManager.clear_cache() Clears an internal cache used by - :class:`~django.contrib.contenttypes.models.ContentType>` to keep track + :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 + :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. diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt index 9a35b6cb8f..007a7079b7 100644 --- a/docs/ref/databases.txt +++ b/docs/ref/databases.txt @@ -220,7 +220,7 @@ bytestrings (which shouldn't be too difficult) is the recommended solution. Should you decide to use ``utf8_bin`` collation for some of your tables with MySQLdb 1.2.1p2, you should still use ``utf8_collation_ci_swedish`` (the default) collation for the :class:`django.contrib.sessions.models.Session` -table (usually called ``django_session`` and the table +table (usually called ``django_session``) and the :class:`django.contrib.admin.models.LogEntry` table (usually called ``django_admin_log``). Those are the two standard tables that use :class:`~django.db.model.TextField` internally. diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 32b5984767..aedad6562f 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -101,6 +101,14 @@ You can use any number of values in a ``{% cycle %}`` tag, separated by spaces. Values enclosed in single (``'``) or double quotes (``"``) are treated as string literals, while values without quotes are treated as template variables. +Note that the variables included in the cycle will not be escaped. This is +because template tags do not escape their content. If you want to escape the +variables in the cycle, you must do so explicitly:: + + {% filter force_escape %} + {% cycle var1 var2 var3 %} + {% endfilter %} + For backwards compatibility, the ``{% cycle %}`` tag supports the much inferior old syntax from previous Django versions. You shouldn't use this in any new projects, but for the sake of the people who are still using it, here's what it @@ -160,8 +168,9 @@ Sample usage:: firstof ~~~~~~~ -Outputs the first variable passed that is not False. Outputs nothing if all the -passed variables are False. +Outputs the first variable passed that is not False, without escaping. + +Outputs nothing if all the passed variables are False. Sample usage:: @@ -170,11 +179,11 @@ Sample usage:: This is equivalent to:: {% if var1 %} - {{ var1 }} + {{ var1|safe }} {% else %}{% if var2 %} - {{ var2 }} + {{ var2|safe }} {% else %}{% if var3 %} - {{ var3 }} + {{ var3|safe }} {% endif %}{% endif %}{% endif %} You can also use a literal string as a fallback value in case all @@ -182,6 +191,14 @@ passed variables are False:: {% firstof var1 var2 var3 "fallback value" %} +Note that the variables included in the firstof tag will not be escaped. This +is because template tags do not escape their content. If you want to escape +the variables in the firstof tag, you must do so explicitly:: + + {% filter force_escape %} + {% firstof var1 var2 var3 "fallback value" %} + {% endfilter %} + .. templatetag:: for for diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt index 4248d4f02e..17978d4328 100644 --- a/docs/topics/http/urls.txt +++ b/docs/topics/http/urls.txt @@ -40,14 +40,14 @@ algorithm the system follows to determine which Python code to execute: this is the value of the ``ROOT_URLCONF`` setting, 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()``. - + 3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL. - + 4. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. The view gets passed an :class:`~django.http.HttpRequest` as its first argument and any values @@ -263,8 +263,15 @@ value should suffice. include ------- -A function that takes a full Python import path to another URLconf that should -be "included" in this place. See `Including other URLconfs`_ below. +A function that takes a full Python import path to another URLconf module that +should be "included" in this place. + +.. versionadded:: 1.1 + +:meth:``include`` also accepts as an argument an iterable that returns URL +patterns. + +See `Including other URLconfs`_ below. Notes on capturing text in URLs =============================== @@ -391,6 +398,25 @@ Django encounters ``include()``, it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing. +.. versionadded:: 1.1 + +Another posibility is to include additional URL patterns not by specifying the +URLconf Python module defining them as the `include`_ argument but by using +directly the pattern list as returned by `patterns`_ instead. For example:: + + from django.conf.urls.defaults import * + + extra_patterns = patterns('', + url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'), + url(r'charge/$', 'credit.views.charge', name='credit-charge'), + ) + + urlpatterns = patterns('', + url(r'^$', 'apps.main.views.homepage', name='site-homepage'), + (r'^help/', include('apps.help.urls')), + (r'^credit/', include(extra_patterns)), + ) + .. _`Django Web site`: http://www.djangoproject.com/ Captured parameters diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt index 86c03221aa..7bf51c11c5 100644 --- a/docs/topics/i18n.txt +++ b/docs/topics/i18n.txt @@ -223,7 +223,19 @@ Pluralization ~~~~~~~~~~~~~ Use the function ``django.utils.translation.ungettext()`` to specify pluralized -messages. Example:: +messages. + +``ungettext`` takes three arguments: the singular translation string, the plural +translation string and the number of objects. + +This function is useful when your need you Django application to be localizable +to languages where the number and complexity of `plural forms +<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is +greater than the two forms used in English ('object' for the singular and +'objects' for all the cases where ``count`` is different from zero, irrespective +of its value.) + +For example:: from django.utils.translation import ungettext def hello_world(request, count): @@ -232,9 +244,61 @@ messages. Example:: } return HttpResponse(page) -``ungettext`` takes three arguments: the singular translation string, the plural -translation string and the number of objects (which is passed to the -translation languages as the ``count`` variable). +In this example the number of objects is passed to the translation languages as +the ``count`` variable. + +Lets see a slightly more complex usage example:: + + from django.utils.translation import ungettext + + count = Report.objects.count() + if count == 1: + name = Report._meta.verbose_name + else: + name = Report._meta.verbose_name_plural + + text = ungettext( + 'There is %(count)d %(name)s available.', + 'There are %(count)d %(name)s available.', + count + ) % { + 'count': count, + 'name': name + } + +Here we reuse localizable, hopefully already translated literals (contained in +the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for +other parts of the sentence so all of it is consistently based on the +cardinality of the elements at play. + +.. _pluralization-var-notes: + +.. note:: + + When using this technique, make sure you use a single name for every + extrapolated variable included in the literal. In the example above note how + we used the ``name`` Python variable in both translation strings. This + example would fail:: + + from django.utils.translation import ungettext + from myapp.models import Report + + count = Report.objects.count() + d = { + 'count': count, + 'name': Report._meta.verbose_name + 'plural_name': Report._meta.verbose_name_plural + } + text = ungettext( + 'There is %(count)d %(name)s available.', + 'There are %(count)d %(plural_name)s available.', + count + ) % d + + You would get a ``a format specification for argument 'name', as in + 'msgstr[0]', doesn't exist in 'msgid'`` error when running + ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at + runtime. In template code ---------------- @@ -257,6 +321,8 @@ content that will require translation in the future:: <title>{% trans "myvar" noop %}</title> +Internally, inline translations use an ``ugettext`` call. + It's not possible to mix a template variable inside a string within ``{% trans %}``. If your translations require strings with variables (placeholders), use ``{% blocktrans %}``:: @@ -288,8 +354,11 @@ To pluralize, specify both the singular and plural forms with the There are {{ counter }} {{ name }} objects. {% endblocktrans %} -Internally, all block and inline translations use the appropriate -``ugettext`` / ``ungettext`` call. +When you use the pluralization feature and bind additional values to local +variables apart from the counter value that selects the translated literal to be +used, have in mind that the ``blocktrans`` construct is internally converted +to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext +variables <pluralization-var-notes>` apply. Each ``RequestContext`` has access to three translation-specific variables: diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt index 1256a61187..d235e0deba 100644 --- a/docs/topics/testing.txt +++ b/docs/topics/testing.txt @@ -479,7 +479,7 @@ arguments at time of construction: Once you have a ``Client`` instance, you can call any of the following methods: - .. method:: Client.get(path, data={}, follow=False) + .. method:: Client.get(path, data={}, follow=False, **extra) Makes a GET request on the provided ``path`` and returns a ``Response`` @@ -495,6 +495,17 @@ arguments at time of construction: /customers/details/?name=fred&age=7 + The ``extra`` keyword arguments parameter can be used to specify + headers to be sent in the request. For example:: + + >>> c = Client() + >>> c.get('/customers/details/', {'name': 'fred', 'age': 7}, + ... HTTP_X_REQUESTED_WITH='XMLHttpRequest') + + ...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the + details view, which is a good way to test code paths that use the + :meth:`django.http.HttpRequest.is_ajax()` method. + .. versionadded:: 1.1 If you already have the GET arguments in URL-encoded form, you can @@ -518,7 +529,7 @@ arguments at time of construction: >>> response.redirect_chain [(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)] - .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False) + .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) Makes a POST request on the provided ``path`` and returns a ``Response`` object, which is documented below. @@ -569,6 +580,8 @@ arguments at time of construction: Note that you should manually close the file after it has been provided to ``post()``. + The ``extra`` argument acts the same as for :meth:`Client.get`. + .. versionchanged:: 1.1 If the URL you request with a POST contains encoded parameters, these @@ -585,7 +598,7 @@ arguments at time of construction: and a ``redirect_chain`` attribute will be set in the response object containing tuples of the intermediate urls and status codes. - .. method:: Client.head(path, data={}, follow=False) + .. method:: Client.head(path, data={}, follow=False, **extra) .. versionadded:: 1.1 @@ -597,7 +610,7 @@ arguments at time of construction: and a ``redirect_chain`` attribute will be set in the response object containing tuples of the intermediate urls and status codes. - .. method:: Client.options(path, data={}, follow=False) + .. method:: Client.options(path, data={}, follow=False, **extra) .. versionadded:: 1.1 @@ -608,7 +621,9 @@ arguments at time of construction: and a ``redirect_chain`` attribute will be set in the response object containing tuples of the intermediate urls and status codes. - .. method:: Client.put(path, data={}, content_type=MULTIPART_CONTENT, follow=False) + The ``extra`` argument acts the same as for :meth:`Client.get`. + + .. method:: Client.put(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) .. versionadded:: 1.1 @@ -620,7 +635,7 @@ arguments at time of construction: and a ``redirect_chain`` attribute will be set in the response object containing tuples of the intermediate urls and status codes. - .. method:: Client.delete(path, follow=False) + .. method:: Client.delete(path, follow=False, **extra) .. versionadded:: 1.1 @@ -631,6 +646,8 @@ arguments at time of construction: and a ``redirect_chain`` attribute will be set in the response object containing tuples of the intermediate urls and status codes. + The ``extra`` argument acts the same as for :meth:`Client.get`. + .. method:: Client.login(**credentials) .. versionadded:: 1.0 |
