From 5ea9b7258513319291513dde105a066df1926a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Honza=20Kr=C3=A1l?= Date: Sun, 21 Jun 2009 19:24:30 +0000 Subject: [PATCH] Merged to trunk at r11079 git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@11083 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/templatetags/cache.py | 4 ++- docs/faq/install.txt | 2 +- docs/howto/deployment/modwsgi.txt | 7 +++-- docs/intro/overview.txt | 10 +++---- docs/intro/tutorial01.txt | 36 ++++++++++++------------ docs/intro/tutorial02.txt | 8 +++--- docs/intro/tutorial03.txt | 13 +++++---- docs/ref/contrib/admin/index.txt | 2 +- docs/ref/contrib/contenttypes.txt | 4 +-- docs/ref/django-admin.txt | 6 +++- docs/ref/settings.txt | 16 +++++------ docs/releases/1.0-porting-guide.txt | 2 +- docs/topics/db/queries.txt | 8 ++++-- docs/topics/forms/modelforms.txt | 2 +- docs/topics/http/middleware.txt | 15 ++++++---- docs/topics/http/sessions.txt | 3 ++ docs/topics/testing.txt | 12 ++++---- tests/regressiontests/templates/tests.py | 7 +++-- 19 files changed, 91 insertions(+), 67 deletions(-) diff --git a/AUTHORS b/AUTHORS index 69eaa24cdc..b1cbdc813e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -226,6 +226,7 @@ answer newbie questions, and generally made Django that much better: Ian G. Kelly Ryan Kelly Thomas Kerpe + Wiley Kestner Ossama M. Khayat Ben Khoo Garth Kidd diff --git a/django/templatetags/cache.py b/django/templatetags/cache.py index 9c6ca76854..387dd8721c 100644 --- a/django/templatetags/cache.py +++ b/django/templatetags/cache.py @@ -3,6 +3,7 @@ from django.template import resolve_variable from django.core.cache import cache from django.utils.encoding import force_unicode from django.utils.http import urlquote +from django.utils.hashcompat import md5_constructor register = Library() @@ -23,7 +24,8 @@ class CacheNode(Node): except (ValueError, TypeError): raise TemplateSyntaxError('"cache" tag got a non-integer timeout value: %r' % expire_time) # Build a unicode key for this fragment and all vary-on's. - cache_key = u':'.join([self.fragment_name] + [urlquote(resolve_variable(var, context)) for var in self.vary_on]) + args = md5_constructor(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on])) + cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest()) value = cache.get(cache_key) if value is None: value = self.nodelist.render(context) diff --git a/docs/faq/install.txt b/docs/faq/install.txt index 1c6ef43d7d..fb8005c7e7 100644 --- a/docs/faq/install.txt +++ b/docs/faq/install.txt @@ -26,7 +26,7 @@ For a development environment -- if you just want to experiment with Django -- you don't need to have a separate Web server installed; Django comes with its own lightweight development server. For a production environment, Django follows the WSGI_ spec, which means it can run on a variety of server -platforms. See :ref:`Deplying Django ` for some +platforms. See :ref:`Deploying Django ` for some popular alternatives. Also, the `server arrangements wiki page`_ contains details for several deployment strategies. diff --git a/docs/howto/deployment/modwsgi.txt b/docs/howto/deployment/modwsgi.txt index c35fba3183..902e312551 100644 --- a/docs/howto/deployment/modwsgi.txt +++ b/docs/howto/deployment/modwsgi.txt @@ -51,8 +51,9 @@ If your project is not on your ``PYTHONPATH`` by default you can add:: sys.path.append('/usr/local/django') -just above the ``import`` line to place your project on the path. Remember to -replace 'mysite.settings' with your correct settings file. +just above the final ``import`` line to place your project on the path. Remember to +replace 'mysite.settings' with your correct settings file, and '/usr/local/django' +with your own project's location. See the :ref:`Apache/mod_python documentation` for directions on serving static media, and the `mod_wsgi documentation`_ for an @@ -65,4 +66,4 @@ For more details, see the `mod_wsgi documentation`_, which explains the above in more detail, and walks through all the various options you've got when deploying under mod_wsgi. -.. _mod_wsgi documentation: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango \ No newline at end of file +.. _mod_wsgi documentation: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango diff --git a/docs/intro/overview.txt b/docs/intro/overview.txt index 297dd38f79..594c9fe582 100644 --- a/docs/intro/overview.txt +++ b/docs/intro/overview.txt @@ -144,10 +144,10 @@ as registering your model in the admin site:: headline = models.CharField(max_length=200) content = models.TextField() reporter = models.ForeignKey(Reporter) - + # In admin.py in the same directory... - + import models from django.contrib import admin @@ -243,9 +243,9 @@ might look like:

Articles for {{ year }}

{% for article in article_list %} -

{{ article.headline }}

-

By {{ article.reporter.full_name }}

-

Published {{ article.pub_date|date:"F j, Y" }}

+

{{ article.headline }}

+

By {{ article.reporter.full_name }}

+

Published {{ article.pub_date|date:"F j, Y" }}

{% endfor %} {% endblock %} diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt index c0ad3dd8cf..ae4af665f1 100644 --- a/docs/intro/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -42,13 +42,13 @@ code, then run the command ``django-admin.py startproject mysite``. This will create a ``mysite`` directory in your current directory. .. admonition:: Mac OS X permissions - + If you're using Mac OS X, you may see the message "permission denied" when you try to run ``django-admin.py startproject``. This is because, on Unix-based systems like OS X, a file must be marked as "executable" before it can be run as a program. To do this, open Terminal.app and navigate (using the ``cd`` command) to the directory where :ref:`django-admin.py - ` is installed, then run the command + ` is installed, then run the command ``chmod +x django-admin.py``. .. note:: @@ -90,14 +90,14 @@ These files are: * :file:`__init__.py`: An empty file that tells Python that this directory should be considered a Python package. (Read `more about packages`_ in the official Python docs if you're a Python beginner.) - + * :file:`manage.py`: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about :file:`manage.py` in :ref:`ref-django-admin`. - + * :file:`settings.py`: Settings/configuration for this Django project. :ref:`topics-settings` will tell you all about how settings work. - + * :file:`urls.py`: The URL declarations for this Django project; a "table of contents" of your Django-powered site. You can read more about URLs in :ref:`topics-http-urls`. @@ -134,22 +134,22 @@ It worked! .. admonition:: Changing the port By default, the :djadmin:`runserver` command starts the development server - on the internal IP at port 8000. - + on the internal IP at port 8000. + If you want to change the server's port, pass it as a command-line argument. For instance, this command starts the server on port 8080: - + .. code-block:: bash python manage.py runserver 8080 - + If you want to change the server's IP, pass it along with the port. So to listen on all public IPs (useful if you want to show off your work on other computers), use: - + .. code-block:: bash - + python manage.py runserver 0.0.0.0:8000 Full docs for the development server can be found in the @@ -164,21 +164,21 @@ database's connection parameters: * :setting:`DATABASE_ENGINE` -- Either 'postgresql_psycopg2', 'mysql' or 'sqlite3'. Other backends are :setting:`also available `. - + * :setting:`DATABASE_NAME` -- The name of your database. If you're using SQLite, the database will be a file on your computer; in that case, ``DATABASE_NAME`` should be the full absolute path, including filename, of that file. If the file doesn't exist, it will automatically be created when you synchronize the database for the first time (see below). - - When specifying the path, always use forward slashes, even on Windows + + When specifying the path, always use forward slashes, even on Windows (e.g. ``C:/homes/user/mysite/sqlite3.db``). - + * :setting:`DATABASE_USER` -- Your database username (not used for SQLite). - + * :setting:`DATABASE_PASSWORD` -- Your database password (not used for SQLite). - + * :setting:`DATABASE_HOST` -- The host your database is on. Leave this as an empty string if your database server is on the same physical machine (not used for SQLite). @@ -594,7 +594,7 @@ your models, not only for your own sanity when dealing with the interactive prompt, but also because objects' representations are used throughout Django's automatically-generated admin. -.. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not +.. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not :meth:`~django.db.models.Model.__str__`? If you're familiar with Python, you might be in the habit of adding diff --git a/docs/intro/tutorial02.txt b/docs/intro/tutorial02.txt index fa1912213a..203c945c02 100644 --- a/docs/intro/tutorial02.txt +++ b/docs/intro/tutorial02.txt @@ -86,8 +86,8 @@ Enter the admin site ==================== Now, try logging in. (You created a superuser account in the first part of this -tutorial, remember? If you didn't create one or forgot the password you can -:ref:`create another one `.) You should see +tutorial, remember? If you didn't create one or forgot the password you can +:ref:`create another one `.) You should see the Django admin index page: .. image:: _images/admin02t.png @@ -238,8 +238,8 @@ the admin page doesn't display choices. Yet. -There are two ways to solve this problem. The first register ``Choice`` with the -admin just as we did with ``Poll``. That's easy:: +There are two ways to solve this problem. The first is to register ``Choice`` +with the admin just as we did with ``Poll``. That's easy:: from mysite.polls.models import Choice diff --git a/docs/intro/tutorial03.txt b/docs/intro/tutorial03.txt index 867b7d1224..f4ef5f76fe 100644 --- a/docs/intro/tutorial03.txt +++ b/docs/intro/tutorial03.txt @@ -71,7 +71,7 @@ For more on :class:`~django.http.HttpRequest` objects, see the :ref:`ref-request-response`. For more details on URLconfs, see the :ref:`topics-http-urls`. -When you ran ``python django-admin.py startproject mysite`` at the beginning of +When you ran ``django-admin.py startproject mysite`` at the beginning of Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also automatically set your :setting:`ROOT_URLCONF` setting (in ``settings.py``) to point at that file:: @@ -98,8 +98,7 @@ This is worth a review. When somebody requests a page from your Web site -- say, the :setting:`ROOT_URLCONF` setting. It finds the variable named ``urlpatterns`` and traverses the regular expressions in order. When it finds a regular expression that matches -- ``r'^polls/(?P\d+)/$'`` -- it loads the -associated Python package/module: ``mysite.polls.views.detail``. That -corresponds to the function ``detail()`` in ``mysite/polls/views.py``. Finally, +function ``detail()`` from ``mysite/polls/views.py``. Finally, it calls that ``detail()`` function like so:: detail(request=, poll_id='23') @@ -468,7 +467,10 @@ Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change ``mysite/urls.py`` to remove the poll-specific URLs and insert an :func:`~django.conf.urls.defaults.include`:: - (r'^polls/', include('mysite.polls.urls')), + ... + urlpatterns = patterns('', + (r'^polls/', include('mysite.polls.urls')), + ... :func:`~django.conf.urls.defaults.include`, simply, references another URLconf. Note that the regular expression doesn't have a ``$`` (end-of-string match @@ -486,7 +488,8 @@ Here's what happens if a user goes to "/polls/34/" in this system: further processing. Now that we've decoupled that, we need to decouple the 'mysite.polls.urls' -URLconf by removing the leading "polls/" from each line:: +URLconf by removing the leading "polls/" from each line, and removing the +lines registering the admin site:: urlpatterns = patterns('mysite.polls.views', (r'^$', 'index'), diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 6719527d2f..bad7dec390 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -347,7 +347,7 @@ A few special cases to note about ``list_display``: birthday = models.DateField() def born_in_fifties(self): - return self.birthday.strftime('%Y')[:3] == 5 + return self.birthday.strftime('%Y')[:3] == '195' born_in_fifties.boolean = True class PersonAdmin(admin.ModelAdmin): diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt index f814eccaab..94900b3892 100644 --- a/docs/ref/contrib/contenttypes.txt +++ b/docs/ref/contrib/contenttypes.txt @@ -347,8 +347,8 @@ doesn't work with a :class:`~django.contrib.contenttypes.generic.GenericRelation`. For example, you might be tempted to try something like:: - Bookmark.objects.aggregate(Count('tags')) - + Bookmark.objects.aggregate(Count('tags')) + This will not work correctly, however. The generic relation adds extra filters to the queryset to ensure the correct content type, but the ``aggregate`` method doesn't take them into account. For now, if you need aggregates on generic diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 71804cf022..f657db20f4 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -611,7 +611,11 @@ sqlsequencereset 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. +Sequences are indexes used by some database engines to track the next available +number for automatically incremented fields. + +Use this command to generate SQL which will fix cases where a sequence is out +of sync with its automatically incremented field data. startapp ------------------ diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 0cca6fe05d..e8c673d995 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -195,7 +195,7 @@ DATABASE_NAME Default: ``''`` (Empty string) The name of the database to use. For SQLite, it's the full path to the database -file. When specifying the path, always use forward slashes, even on Windows +file. When specifying the path, always use forward slashes, even on Windows (e.g. ``C:/homes/user/mysite/sqlite3.db``). .. setting:: DATABASE_OPTIONS @@ -228,7 +228,7 @@ 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 ------------- @@ -251,7 +251,7 @@ See also ``DATETIME_FORMAT``, ``TIME_FORMAT``, ``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. .. setting:: DATETIME_FORMAT - + DATETIME_FORMAT --------------- @@ -330,7 +330,7 @@ isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the DEFAULT_FILE_STORAGE -------------------- -Default: ``django.core.files.storage.FileSystemStorage`` +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`. @@ -519,14 +519,14 @@ system's standard umask. .. warning:: **Always prefix the mode with a 0.** - + If you're not familiar with file modes, please note that the leading ``0`` is very important: it indicates an octal number, which is the way that modes must be specified. If you try to use ``644``, you'll get totally incorrect behavior. - -.. _documentation for os.chmod: http://docs.python.org/lib/os-file-dir.html + +.. _documentation for os.chmod: http://docs.python.org/lib/os-file-dir.html .. setting:: FIXTURE_DIRS @@ -1153,7 +1153,7 @@ running in the correct environment. 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 diff --git a/docs/releases/1.0-porting-guide.txt b/docs/releases/1.0-porting-guide.txt index 9a5d487f38..f87da1c8d0 100644 --- a/docs/releases/1.0-porting-guide.txt +++ b/docs/releases/1.0-porting-guide.txt @@ -677,7 +677,7 @@ load_data:: management.call_command('flush', verbosity=0, interactive=False) management.call_command('loaddata', 'test_data', verbosity=0) -Subcommands must now preceed options +Subcommands must now precede options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``django-admin.py`` and ``manage.py`` now require subcommands to precede diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 4aa54261c4..5e353b2ec3 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -278,7 +278,7 @@ For example, this returns the first 5 objects (``LIMIT 5``):: This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):: >>> Entry.objects.all()[5:10] - + Negative indexing (i.e. ``Entry.objects.all()[-1]``) is not supported. Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't @@ -945,11 +945,15 @@ in the :ref:`related objects reference `. Removes all objects from the related object set. To assign the members of a related set in one fell swoop, just assign to it -from any iterable object. Example:: +from any iterable object. The iterable can contain object instances, or just +a list of primary key values. For example:: b = Blog.objects.get(id=1) b.entry_set = [e1, e2] +In this example, ``e1`` and ``e2`` can be full Entry instances, or integer +primary key values. + If the ``clear()`` method is available, any pre-existing objects will be removed from the ``entry_set`` before all objects in the iterable (in this case, a list) are added to the set. If the ``clear()`` method is *not* diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index 690ca7f391..8acb3f7646 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -611,7 +611,7 @@ Just like with ``ModelForms``, by default the ``clean()`` method of a the unique constraints on your model (either ``unique``, ``unique_together`` or ``unique_for_date|month|year``). If you want to overide the ``clean()`` method on a ``model_formset`` and maintain this validation, you must call the parent -classes ``clean`` method:: +class's ``clean`` method:: class MyModelFormSet(BaseModelFormSet): def clean(self): diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt index 9040533f33..19facb8371 100644 --- a/docs/topics/http/middleware.txt +++ b/docs/topics/http/middleware.txt @@ -107,15 +107,18 @@ middleware is always called on every response. ``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the :class:`~django.http. HttpResponse` object returned by a Django view. -``process_response()`` should return an :class:`~django.http. HttpResponse` +``process_response()`` must return an :class:`~django.http. HttpResponse` object. It could alter the given ``response``, or it could create and return a brand-new :class:`~django.http. HttpResponse`. -Remember that your middleware will not be called if another middleware object -returns a response before you. But unlike ``process_request()`` and -``process_view()``, during the response phase the classes are applied in reverse -order, from the bottom up. This means classes defined at the end of -:setting:`MIDDLEWARE_CLASSES` will be run first. +Unlike the ``process_request()`` and ``process_view()`` methods, the +``process_response()`` method is always called, even if the ``process_request()`` +and ``process_view()`` methods of the same middleware class were skipped because +an earlier middleware method returned an :class:`~django.http. HttpResponse` +(this means that your ``process_response()`` method cannot rely on setup done in +``process_request()``, for example). In addition, during the response phase the +classes are applied in reverse order, from the bottom up. This means classes +defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first. .. _exception-middleware: diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index fa3864a7c2..d3956504c7 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -4,6 +4,9 @@ How to use sessions =================== +.. module:: django.contrib.sessions + :synopsis: Provides session management for Django projects. + Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt index 0410049297..1256a61187 100644 --- a/docs/topics/testing.txt +++ b/docs/topics/testing.txt @@ -139,8 +139,8 @@ In the case of model tests, note that the test runner takes care of creating its own test database. That is, any test that accesses a database -- by creating and saving model instances, for example -- will not affect your production database. However, the database is not refreshed between doctests, -so if your doctest requires a certain state you should consider flushin the -database or loading a fixture. (See the section on fixtures, below, for more +so if your doctest requires a certain state you should consider flushing the +database or loading a fixture. (See the section on fixtures, below, for more on this.) Note that to use this feature, the database user Django is connecting as must have ``CREATE DATABASE`` rights. @@ -1042,7 +1042,7 @@ applications: Asserts that a ``Response`` instance produced the given ``status_code`` and that ``text`` does not appears in the content of the response. -.. method:: assertFormError(response, form, field, errors) +.. method:: TestCase.assertFormError(response, form, field, errors) Asserts that a field on a form raises the provided list of errors when rendered on the form. @@ -1057,19 +1057,19 @@ applications: ``errors`` is an error string, or a list of error strings, that are expected as a result of form validation. -.. method:: assertTemplateUsed(response, template_name) +.. method:: TestCase.assertTemplateUsed(response, template_name) Asserts that the template with the given name was used in rendering the response. The name is a string such as ``'admin/index.html'``. -.. method:: assertTemplateNotUsed(response, template_name) +.. method:: TestCase.assertTemplateNotUsed(response, template_name) Asserts that the template with the given name was *not* used in rendering the response. -.. method:: assertRedirects(response, expected_url, status_code=302, target_status_code=200) +.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200) Asserts that the response return a ``status_code`` redirect status, it redirected to ``expected_url`` (including any GET data), and the final diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 953e8faa1a..9c01b492e3 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -69,7 +69,7 @@ class SomeException(Exception): class SomeOtherException(Exception): pass - + class ContextStackException(Exception): pass @@ -629,7 +629,7 @@ class Templates(unittest.TestCase): # Logically the same as above, just written with explicit # ifchanged for the day. - 'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), + 'ifchanged-param05': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), # Test the else clause of ifchanged. 'ifchanged-else01': ('{% for id in ids %}{{ id }}{% ifchanged id %}-first{% else %}-other{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-first,1-other,2-first,2-other,2-other,3-first,'), @@ -1014,6 +1014,9 @@ class Templates(unittest.TestCase): # Regression test for #7460. 'cache16': ('{% load cache %}{% cache 1 foo bar %}{% endcache %}', {'foo': 'foo', 'bar': 'with spaces'}, ''), + # Regression test for #11270. + 'cache17': ('{% load cache %}{% cache 10 long_cache_key poem %}Some Content{% endcache %}', {'poem': 'Oh freddled gruntbuggly/Thy micturations are to me/As plurdled gabbleblotchits/On a lurgid bee/That mordiously hath bitled out/Its earted jurtles/Into a rancid festering/Or else I shall rend thee in the gobberwarts with my blurglecruncheon/See if I dont.'}, 'Some Content'), + ### AUTOESCAPE TAG ############################################## 'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"), 'autoescape-tag02': ("{% autoescape off %}{{ first }}{% endautoescape %}", {"first": "hello"}, "hello"),