<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>django/conf/app_template/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/css/dashboard.css</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/css/forms.css</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/css/layout.css</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/css/login.css</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/css/widgets.css</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/deleted-overlay.gif</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/inline-delete-8bit.png</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/inline-delete.png</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/inline-restore-8bit.png</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/inline-restore.png</filename>
    </added>
    <added>
      <filename>django/contrib/admin/media/img/admin/inline-splitter-bg.gif</filename>
    </added>
    <added>
      <filename>django/contrib/admin/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/admin/urls.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/create_superuser.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/decorators.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/forms.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/management.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/middleware.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/auth/views.py</filename>
    </added>
    <added>
      <filename>django/contrib/comments/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/contenttypes/__init__.py</filename>
    </added>
    <added>
      <filename>django/contrib/contenttypes/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/flatpages/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/redirects/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/sessions/__init__.py</filename>
    </added>
    <added>
      <filename>django/contrib/sessions/middleware.py</filename>
    </added>
    <added>
      <filename>django/contrib/sessions/models.py</filename>
    </added>
    <added>
      <filename>django/contrib/sites/__init__.py</filename>
    </added>
    <added>
      <filename>django/contrib/sites/management.py</filename>
    </added>
    <added>
      <filename>django/contrib/sites/models.py</filename>
    </added>
    <added>
      <filename>django/core/signals.py</filename>
    </added>
    <added>
      <filename>django/db/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/ado_mssql/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/ado_mssql/base.py</filename>
    </added>
    <added>
      <filename>django/db/backends/ado_mssql/client.py</filename>
    </added>
    <added>
      <filename>django/db/backends/ado_mssql/creation.py</filename>
    </added>
    <added>
      <filename>django/db/backends/ado_mssql/introspection.py</filename>
    </added>
    <added>
      <filename>django/db/backends/dummy/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/dummy/base.py</filename>
    </added>
    <added>
      <filename>django/db/backends/dummy/client.py</filename>
    </added>
    <added>
      <filename>django/db/backends/dummy/creation.py</filename>
    </added>
    <added>
      <filename>django/db/backends/dummy/introspection.py</filename>
    </added>
    <added>
      <filename>django/db/backends/mysql/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/mysql/base.py</filename>
    </added>
    <added>
      <filename>django/db/backends/mysql/client.py</filename>
    </added>
    <added>
      <filename>django/db/backends/mysql/creation.py</filename>
    </added>
    <added>
      <filename>django/db/backends/mysql/introspection.py</filename>
    </added>
    <added>
      <filename>django/db/backends/postgresql/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/postgresql/base.py</filename>
    </added>
    <added>
      <filename>django/db/backends/postgresql/client.py</filename>
    </added>
    <added>
      <filename>django/db/backends/postgresql/creation.py</filename>
    </added>
    <added>
      <filename>django/db/backends/postgresql/introspection.py</filename>
    </added>
    <added>
      <filename>django/db/backends/sqlite3/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/backends/sqlite3/base.py</filename>
    </added>
    <added>
      <filename>django/db/backends/sqlite3/client.py</filename>
    </added>
    <added>
      <filename>django/db/backends/sqlite3/creation.py</filename>
    </added>
    <added>
      <filename>django/db/backends/sqlite3/introspection.py</filename>
    </added>
    <added>
      <filename>django/db/backends/util.py</filename>
    </added>
    <added>
      <filename>django/db/models/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/models/base.py</filename>
    </added>
    <added>
      <filename>django/db/models/fields/__init__.py</filename>
    </added>
    <added>
      <filename>django/db/models/fields/related.py</filename>
    </added>
    <added>
      <filename>django/db/models/loading.py</filename>
    </added>
    <added>
      <filename>django/db/models/manager.py</filename>
    </added>
    <added>
      <filename>django/db/models/manipulators.py</filename>
    </added>
    <added>
      <filename>django/db/models/options.py</filename>
    </added>
    <added>
      <filename>django/db/models/query.py</filename>
    </added>
    <added>
      <filename>django/db/models/related.py</filename>
    </added>
    <added>
      <filename>django/db/models/signals.py</filename>
    </added>
    <added>
      <filename>django/db/transaction.py</filename>
    </added>
    <added>
      <filename>django/dispatch/__init__.py</filename>
    </added>
    <added>
      <filename>django/dispatch/dispatcher.py</filename>
    </added>
    <added>
      <filename>django/dispatch/errors.py</filename>
    </added>
    <added>
      <filename>django/dispatch/license.txt</filename>
    </added>
    <added>
      <filename>django/dispatch/robust.py</filename>
    </added>
    <added>
      <filename>django/dispatch/robustapply.py</filename>
    </added>
    <added>
      <filename>django/dispatch/saferef.py</filename>
    </added>
    <added>
      <filename>django/forms/__init__.py</filename>
    </added>
    <added>
      <filename>django/http/__init__.py</filename>
    </added>
    <added>
      <filename>django/middleware/transaction.py</filename>
    </added>
    <added>
      <filename>django/shortcuts/__init__.py</filename>
    </added>
    <added>
      <filename>django/template/__init__.py</filename>
    </added>
    <added>
      <filename>django/template/context.py</filename>
    </added>
    <added>
      <filename>django/template/defaultfilters.py</filename>
    </added>
    <added>
      <filename>django/template/defaulttags.py</filename>
    </added>
    <added>
      <filename>django/template/loader.py</filename>
    </added>
    <added>
      <filename>django/template/loader_tags.py</filename>
    </added>
    <added>
      <filename>django/template/loaders/__init__.py</filename>
    </added>
    <added>
      <filename>django/template/loaders/app_directories.py</filename>
    </added>
    <added>
      <filename>django/template/loaders/eggs.py</filename>
    </added>
    <added>
      <filename>django/template/loaders/filesystem.py</filename>
    </added>
    <added>
      <filename>django/utils/termcolors.py</filename>
    </added>
    <added>
      <filename>docs/transactions.txt</filename>
    </added>
    <added>
      <filename>examples/__init__.py</filename>
    </added>
    <added>
      <filename>examples/hello/__init__.py</filename>
    </added>
    <added>
      <filename>examples/hello/urls.py</filename>
    </added>
    <added>
      <filename>examples/hello/views.py</filename>
    </added>
    <added>
      <filename>examples/manage.py</filename>
    </added>
    <added>
      <filename>examples/settings.py</filename>
    </added>
    <added>
      <filename>examples/urls.py</filename>
    </added>
    <added>
      <filename>examples/views.py</filename>
    </added>
    <added>
      <filename>extras/README.TXT</filename>
    </added>
    <added>
      <filename>extras/django_bash_completion</filename>
    </added>
    <added>
      <filename>tests/modeltests/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/basic/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/basic/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/choices/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/choices/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_columns/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_columns/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_managers/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_managers/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_methods/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_methods/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_pk/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/custom_pk/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/field_defaults/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/field_defaults/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/get_latest/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/get_latest/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/invalid_models/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/invalid_models/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/lookup/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/lookup/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_and_m2o/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_and_m2o/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_intermediary/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_intermediary/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_multiple/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_multiple/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_recursive/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2m_recursive/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2o_recursive/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2o_recursive/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2o_recursive2/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/m2o_recursive2/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/manipulators/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/manipulators/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_many/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_many/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_one/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_one/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_one_null/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/many_to_one_null/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/model_inheritance/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/model_inheritance/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/mutually_referential/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/mutually_referential/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/one_to_one/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/one_to_one/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/or_lookups/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/or_lookups/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/ordering/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/ordering/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/pagination/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/pagination/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/properties/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/properties/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/repr/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/repr/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/reserved_names/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/reserved_names/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/reverse_lookup/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/reverse_lookup/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/save_delete_hooks/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/save_delete_hooks/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/transactions/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/transactions/models.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/validation/__init__.py</filename>
    </added>
    <added>
      <filename>tests/modeltests/validation/models.py</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -71,6 +71,7 @@ answer newbie questions, and generally made Django that much better:
     lakin.wecker@gmail.com
     Stuart Langridge &lt;http://www.kryogenix.org/&gt;
     Eugene Lazutkin &lt;http://lazutkin.com/blog/&gt;
+    Christopher Lenz &lt;http://www.cmlenz.net/&gt;
     limodou
     Martin Maney &lt;http://www.chipy.org/Martin_Maney&gt;
     Manuzhai
@@ -79,6 +80,7 @@ answer newbie questions, and generally made Django that much better:
     mattycakes@gmail.com
     Jason McBrayer &lt;http://www.carcosa.net/jason/&gt;
     michael.mcewan@gmail.com
+    mir@noris.de
     mmarshall
     Eric Moritz &lt;http://eric.themoritzfamily.com/&gt;
     Robin Munn &lt;http://www.geekforgod.com/&gt;
@@ -102,7 +104,9 @@ answer newbie questions, and generally made Django that much better:
     Aaron Swartz &lt;http://www.aaronsw.com/&gt;
     Tom Tobin
     Joe Topjian &lt;http://joe.terrarum.net/geek/code/python/django/&gt;
+    Malcolm Tredinnick
     Amit Upadhyay
+    Geert Vanderkelen
     Milton Waddams
     Rachel Willmer &lt;http://www.willmer.com/kb/&gt;
     wojtek</diff>
      <filename>AUTHORS</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-VERSION = (0, 9, 1, 'SVN')
+VERSION = (0, 95, 'post-magic-removal')</diff>
      <filename>django/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,17 +1,17 @@
 &quot;Daily cleanup file&quot;
 
-from django.core.db import db
+from django.db import backend, connection, transaction
 
 DOCUMENTATION_DIRECTORY = '/home/html/documentation/'
 
 def clean_up():
     # Clean up old database records
-    cursor = db.cursor()
+    cursor = connection.cursor()
     cursor.execute(&quot;DELETE FROM %s WHERE %s &lt; NOW()&quot; % \
-        (db.quote_name('core_sessions'), db.quote_name('expire_date')))
+        (backend.quote_name('core_sessions'), backend.quote_name('expire_date')))
     cursor.execute(&quot;DELETE FROM %s WHERE %s &lt; NOW() - INTERVAL '1 week'&quot; % \
-        (db.quote_name('registration_challenges'), db.quote_name('request_date')))
-    db.commit()
+        (backend.quote_name('registration_challenges'), backend.quote_name('request_date')))
+    transaction.commit_unless_managed()
 
 if __name__ == &quot;__main__&quot;:
     clean_up()</diff>
      <filename>django/bin/daily_cleanup.py</filename>
    </modified>
    <modified>
      <diff>@@ -0,0 +1,73 @@
+&quot;&quot;&quot;
+Settings and configuration for Django.
+
+Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment
+variable, and then from django.conf.global_settings; see the global settings file for
+a list of all possible variables.
+&quot;&quot;&quot;
+
+import os
+import sys
+from django.conf import global_settings
+
+ENVIRONMENT_VARIABLE = &quot;DJANGO_SETTINGS_MODULE&quot;
+
+class Settings:
+
+    def __init__(self, settings_module):
+
+        # update this dict from global settings (but only for ALL_CAPS settings)
+        for setting in dir(global_settings):
+            if setting == setting.upper():
+                setattr(self, setting, getattr(global_settings, setting))
+
+        # store the settings module in case someone later cares
+        self.SETTINGS_MODULE = settings_module
+
+        try:
+            mod = __import__(self.SETTINGS_MODULE, '', '', [''])
+        except ImportError, e:
+            raise EnvironmentError, &quot;Could not import settings '%s' (is it on sys.path?): %s&quot; % (self.SETTINGS_MODULE, e)
+
+        # Settings that should be converted into tuples if they're mistakenly entered
+        # as strings.
+        tuple_settings = (&quot;INSTALLED_APPS&quot;, &quot;TEMPLATE_DIRS&quot;)
+
+        for setting in dir(mod):
+            if setting == setting.upper():
+                setting_value = getattr(mod, setting)
+                if setting in tuple_settings and type(setting_value) == str:
+                    setting_value = (setting_value,) # In case the user forgot the comma.
+                setattr(self, setting, setting_value)
+
+        # Expand entries in INSTALLED_APPS like &quot;django.contrib.*&quot; to a list
+        # of all those apps.
+        new_installed_apps = []
+        for app in self.INSTALLED_APPS:
+            if app.endswith('.*'):
+                appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__)
+                for d in os.listdir(appdir):
+                    if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
+                        new_installed_apps.append('%s.%s' % (app[:-2], d))
+            else:
+                new_installed_apps.append(app)
+        self.INSTALLED_APPS = new_installed_apps
+
+        # move the time zone info into os.environ
+        os.environ['TZ'] = self.TIME_ZONE
+
+# try to load DJANGO_SETTINGS_MODULE
+try:
+    settings_module = os.environ[ENVIRONMENT_VARIABLE]
+    if not settings_module: # If it's set but is an empty string.
+        raise KeyError
+except KeyError:
+    raise EnvironmentError, &quot;Environment variable %s is undefined.&quot; % ENVIRONMENT_VARIABLE
+
+# instantiate the configuration object
+settings = Settings(settings_module)
+
+# install the translation machinery so that it is available
+from django.utils import translation
+translation.install()
+</diff>
      <filename>django/conf/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -79,7 +79,7 @@ SERVER_EMAIL = 'root@localhost'
 SEND_BROKEN_LINK_EMAILS = False
 
 # Database connection info.
-DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
+DATABASE_ENGINE = ''           # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
 DATABASE_NAME = ''             # Or path to database file if using sqlite3.
 DATABASE_USER = ''             # Not used with sqlite3.
 DATABASE_PASSWORD = ''         # Not used with sqlite3.
@@ -102,19 +102,16 @@ INSTALLED_APPS = ()
 # List of locations of the template source files, in search order.
 TEMPLATE_DIRS = ()
 
-# Extension on all templates.
-TEMPLATE_FILE_EXTENSION = '.html'
-
 # List of callables that know how to import templates from various sources.
 # See the comments in django/core/template/loader.py for interface
 # documentation.
 TEMPLATE_LOADERS = (
-    'django.core.template.loaders.filesystem.load_template_source',
-    'django.core.template.loaders.app_directories.load_template_source',
-#     'django.core.template.loaders.eggs.load_template_source',
+    'django.template.loaders.filesystem.load_template_source',
+    'django.template.loaders.app_directories.load_template_source',
+#     'django.template.loaders.eggs.load_template_source',
 )
 
-# List of processors used by DjangoContext to populate the context.
+# List of processors used by RequestContext to populate the context.
 # Each one should be a callable that takes the request object as its
 # only parameter and returns a dictionary to add to the context.
 TEMPLATE_CONTEXT_PROCESSORS = (
@@ -205,6 +202,10 @@ TIME_FORMAT = 'P'
 # http://psyco.sourceforge.net/
 ENABLE_PSYCO = False
 
+# Do you want to manage transactions manually?
+# Hint: you really don't!
+TRANSACTIONS_MANAGED = False
+
 ##############
 # MIDDLEWARE #
 ##############
@@ -213,7 +214,8 @@ ENABLE_PSYCO = False
 # this middleware classes will be applied in the order given, and in the
 # response phase the middleware will be applied in reverse order.
 MIDDLEWARE_CLASSES = (
-    &quot;django.middleware.sessions.SessionMiddleware&quot;,
+    &quot;django.contrib.sessions.middleware.SessionMiddleware&quot;,
+    &quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;,
 #     &quot;django.middleware.http.ConditionalGetMiddleware&quot;,
 #     &quot;django.middleware.gzip.GZipMiddleware&quot;,
     &quot;django.middleware.common.CommonMiddleware&quot;,</diff>
      <filename>django/conf/global_settings.py</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@ ADMINS = (
 
 MANAGERS = ADMINS
 
-DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
+DATABASE_ENGINE = ''           # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
 DATABASE_NAME = ''             # Or path to database file if using sqlite3.
 DATABASE_USER = ''             # Not used with sqlite3.
 DATABASE_PASSWORD = ''         # Not used with sqlite3.
@@ -45,14 +45,15 @@ SECRET_KEY = ''
 
 # List of callables that know how to import templates from various sources.
 TEMPLATE_LOADERS = (
-    'django.core.template.loaders.filesystem.load_template_source',
-    'django.core.template.loaders.app_directories.load_template_source',
-#     'django.core.template.loaders.eggs.load_template_source',
+    'django.template.loaders.filesystem.load_template_source',
+    'django.template.loaders.app_directories.load_template_source',
+#     'django.template.loaders.eggs.load_template_source',
 )
 
 MIDDLEWARE_CLASSES = (
     &quot;django.middleware.common.CommonMiddleware&quot;,
-    &quot;django.middleware.sessions.SessionMiddleware&quot;,
+    &quot;django.contrib.sessions.middleware.SessionMiddleware&quot;,
+    &quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;,
     &quot;django.middleware.doc.XViewMiddleware&quot;,
 )
 
@@ -64,4 +65,8 @@ TEMPLATE_DIRS = (
 )
 
 INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
 )</diff>
      <filename>django/conf/project_template/settings.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,5 +5,5 @@ urlpatterns = patterns('',
     # (r'^{{ project_name }}/', include('{{ project_name }}.apps.foo.urls.foo')),
 
     # Uncomment this for admin:
-#     (r'^admin/', include('django.contrib.admin.urls.admin')),
+#     (r'^admin/', include('django.contrib.admin.urls')),
 )</diff>
      <filename>django/conf/project_template/urls.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,9 @@
 from django.conf.urls.defaults import *
 
 urlpatterns = patterns('',
-    (r'^login/$', 'django.views.auth.login.login'),
-    (r'^logout/$', 'django.views.auth.login.logout'),
-    (r'^login_another/$', 'django.views.auth.login.logout_then_login'),
+    (r'^login/$', 'django.contrib.auth.view.login'),
+    (r'^logout/$', 'django.contrib.auth.views.logout'),
+    (r'^login_another/$', 'django.contrib.auth.views.logout_then_login'),
 
     (r'^register/$', 'ellington.registration.views.registration.signup'),
     (r'^register/(?P&lt;challenge_string&gt;\w{32})/$', 'ellington.registration.views.registration.register_form'),
@@ -12,8 +12,8 @@ urlpatterns = patterns('',
     (r'^profile/welcome/$', 'ellington.registration.views.profile.profile_welcome'),
     (r'^profile/edit/$', 'ellington.registration.views.profile.edit_profile'),
 
-    (r'^password_reset/$', 'django.views.registration.passwords.password_reset'),
-    (r'^password_reset/done/$', 'django.views.registration.passwords.password_reset_done'),
-    (r'^password_change/$', 'django.views.registration.passwords.password_change'),
-    (r'^password_change/done/$', 'django.views.registration.passwords.password_change_done'),
+    (r'^password_reset/$', 'django.contrib.auth.views.password_reset'),
+    (r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done'),
+    (r'^password_change/$', 'django.contrib.auth.views.password_change'),
+    (r'^password_change/done/$', 'django.contrib.auth.views.password_change_done'),
 )</diff>
      <filename>django/conf/urls/registration.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@ Each filter subclass knows how to display a filter for a field that passes a
 certain test -- e.g. being a DateField or ForeignKey.
 &quot;&quot;&quot;
 
-from django.core import meta
+from django.db import models
 import datetime
 
 class FilterSpec(object):
@@ -50,13 +50,13 @@ class FilterSpec(object):
 class RelatedFilterSpec(FilterSpec):
     def __init__(self, f, request, params):
         super(RelatedFilterSpec, self).__init__(f, request, params)
-        if isinstance(f, meta.ManyToManyField):
-            self.lookup_title = f.rel.to.verbose_name
+        if isinstance(f, models.ManyToManyField):
+            self.lookup_title = f.rel.to._meta.verbose_name
         else:
             self.lookup_title = f.verbose_name
-        self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to.pk.name)
+        self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to._meta.pk.name)
         self.lookup_val = request.GET.get(self.lookup_kwarg, None)
-        self.lookup_choices = f.rel.to.get_model_module().get_list()
+        self.lookup_choices = f.rel.to._default_manager.all()
 
     def has_output(self):
         return len(self.lookup_choices) &gt; 1
@@ -69,7 +69,7 @@ class RelatedFilterSpec(FilterSpec):
                'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
                'display': _('All')}
         for val in self.lookup_choices:
-            pk_val = getattr(val, self.field.rel.to.pk.attname)
+            pk_val = getattr(val, self.field.rel.to._meta.pk.attname)
             yield {'selected': self.lookup_val == str(pk_val),
                    'query_string': cl.get_query_string( {self.lookup_kwarg: pk_val}),
                    'display': val}
@@ -103,7 +103,7 @@ class DateFieldFilterSpec(FilterSpec):
 
         today = datetime.date.today()
         one_week_ago = today - datetime.timedelta(days=7)
-        today_str = isinstance(self.field, meta.DateTimeField) and today.strftime('%Y-%m-%d 23:59:59') or today.strftime('%Y-%m-%d')
+        today_str = isinstance(self.field, models.DateTimeField) and today.strftime('%Y-%m-%d 23:59:59') or today.strftime('%Y-%m-%d')
 
         self.links = (
             (_('Any date'), {}),
@@ -126,7 +126,7 @@ class DateFieldFilterSpec(FilterSpec):
                    'query_string': cl.get_query_string( param_dict, self.field_generic),
                    'display': title}
 
-FilterSpec.register(lambda f: isinstance(f, meta.DateField), DateFieldFilterSpec)
+FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
 
 class BooleanFieldFilterSpec(FilterSpec):
     def __init__(self, f, request, params):
@@ -144,9 +144,9 @@ class BooleanFieldFilterSpec(FilterSpec):
             yield {'selected': self.lookup_val == v and not self.lookup_val2,
                    'query_string': cl.get_query_string( {self.lookup_kwarg: v}, [self.lookup_kwarg2]),
                    'display': k}
-        if isinstance(self.field, meta.NullBooleanField):
+        if isinstance(self.field, models.NullBooleanField):
             yield {'selected': self.lookup_val2 == 'True',
                    'query_string': cl.get_query_string( {self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
                    'display': _('Unknown')}
 
-FilterSpec.register(lambda f: isinstance(f, meta.BooleanField) or isinstance(f, meta.NullBooleanField), BooleanFieldFilterSpec)
+FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)</diff>
      <filename>django/contrib/admin/filterspecs.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,14 @@
-@import url(global.css);
-@import url(changelists.css);
+/*
+    DJANGO Admin
+    by Wilson Miner wilson@lawrence.com
+*/
+
+/* Block IE 5 */
+@import &quot;null?\&quot;\{&quot;;
+
+/* Import other styles */
+@import url('global.css');
+@import url('layout.css');
+
+/* Import patch for IE 6 Windows */
 /*\*/ @import &quot;patch-iewin.css&quot;; /**/
\ No newline at end of file</diff>
      <filename>django/contrib/admin/media/css/base.css</filename>
    </modified>
    <modified>
      <diff>@@ -1,16 +1,13 @@
-/*
-    DJANGO Admin Changelist Styles
-    by Wilson Miner wilson@lawrence.com
-    Copyright (c) 2005 Lawrence Journal-World
-*/
+@import url('base.css');
 
+/* CHANGELISTS */
 #changelist { position:relative; width:100%; }
 #changelist table { width:100%; }
 .change-list .filtered table { border-right:1px solid #ddd;  }
 .change-list .filtered { min-height:400px; _height:400px; }
 .change-list .filtered { background:white url(../img/admin/changelist-bg.gif) top right repeat-y !important; }
 .change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:160px !important; width:auto !important; }
-.change-list .filtered table tbody th { padding-right:10px; }
+.change-list .filtered table tbody th { padding-right:1em; }
 #changelist .toplinks { border-bottom:1px solid #ccc !important; }
 #changelist .paginator { color:#666; border-top:1px solid #eee; border-bottom:1px solid #eee; background:white url(../img/admin/nav-bg.gif) 0 180% repeat-x; overflow:hidden; }
 .change-list .filtered .paginator { border-right:1px solid #ddd; }
@@ -42,3 +39,12 @@
 .change-list ul.toplinks li { float: left; width: 9em; padding:3px 6px; font-weight: bold; list-style-type:none; }
 .change-list ul.toplinks .date-back a { color:#999; }
 .change-list ul.toplinks .date-back a:hover { color:#036; }
+
+/* PAGINATOR */
+.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
+.paginator a:link, .paginator a:visited	{ padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a.showall { padding:0 !important; border:none !important; }
+.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
+.paginator .end	{ border-width:2px !important; margin-right:6px; }
+.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
+.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }</diff>
      <filename>django/contrib/admin/media/css/changelists.css</filename>
    </modified>
    <modified>
      <diff>@@ -1,19 +1,14 @@
-/*
-    DJANGO Admin Global Styles
-    by Wilson Miner wilson@lawrence.com
-    Copyright (c) 2005 Lawrence Journal-World
-*/
-
-body { margin:0; padding:0; font-family:&quot;Lucida Grande&quot;,&quot;Bitstream Vera Sans&quot;,Verdana,Arial,sans-serif; color:#333; background:#fff; }
+body { margin:0; padding:0; font-size:12px; font-family:&quot;Lucida Grande&quot;,&quot;Bitstream Vera Sans&quot;,Verdana,Arial,sans-serif; color:#333; background:#fff; }
 
 /* LINKS */
 a:link, a:visited { color: #5b80b2; text-decoration:none; }
 a:hover { color: #036; }
 a img { border:none; }
 
-/*  GLOBAL DEFAULTS */
-p, ol, ul, dl { margin:.2em 0 .8em 0; font-size:12px; }
+/* GLOBAL DEFAULTS */
+p, ol, ul, dl { margin:.2em 0 .8em 0; }
 p { padding:0; line-height:140%; }
+
 h1,h2,h3,h4,h5 { font-weight:bold; }
 h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
 h2 { font-size:16px; margin:1em 0 .5em 0; }
@@ -21,6 +16,7 @@ h2.subhead { font-weight:normal;margin-top:0; }
 h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
 h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
 h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
+
 ul li { list-style-type:square; padding:1px 0; }
 ul.plainlist { margin-left:0 !important; }
 ul.plainlist li { list-style-type:none; }
@@ -28,150 +24,83 @@ li ul { margin-bottom:0; }
 li, dt, dd { font-size:11px; line-height:14px; }
 dt { font-weight:bold; margin-top:4px; }
 dd { margin-left:0; }
+
 form { margin:0; padding:0; }
 fieldset { margin:0; padding:0; }
+
 blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
 code, pre { font-family:&quot;Bitstream Vera Sans Mono&quot;, Monaco, &quot;Courier New&quot;, Courier, monospace; background:inherit; color:#666; font-size:11px; }
 pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
 code strong	{ color:#930; }
 hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
 
-/*  PAGE STRUCTURE  */
-#container { position:relative; width:100%; min-width:760px; }
-#content { margin:10px 15px; }
-#header { width:100%; }
-#content-main { float:left; width:100%; }
-#content-related { float:right; width:220px; position:relative; margin-right:-230px; }
-#footer	{ clear:both; padding:10px; }
-
-/*  COLUMN TYPES  */
-.colMS { margin-right:245px !important; }
-.colSM { margin-left:245px !important; }
-.colSM #content-related { float:left; margin-right:0; margin-left:-230px; } 
-.colSM #content-main { float:right; }
-.popup .colM { width:95%; }
-.subcol { float:left; width:46%; margin-right:15px; }
-.dashboard #content { width:500px; }
-
-/*  HEADER  */
-#header	{ background:#417690; color:#ffc; min-height:2.4em; overflow:hidden; }
-#header a:link, #header a:visited { color:white; }
-#header a:hover { text-decoration:underline; }
-#branding h1 { padding:0.5em 10px 0 10px; font-size:18px; margin:0; font-weight:normal; color:#f4f379; }
-#branding h2 { padding:0 10px 0.8em 10px; font-size:14px; margin:0; font-weight:normal; color:#ffc; }
-#user-tools	{ position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
-
-/*  SIDEBAR  */
-#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
-#content-related h4 { font-size:11px; }
+/* TEXT STYLES &amp; MODIFIERS */
+.small { font-size:11px; }
+.tiny { font-size:10px; }
+p.tiny { margin-top:-2px; }
+.mini { font-size:9px; }
+p.mini { margin-top:-3px; }
+.help, p.help { font-size:10px !important; color:#999; }
+p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
+.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
+.quiet strong { font-weight:bold !important; }
+.float-right { float:right; }
+.float-left { float:left; }
+.clear { clear:both; }
+.align-left { text-align:left; }
+.align-right { text-align:right; }
+.example { margin:10px 0; padding:5px 10px; background:#efefef; }
+.nowrap { white-space:nowrap; }
 
-/*  TABLES  */
+/* TABLES */
 table { border-collapse:collapse; border-color:#ccc; }
 td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:&quot;Lucida Grande&quot;, Verdana, Arial, sans-serif; }
-th { text-align:left; font-size:12px; }
-thead th	{ font-weight:bold; color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
-thead th:first-child { border-left:none !important; }
-.superwide table th, .superwide table td, .superwide table input, .superwide table select { font-size:10px; }
-.module table { border-collapse: collapse; }
+th { text-align:left; font-size:12px; font-weight:bold; }
+thead th, 
+tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
+tfoot td { border-bottom:none; border-top:1px solid #ddd; }
+thead th:first-child, 
+tfoot td:first-child { border-left:none !important; }
 thead th.optional { font-weight:normal !important; }
-#home-page table.module tr:hover { background:#EDF3FE; }
 fieldset table { border-right:1px solid #eee; }
 tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
 tr.alt { background:#f6f6f6; }
 .row1 { background:#EDF3FE; }
 .row2 { background:white; }
-table#change-history { width:100%; }
-table#change-history tbody th { width:16em; }
 
-/*  TABLE SORTING  */
+/* SORTABLE TABLES */
 thead th a:link, thead th a:visited { color:#666; display:block; }
 table thead th.sorted { background-position:bottom left !important; }
 table thead th.sorted a { padding-right:13px; }
 table thead th.ascending a { background:url(../img/admin/arrow-down.gif) right .4em no-repeat; }
 table thead th.descending a { background:url(../img/admin/arrow-up.gif) right .4em no-repeat; }
 
-/*  MODULES  */
-.module	{ border:1px solid #ccc; margin-bottom:5px; background:white; }
-.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
-.module blockquote { margin-left:12px; }
-.module ul, .module ol { margin-left:1.5em; }
-.module h2,  .module caption { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; background:#7CA0C7 url(../img/admin/default-bg.gif) left top repeat-x; color:white; font-weight:bold; }
-.module caption	{ border:1px solid #ccc; border-bottom:none; }
-.module h3 { margin-top:.6em; }
-#content-related .module h2	{ background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
-#content-main .verbose .actionlist { float:right; font-size:10px; width:17em; position:relative; top:-1.6em; margin:0 8px; }
-
-/* DASHBOARD */
-.dashboard .module table th { width:100%; }
-.dashboard .module table td { white-space:nowrap; }
-.dashboard .module table td a { display:block; padding-right:.6em; }
+/* ORDERABLE TABLES */
+table.orderable tbody tr td:hover { cursor:move; }
+table.orderable tbody tr td:first-child { padding-left:14px; background-image:url(../img/admin/nav-bg-grabber.gif); background-repeat:repeat-y; }
+table.orderable-initalized .order-cell, body&gt;tr&gt;td.order-cell { display:none; }
 
-/*  RECENT ACTIONS MODULE  */
-.module ul.actionlist { margin-left:0; }
-ul.actionlist li { list-style-type:none; }
-
-/*  FORM DEFAULTS  */
-input, textarea, select	{ margin:2px 0; padding:2px 3px; vertical-align:middle; border:1px solid #ccc; font-family:&quot;Lucida Grande&quot;, Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+/* FORM DEFAULTS */
+input, textarea, select	{ margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:&quot;Lucida Grande&quot;, Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
 textarea { vertical-align:top !important; }
-input[type=checkbox], input[type=radio] { border:none; }
+input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
 
 /*  FORM BUTTONS  */
 input[type=submit], input[type=button], .submit-row input { background:white url(../img/admin/nav-bg.gif) bottom repeat-x; padding:3px; color:black; }
 input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
 input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
 input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
-.submit-row { padding:5px 7px; text-align:right; background:#ffc; border:1px solid #ccc; margin:5px 0; }
-.submit-row input { margin:0 0 0 5px; }
-.submit-row .float-left { padding-top:.1em; }
-
-/*  FORM ROWS  */
-.form-row { clear:both; padding:8px 12px; font-size:11px; }
-html&gt;body .form-row { border-bottom:1px solid #eee; }
-.form-row:after { content: &quot;.&quot;; display: block; height: 0; clear: both; visibility: hidden; }
-.form-row img, .form-row input { vertical-align:middle; }
-form .form-row p { padding-left:0; font-size:11px; }
-
-/*  FORM LABELS  */
-form h4	{ margin:0 !important; padding:0 !important; border:none !important; }
-label { font-weight:normal !important; color:#666; font-size:12px; }
-label.inline { margin-left:20px; }
-.required label, label.required	{ font-weight:bold !important; color:#333 !important; }
-
-/*  RADIO BUTTONS */
-form ul.radiolist li { list-style-type:none; }
-form ul.radiolist label { float:none; display:inline; }
-form ul.inline { margin-left:0; padding:0; }
-form ul.inline li { float:left; padding-right:7px; }
-
-/*  ALIGNED FIELDSETS  */
-.aligned label { display:block; padding:0 1em 3px 0; float:left; text-align:left; width:8em; }
-.aligned label.inline { display:inline; float:none; }
-.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { width:350px; }
-form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
-form .aligned table p { margin-left:0; padding-left:0; }
-form .aligned p.help { padding-left:38px; }
-.aligned .vCheckboxLabel { float:none !important; display:inline; }
-.colM .aligned .vLargeTextField, colM .aligned .vXMLLargeTextField { width:610px; }
-.checkbox-row p.help { margin-left:0; padding-left:0 !important; }
-
-/*  WIDE FIELDSETS  */
-.wide label { width:15em !important; }
-form .wide p { margin-left:15em; }
-form .wide p.help { padding-left:38px; }
-.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { width:450px; }
 
-/*  COLLAPSED FIELDSETS  */
-fieldset.collapsed * { display:none; }
-fieldset.collapsed h2, fieldset.collapsed { display:block !important; }
-fieldset.collapsed .collapse-toggle { display: inline !important; }
-fieldset.collapse h2 a.collapse-toggle { color:#ffc; }
-fieldset.collapse h2 a.collapse-toggle:hover { text-decoration:underline; }
-.hidden { display:none; }
-
-/* MONOSPACE TEXTAREAS */
-fieldset.monospace textarea { font-family:&quot;Bitstream Vera Sans Mono&quot;,Monaco,&quot;Courier New&quot;,Courier,monospace; }
+/* MODULES */
+.module	{ border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
+.module blockquote { margin-left:12px; }
+.module ul, .module ol { margin-left:1.5em; }
+.module h3 { margin-top:.6em; }
+.module h2, .module caption { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/admin/default-bg.gif) top left repeat-x; color:white; }
+.module table { border-collapse: collapse; }
 
-/* MESSAGES &amp; ERRORS  */
+/* MESSAGES &amp; ERRORS */
 ul.messagelist { padding:0 0 5px 0; margin:0; }
 ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/admin/icon_success.gif) 5px .3em no-repeat; }
 .errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; }
@@ -183,17 +112,21 @@ td ul.errorlist li { margin:0 !important; }
 .error input, .error select { border:1px solid red; }
 div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
 div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; }
+.description { font-size:12px; padding:5px 0 0 12px; }
 
-/*  ACTION ICONS  */
+/* BREADCRUMBS */
+div.breadcrumbs { background:white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px;  color:#999;  border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
+
+/* ACTION ICONS */
 .addlink { padding-left:12px; background:url(../img/admin/icon_addlink.gif) 0 .2em no-repeat; }
 .changelink { padding-left:12px; background:url(../img/admin/icon_changelink.gif) 0 .2em no-repeat; }
-.deletelink { padding-left:12px; background:url(../img/admin/icon_deletelink.gif) 0 .2em no-repeat; }
+.deletelink { padding-left:12px; background:url(../img/admin/icon_deletelink.gif) 0 .25em no-repeat; }
 a.deletelink:link, a.deletelink:visited { color:#CC3434; }
 a.deletelink:hover { color:#993333; }
 
-/*  OBJECT TOOLS  */
-.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; margin-bottom:5px; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
-.form-row .object-tools { margin-top:0; margin-bottom:0; }
+/* OBJECT TOOLS */
+.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
+.form-row .object-tools { margin-top:5px; margin-bottom:5px; float:none; height:2em; padding-left:3.5em; }
 .object-tools li { display:block; float:left; background:url(../img/admin/tool-left.gif) 0 0 no-repeat; padding:0 0 0 8px; margin-left:2px; height:16px; }
 .object-tools li:hover { background:url(../img/admin/tool-left_over.gif) 0 0 no-repeat; }
 .object-tools a:link, .object-tools a:visited { display:block; float:left; color:white; padding:.1em 14px .1em 8px; height:14px; background:#999 url(../img/admin/tool-right.gif) 100% 0 no-repeat; }
@@ -203,123 +136,6 @@ a.deletelink:hover { color:#993333; }
 .object-tools a.addlink { background:#999 url(../img/admin/tooltag-add.gif) top right no-repeat; padding-right:28px; }
 .object-tools a.addlink:hover { background:#5b80b2 url(../img/admin/tooltag-add_over.gif) top right no-repeat; }
 
-/*  INLINE CONTROLS  */
-#inline-controls { font-weight:bold; font-size:12px; }
-#inline-specific-controls { margin-left:6px; padding:0 8px; border-left:6px solid #ccc;  }
-
-/*  BREADCRUMBS  */
-p.breadcrumbs { font-size:11px; color:#ccc;text-align:left; } /* old breadcrumbs style */
-div.breadcrumbs { background:white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px;  color:#999;  border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
-
-/*  SELECTOR (FILTER INTERFACE)  */
-.selector { width:580px; float:left; }
-.selector select { width:270px; height:170px; }
-.selector-available, .selector-chosen { float:left; width:270px; text-align:center; margin-bottom:5px; }
-.selector-available h2, .selector-chosen h2 { border:1px solid #ccc; }
-.selector .selector-available h2 { background:white url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
-.selector .selector-filter { background:white; border:1px solid #ccc; border-width:0 1px; padding:3px; color:#999; font-size:10px; margin:0; text-align:left; }
-.selector .selector-chosen .selector-filter { padding:4px 5px; }
-.selector .selector-available input { width:230px; }
-.selector ul.selector-chooser { float:left; width:22px; height:50px; background:url(../img/admin/chooser-bg.gif) top center no-repeat; margin:13% 3px 0 3px; padding:0; }
-.selector-chooser li { margin:0; padding:3px; list-style-type:none; }
-.selector select { margin-bottom:5px; margin-top:0; }
-.selector-add, .selector-remove { width:16px; height:16px; display:block; text-indent:-3000px; }
-.selector-add { background:url(../img/admin/selector-add.gif) top center no-repeat; margin-bottom:2px; }
-.selector-remove { background:url(../img/admin/selector-remove.gif) top center no-repeat; }
-a.selector-chooseall, a.selector-clearall { display:block; width:6em; text-align:left; margin-left:auto; margin-right:auto; font-weight:bold; color:#666;  padding:3px 0 3px 18px; }
-a.selector-chooseall:hover, a.selector-clearall:hover { color:#036; }
-a.selector-chooseall { width:7em; background:url(../img/admin/selector-addall.gif) left center no-repeat; }
-a.selector-clearall { background:url(../img/admin/selector-removeall.gif) left center no-repeat; }
-
-/*  Stacked selectors for long items  */
-.stacked { float:left; width:500px; }
-.stacked select { width:480px; height:100px; }
-.stacked .selector-available, .stacked .selector-chosen { width:480px; }
-.stacked .selector-available { margin-bottom:0; }
-.stacked .selector-available input { width:442px; }
-.stacked ul.selector-chooser { height:22px; width:50px; margin:0 0 3px 40%; background:url(../img/admin/chooser_stacked-bg.gif) top center no-repeat; }
-.stacked .selector-chooser li { float:left; padding:3px 3px 3px 5px; }
-.stacked .selector-chooseall, .stacked .selector-clearall { display:none; }
-.stacked .selector-add { background-image:url(../img/admin/selector_stacked-add.gif); }
-.stacked .selector-remove { background-image:url(../img/admin/selector_stacked-remove.gif); }
-
-/*  DATE AND TIME  */
-p.datetime { line-height:20px; margin:0; padding:0; color:#666; font-size:11px; font-weight:bold; }
-.datetime span { font-size:11px; font-weight:normal; color:#ccc; white-space:nowrap; }
-.vDateField { margin-left:4px; }
-table p.datetime { font-size:10px; margin-left:0; padding-left:0; }
-
-/*  FILE UPLOADS  */
-p.file-upload { line-height:20px; margin:0; padding:0; color:#666; font-size:11px; font-weight:bold; }
-.file-upload a { font-weight:normal; }
-.file-upload .deletelink { margin-left:5px; }
-
-/*  CALENDARS &amp; CLOCKS  */
-.calendarbox, .clockbox { margin:5px auto; font-size:11px; width: 16em; text-align: center; background:white; position:relative; }
-.clockbox { width:9em; }
-.calendar { margin:0; padding: 0; }
-.calendar table { margin: 0; padding: 0; border-collapse:collapse; background:white; width:99%; }
-.calendar caption, .calendarbox h2 { margin: 0; font-size:11px; text-align:center; border-top:none; }
-.calendar th { font-size:10px; color:#666; padding:2px 3px; text-align:center; background:#e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x; border-bottom:1px solid #ddd; }
-.calendar td { font-size:11px; text-align: center; padding: 0; border-top:1px solid #eee; border-bottom:none; }
-.calendar td.selected a { background: #C9DBED; }
-.calendar td.nonday { background:#efefef; }
-.calendar td.today a { background:#ffc; }
-.calendar td a, .timelist a { display: block; font-weight:bold; padding:4px; text-decoration: none; color:#444; }
-.calendar td a:hover, .timelist a:hover { background: #5b80b2; color:white; }
-.calendar td a:active, .timelist a:active { background: #036; color:white; }
-.calendarnav { font-size:10px; text-align: center; color:#ccc; margin:0; padding:1px 3px; }
-.calendarnav a:link, #calendarnav a:visited, #calendarnav a:hover { color: #999; }
-.calendar-shortcuts { background:white; font-size:10px; line-height:11px; border-top:1px solid #eee; padding:3px 0 4px; color:#ccc; }
-.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { display:block; position:absolute; font-weight:bold; font-size:12px; background:#C9DBED url(../img/admin/default-bg.gif) bottom left repeat-x; padding:1px 4px 2px 4px; color:white; }
-.calendarnav-previous:hover, .calendarnav-next:hover { background:#036; }
-.calendarnav-previous { top:0; left:0; }
-.calendarnav-next { top:0; right:0; }
-.calendar-cancel { margin:0 !important; padding:0; font-size:10px; background:#e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x;  border-top:1px solid #ddd; }
-.calendar-cancel a { padding:2px; color:#999; }
-ul.timelist, .timelist li { list-style-type:none; margin:0; padding:0; }
-.timelist a { padding:2px; }
-
-/*  ORDERING WIDGET  */
-ul#orderthese { position:absolute; top:8em; right:0; width:240px; padding:0; margin:0; list-style-type:none; }
-ul#orderthese li { list-style-type:none; display:block; padding:0; margin:6px 0; width:214px; background:#f6f6f6; white-space:nowrap; overflow:hidden; }
-ul#orderthese li span { display:block; border:1px solid #e7e7e7; background:transparent url(../img/admin/nav-bg-grabber.gif) top left repeat-y; font-size:10px !important; padding:4px 6px 4px 12px; }
-ul#orderthese span:hover { background-color:#efefef; }
-
-/*  PAGINATOR  */
-.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
-.paginator a:link, .paginator a:visited	{ padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
-.paginator a.showall { padding:0 !important; border:none !important; }
-.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
-.paginator .end	{ border-width:2px !important; margin-right:6px; }
-.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
-.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
-
-/*  TEXT STYLES &amp; MODIFIERS  */
-.small { font-size:11px; }
-.tiny { font-size:10px; }
-p.tiny { margin-top:-2px; }
-.mini { font-size:9px; }
-p.mini { margin-top:-3px; }
-.help, p.help { font-size:10px !important; color:#999; }
-p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
-.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
-.quiet strong { font-weight:bold !important; }
-.float-right { float:right; }
-.float-left { float:left; }
-.clear { clear:both; }
-.align-left { text-align:left; }
-.align-right { text-align:right; }
-.example { margin:10px 0; padding:5px 10px; background:#efefef; }
-.nowrap { white-space:nowrap; }
-
-/*  CUSTOM FORM FIELDS  */
-.vSelectMultipleField { vertical-align:top !important; }
-.vCheckboxField { border:none; }
-.vDateField, .vTimeField { margin-right:2px; }
-.vFileUploadField { border:none; }
-.vURLField { width:380px; }
-.vLargeTextField, .vXMLLargeTextField { width:480px; }
-.colM .vLargeTextField, .colM .vXMLLargeTextField { width:720px; }
-body.core-flatfile #id_content { height: 400px; }
-.module table .vPositiveSmallIntegerField { width: 22px; }
\ No newline at end of file
+/* OBJECT HISTORY */
+table#change-history { width:100%; }
+table#change-history tbody th { width:16em; }</diff>
      <filename>django/contrib/admin/media/css/global.css</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,6 @@
 * html #container { position:static; } /* keep header from flowing off the page */
 * html .colMS #content-related { margin-right:0; margin-left:10px; position:static; } /* put the right sidebars back on the page */
 * html .colSM #content-related { margin-right:10px; margin-left:-115px; position:static; } /* put the left sidebars back on the page */
+* html .form-row { height:1%; }
 * html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
-* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
-* html #content { width /**/: 768px; } /* fixed width for IE5 */
-* html #content-main { width /**/: 535px; } /* fixed width for IE5 */
\ No newline at end of file
+* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
\ No newline at end of file</diff>
      <filename>django/contrib/admin/media/css/patch-iewin.css</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,7 @@ function dismissAddAnotherPopup(win, newId, newRepr) {
         if (elem.nodeName == 'SELECT') {
             var o = new Option(newRepr, newId);
             elem.options[elem.options.length] = o;
-            elem.selectedIndex = elem.length - 1;
+            o.selected = true;
         } else if (elem.nodeName == 'INPUT') {
             elem.value = newId;
         }</diff>
      <filename>django/contrib/admin/media/js/admin/RelatedObjectLookups.js</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block title %}{% trans 'Page not found' %}{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin/404.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;/&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo; {% trans &quot;Server error&quot; %}&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin/500.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base&quot; %}
+{% extends &quot;admin/base.html&quot; %}
 {% load i18n %}
 
 {% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin/base_site.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,36 +1,39 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n admin_modify adminmedia %}
 {% block extrahead %}{{ block.super }}
 &lt;script type=&quot;text/javascript&quot; src=&quot;../../../jsi18n/&quot;&gt;&lt;/script&gt;
-{% for js in bound_manipulator.javascript_imports %}{% include_admin_script js %}{% endfor %}
+{% for js in javascript_imports %}{% include_admin_script js %}{% endfor %}
 {% endblock %}
-{% block coltype %}{{ bound_manipulator.coltype }}{% endblock %}
-{% block bodyclass %}{{ app_label }}-{{ bound_manipulator.object_name.lower }} change-form{% endblock %}
+{% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %}
+{% block coltype %}{% if ordered_objects %}colMS{% else %}colM{% endif %}{% endblock %}
+{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../../../doc/&quot;&gt;{% trans 'Documentation' %}&lt;/a&gt; / &lt;a href=&quot;../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
 {% block breadcrumbs %}{% if not is_popup %}
 &lt;div class=&quot;breadcrumbs&quot;&gt;
      &lt;a href=&quot;../../../&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo;
-     &lt;a href=&quot;../&quot;&gt;{{ bound_manipulator.verbose_name_plural|capfirst }}&lt;/a&gt; &amp;rsaquo;
-     {% if add %}{% trans &quot;Add&quot; %} {{ bound_manipulator.verbose_name }}{% else %}{{ bound_manipulator.original|striptags|truncatewords:&quot;18&quot; }}{% endif %}
+     &lt;a href=&quot;../&quot;&gt;{{ opts.verbose_name_plural|capfirst }}&lt;/a&gt; &amp;rsaquo;
+     {% if add %}{% trans &quot;Add&quot; %} {{ opts.verbose_name }}{% else %}{{ original|striptags|truncatewords:&quot;18&quot; }}{% endif %}
 &lt;/div&gt;
 {% endif %}{% endblock %}
 {% block content %}&lt;div id=&quot;content-main&quot;&gt;
 {% if change %}{% if not is_popup %}
   &lt;ul class=&quot;object-tools&quot;&gt;&lt;li&gt;&lt;a href=&quot;history/&quot; class=&quot;historylink&quot;&gt;{% trans &quot;History&quot; %}&lt;/a&gt;&lt;/li&gt;
-  {% if bound_manipulator.has_absolute_url %}&lt;li&gt;&lt;a href=&quot;/r/{{ bound_manipulator.content_type_id }}/{{ object_id }}/&quot; class=&quot;viewsitelink&quot;&gt;{% trans &quot;View on site&quot; %}&lt;/a&gt;&lt;/li&gt;{% endif%}
+  {% if has_absolute_url %}&lt;li&gt;&lt;a href=&quot;../../../r/{{ content_type_id }}/{{ object_id }}/&quot; class=&quot;viewsitelink&quot;&gt;{% trans &quot;View on site&quot; %}&lt;/a&gt;&lt;/li&gt;{% endif%}
   &lt;/ul&gt;
 {% endif %}{% endif %}
-&lt;form {{ bound_manipulator.form_enc_attrib }} action=&quot;{{ form_url }}&quot; method=&quot;post&quot;&gt;{% block form_top %}{% endblock %}
+&lt;form {% if has_file_field %}enctype=&quot;multipart/form-data&quot; {% endif %}action=&quot;{{ form_url }}&quot; method=&quot;post&quot;&gt;{% block form_top %}{% endblock %}
+&lt;div&gt;
 {% if is_popup %}&lt;input type=&quot;hidden&quot; name=&quot;_popup&quot; value=&quot;1&quot; /&gt;{% endif %}
-{% if bound_manipulator.save_on_top %}{% submit_row bound_manipulator %}{% endif %}
+{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
 {% if form.error_dict %}
     &lt;p class=&quot;errornote&quot;&gt;
     {% blocktrans count form.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
     &lt;/p&gt;
 {% endif %}
-{% for bound_field_set in bound_manipulator.bound_field_sets %}
+{% for bound_field_set in bound_field_sets %}
    &lt;fieldset class=&quot;module aligned {{ bound_field_set.classes }}&quot;&gt;
     {% if bound_field_set.name %}&lt;h2&gt;{{ bound_field_set.name }}&lt;/h2&gt;{% endif %}
+    {% if bound_field_set.description %}&lt;div class=&quot;description&quot;&gt;{{ bound_field_set.description }}&lt;/div&gt;{% endif %}
     {% for bound_field_line in bound_field_set %}
         {% admin_field_line bound_field_line %}
         {% for bound_field in bound_field_line %}
@@ -41,7 +44,7 @@
 {% endfor %}
 {% block after_field_sets %}{% endblock %}
 {% if change %}
-   {% if bound_manipulator.ordered_objects %}
+   {% if ordered_objects %}
    &lt;fieldset class=&quot;module&quot;&gt;&lt;h2&gt;{% trans &quot;Ordering&quot; %}&lt;/h2&gt;
    &lt;div class=&quot;form-row{% if form.order_.errors %} error{% endif %} &quot;&gt;
    {% if form.order_.errors %}{{ form.order_.html_error_list }}{% endif %}
@@ -49,27 +52,17 @@
    &lt;/div&gt;&lt;/fieldset&gt;
    {% endif %}
 {% endif %}
-{% for related_object in bound_manipulator.inline_related_objects %}{% edit_inline related_object %}{% endfor %}
+{% for related_object in inline_related_objects %}{% edit_inline related_object %}{% endfor %}
 {% block after_related_objects %}{% endblock %}
-{% submit_row bound_manipulator %}
+{% submit_row %}
 {% if add %}
-   &lt;script type=&quot;text/javascript&quot;&gt;document.getElementById(&quot;{{ bound_manipulator.first_form_field_id }}&quot;).focus();&lt;/script&gt;
+   &lt;script type=&quot;text/javascript&quot;&gt;document.getElementById(&quot;{{ first_form_field_id }}&quot;).focus();&lt;/script&gt;
 {% endif %}
-{% if bound_manipulator.auto_populated_fields %}
+{% if auto_populated_fields %}
    &lt;script type=&quot;text/javascript&quot;&gt;
-   {% auto_populated_field_script bound_manipulator.auto_populated_fields change %}
+   {% auto_populated_field_script auto_populated_fields change %}
    &lt;/script&gt;
 {% endif %}
-{% if change %}
-   {% if bound_manipulator.ordered_objects %}
-      {% if form.order_objects %}&lt;ul id=&quot;orderthese&quot;&gt;
-          {% for object in form.order_objects %}
-             &lt;li id=&quot;p{% object_pk bound_manipulator object %}&quot;&gt;
-             &lt;span id=&quot;handlep{% object_pk bound_manipulator object %}&quot;&gt;{{ object|truncatewords:&quot;5&quot; }}&lt;/span&gt;
-             &lt;/li&gt;
-             {% endfor %}
-      &lt;/ul&gt;{% endif %}
-   {% endif %}
-{% endif %}
+&lt;/div&gt;
 &lt;/form&gt;&lt;/div&gt;
 {% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin/change_form.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,9 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load adminmedia admin_list i18n %}
+{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
 {% block bodyclass %}change-list{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../../doc/&quot;&gt;{% trans 'Documentation' %}&lt;/a&gt; / &lt;a href=&quot;../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
-{% if not is_popup %}{% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo; {{ cl.opts.verbose_name_plural|capfirst }} &lt;/div&gt;{% endblock %}{% endif %}
+{% if not is_popup %}{% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}&lt;/div&gt;{% endblock %}{% endif %}
 {% block coltype %}flex{% endblock %}
 {% block content %}
 &lt;div id=&quot;content-main&quot;&gt;</diff>
      <filename>django/contrib/admin/templates/admin/change_list.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,14 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block userlinks %}&lt;a href=&quot;../../../../doc/&quot;&gt;{% trans 'Documentation' %}&lt;/a&gt; / &lt;a href=&quot;../../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
+{% block breadcrumbs %}
+&lt;div class=&quot;breadcrumbs&quot;&gt;
+     &lt;a href=&quot;../../../../&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo;
+     &lt;a href=&quot;../../&quot;&gt;{{ opts.verbose_name_plural|capfirst }}&lt;/a&gt; &amp;rsaquo;
+     &lt;a href=&quot;../&quot;&gt;{{ object|striptags|truncatewords:&quot;18&quot; }}&lt;/a&gt; &amp;rsaquo;
+     {% trans 'Delete' %}
+&lt;/div&gt;
+{% endblock %}
 {% block content %}
 {% if perms_lacking %}
     &lt;p&gt;{% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}&lt;/p&gt;
@@ -13,8 +21,10 @@
     &lt;p&gt;{% blocktrans %}Are you sure you want to delete the {{ object_name }} &quot;{{ object }}&quot;? All of the following related items will be deleted:{% endblocktrans %}&lt;/p&gt;
     &lt;ul&gt;{{ deleted_objects|unordered_list }}&lt;/ul&gt;
     &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
+    &lt;div&gt;
     &lt;input type=&quot;hidden&quot; name=&quot;post&quot; value=&quot;yes&quot; /&gt;
     &lt;input type=&quot;submit&quot; value=&quot;{% trans &quot;Yes, I'm sure&quot; %}&quot; /&gt;
+    &lt;/div&gt;
     &lt;/form&gt;
 {% endif %}
 {% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin/delete_confirmation.html</filename>
    </modified>
    <modified>
      <diff>@@ -13,4 +13,4 @@
          {% endif %}
       {% endfor %}
     {% endfor %}
-&lt;/fieldset&gt;
\ No newline at end of file
+&lt;/fieldset&gt;</diff>
      <filename>django/contrib/admin/templates/admin/edit_inline_stacked.html</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,6 @@
   {% if not bound_field.has_label_first %}
     {% field_label bound_field %}
   {% endif %}
-  {% if change %}
-    {% if bound_field.field.primary_key %}
-      {{ bound_field.original_value }}
-    {% endif %}
-    {% if bound_field.raw_id_admin %}
-      {% if bound_field.existing_display %}&amp;nbsp;&lt;strong&gt;{{ bound_field.existing_display|truncatewords:&quot;14&quot; }}&lt;/strong&gt;{% endif %}
-    {% endif %}
-  {% endif %}
   {% if bound_field.field.help_text %}&lt;p class=&quot;help&quot;&gt;{{ bound_field.field.help_text }}&lt;/p&gt;{% endif %}
 {% endfor %}
 &lt;/div&gt;</diff>
      <filename>django/contrib/admin/templates/admin/field_line.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
+{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/dashboard.css{% endblock %}
 {% block coltype %}colMS{% endblock %}
 {% block bodyclass %}dashboard{% endblock %}
 {% block breadcrumbs %}{% endblock %}
@@ -13,14 +14,14 @@
 {% if app_list %}
     {% for app in app_list %}
         &lt;div class=&quot;module&quot;&gt;
-        &lt;h2&gt;{{ app.name }}&lt;/h2&gt;
-        &lt;table&gt;
+        &lt;table summary=&quot;{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}&quot;&gt;
+        &lt;caption&gt;{{ app.name }}&lt;/caption&gt;
         {% for model in app.models %}
             &lt;tr&gt;
             {% if model.perms.change %}
-                &lt;th&gt;&lt;a href=&quot;{{ model.admin_url }}&quot;&gt;{{ model.name }}&lt;/a&gt;&lt;/th&gt;
+                &lt;th scope=&quot;row&quot;&gt;&lt;a href=&quot;{{ model.admin_url }}&quot;&gt;{{ model.name }}&lt;/a&gt;&lt;/th&gt;
             {% else %}
-                &lt;th&gt;{{ model.name }}&lt;/th&gt;
+                &lt;th scope=&quot;row&quot;&gt;{{ model.name }}&lt;/th&gt;
             {% endif %}
 
             {% if model.perms.add %}
@@ -57,7 +58,7 @@
             {% else %}
             &lt;ul class=&quot;actionlist&quot;&gt;
             {% for entry in admin_log %}
-                &lt;li class=&quot;{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}&quot;&gt;{% if not entry.is_deletion %}&lt;a href=&quot;{{ entry.get_admin_url }}&quot;&gt;{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}&lt;/a&gt;{% endif %}&lt;br /&gt;&lt;span class=&quot;mini quiet&quot;&gt;{{ entry.get_content_type.name|capfirst }}&lt;/span&gt;&lt;/li&gt;
+                &lt;li class=&quot;{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}&quot;&gt;{% if not entry.is_deletion %}&lt;a href=&quot;{{ entry.get_admin_url }}&quot;&gt;{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}&lt;/a&gt;{% endif %}&lt;br /&gt;&lt;span class=&quot;mini quiet&quot;&gt;{{ entry.content_type.name|capfirst }}&lt;/span&gt;&lt;/li&gt;
             {% endfor %}
             &lt;/ul&gt;
             {% endif %}</diff>
      <filename>django/contrib/admin/templates/admin/index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,9 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
+{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/login.css{% endblock %}
+{% block bodyclass %}login{% endblock %}
+{% block content_title %}{% endblock %}
 {% block breadcrumbs %}{% endblock %}
 
 {% block content %}
@@ -9,20 +12,18 @@
 &lt;p class=&quot;errornote&quot;&gt;{{ error_message }}&lt;/p&gt;
 {% endif %}
 &lt;div id=&quot;content-main&quot;&gt;
-&lt;form action=&quot;{{ app_path }}&quot; method=&quot;post&quot;&gt;
-
-&lt;p class=&quot;aligned&quot;&gt;
-&lt;label for=&quot;id_username&quot;&gt;{% trans 'Username:' %}&lt;/label&gt; &lt;input type=&quot;text&quot; name=&quot;username&quot; id=&quot;id_username&quot; /&gt;
-&lt;/p&gt;
-&lt;p class=&quot;aligned&quot;&gt;
-&lt;label for=&quot;id_password&quot;&gt;{% trans 'Password:' %}&lt;/label&gt; &lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;id_password&quot; /&gt;
-&lt;input type=&quot;hidden&quot; name=&quot;this_is_the_login_form&quot; value=&quot;1&quot; /&gt;
-&lt;input type=&quot;hidden&quot; name=&quot;post_data&quot; value=&quot;{{ post_data }}&quot; /&gt;{% comment %} &lt;span class=&quot;help&quot;&gt;{% trans 'Have you &lt;a href=&quot;/password_reset/&quot;&gt;forgotten your password&lt;/a&gt;?' %}&lt;/span&gt;{% endcomment %}
-&lt;/p&gt;
-
-&lt;div class=&quot;aligned &quot;&gt;
-&lt;label&gt;&amp;nbsp;&lt;/label&gt;&lt;input type=&quot;submit&quot; value=&quot;{% trans 'Log in' %}&quot; /&gt;
-&lt;/div&gt;
+&lt;form action=&quot;{{ app_path }}&quot; method=&quot;post&quot; id=&quot;login-form&quot;&gt;
+	&lt;div class=&quot;form-row&quot;&gt;
+		&lt;label for=&quot;id_username&quot;&gt;{% trans 'Username:' %}&lt;/label&gt; &lt;input type=&quot;text&quot; name=&quot;username&quot; id=&quot;id_username&quot; /&gt;
+	&lt;/div&gt;
+	&lt;div class=&quot;form-row&quot;&gt;
+		&lt;label for=&quot;id_password&quot;&gt;{% trans 'Password:' %}&lt;/label&gt; &lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;id_password&quot; /&gt;
+		&lt;input type=&quot;hidden&quot; name=&quot;this_is_the_login_form&quot; value=&quot;1&quot; /&gt;
+		&lt;input type=&quot;hidden&quot; name=&quot;post_data&quot; value=&quot;{{ post_data }}&quot; /&gt; {% comment %}&lt;span class=&quot;help&quot;&gt;{% trans 'Have you &lt;a href=&quot;/password_reset/&quot;&gt;forgotten your password&lt;/a&gt;?' %}&lt;/span&gt;{% endcomment %}
+	&lt;/div&gt;
+	&lt;div class=&quot;submit-row&quot;&gt;
+		&lt;label&gt;&amp;nbsp;&lt;/label&gt;&lt;input type=&quot;submit&quot; value=&quot;{% trans 'Log in' %}&quot; /&gt;
+	&lt;/div&gt;
 &lt;/form&gt;
 
 &lt;script type=&quot;text/javascript&quot;&gt;</diff>
      <filename>django/contrib/admin/templates/admin/login.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block userlinks %}&lt;a href=&quot;../../../../doc/&quot;&gt;{% trans 'Documentation' %}&lt;/a&gt; / &lt;a href=&quot;../../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
 {% block breadcrumbs %}
@@ -15,16 +15,16 @@
     &lt;table id=&quot;change-history&quot;&gt;
         &lt;thead&gt;
         &lt;tr&gt;
-            &lt;th&gt;{% trans 'Date/time' %}&lt;/th&gt;
-            &lt;th&gt;{% trans 'User' %}&lt;/th&gt;
-            &lt;th&gt;{% trans 'Action' %}&lt;/th&gt;
+            &lt;th scope=&quot;col&quot;&gt;{% trans 'Date/time' %}&lt;/th&gt;
+            &lt;th scope=&quot;col&quot;&gt;{% trans 'User' %}&lt;/th&gt;
+            &lt;th scope=&quot;col&quot;&gt;{% trans 'Action' %}&lt;/th&gt;
         &lt;/tr&gt;
         &lt;/thead&gt;
         &lt;tbody&gt;
         {% for action in action_list %}
         &lt;tr&gt;
-            &lt;th&gt;{{ action.action_time|date:_(&quot;DATE_WITH_TIME_FULL&quot;) }}&lt;/th&gt;
-            &lt;td&gt;{{ action.get_user.username }}{% if action.get_user.first_name %} ({{ action.get_user.first_name }} {{ action.get_user.last_name }}){% endif %}&lt;/td&gt;
+            &lt;th scope=&quot;row&quot;&gt;{{ action.action_time|date:_(&quot;DATE_WITH_TIME_FULL&quot;) }}&lt;/th&gt;
+            &lt;td&gt;{{ action.user.username }}{% if action.user.first_name %} ({{ action.user.first_name }} {{ action.user.last_name }}){% endif %}&lt;/td&gt;
             &lt;td&gt;{{ action.change_message}}&lt;/td&gt;
         &lt;/tr&gt;
         {% endfor %}</diff>
      <filename>django/contrib/admin/templates/admin/object_history.html</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 {% if cl.lookup_opts.admin.search_fields %}
 &lt;div id=&quot;toolbar&quot;&gt;&lt;form id=&quot;changelist-search&quot; action=&quot;&quot; method=&quot;get&quot;&gt;
 &lt;div&gt;&lt;!-- DIV needed for valid HTML --&gt;
-&lt;label&gt;&lt;img src=&quot;{% admin_media_prefix %}img/admin/icon_searchbox.png&quot; alt=&quot;Search&quot; /&gt;&lt;/label&gt;
+&lt;label for=&quot;searchbar&quot;&gt;&lt;img src=&quot;{% admin_media_prefix %}img/admin/icon_searchbox.png&quot; alt=&quot;Search&quot; /&gt;&lt;/label&gt;
 &lt;input type=&quot;text&quot; size=&quot;40&quot; name=&quot;{{ search_var }}&quot; value=&quot;{{ cl.query|escape }}&quot; id=&quot;searchbar&quot; /&gt;
 &lt;input type=&quot;submit&quot; value=&quot;{% trans 'Go' %}&quot; /&gt;
 {% if show_result_count %}</diff>
      <filename>django/contrib/admin/templates/admin/search_form.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 
 {% block content %}
 </diff>
      <filename>django/contrib/admin/templates/admin/template_validator.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 
 {% block breadcrumbs %}{% load i18n %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;{% trans &quot;Home&quot; %}&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;{% trans &quot;Documentation&quot; %}&lt;/a&gt; &amp;rsaquo; {% trans &quot;Bookmarklets&quot; %}&lt;/div&gt;{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/bookmarklets.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; Documentation&lt;/div&gt;{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; Documentation&lt;/div&gt;{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/missing_docutils.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block userlinks %}&lt;a href=&quot;../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
 {% block extrahead %}
@@ -41,6 +41,6 @@
 &lt;/table&gt;
 &lt;/div&gt;
 
-&lt;p class=&quot;small&quot;&gt;&lt;a href=&quot;../&quot;&gt;&amp;lsaquo; Back to Models Documentation&lt;/p&gt;
+&lt;p class=&quot;small&quot;&gt;&lt;a href=&quot;../&quot;&gt;&amp;lsaquo; Back to Models Documentation&lt;/a&gt;&lt;/p&gt;
 &lt;/div&gt;
 {% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/model_detail.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block coltype %}colSM{% endblock %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; Models&lt;/div&gt;{% endblock %}
@@ -8,18 +8,19 @@
 
 {% block content %}
 
-&lt;h1&gt;Models Documentation&lt;/h1&gt;
+&lt;h1&gt;Model documentation&lt;/h1&gt;
+
+{% regroup models by app_label as grouped_models %}
 
 &lt;div id=&quot;content-main&quot;&gt;
-{% regroup models|dictsort:&quot;module&quot; by module as grouped_models %}
 {% for group in grouped_models %}
 &lt;div class=&quot;module&quot;&gt;
-&lt;h2 id='{{ group.grouper }}'&gt;{{ group.grouper }}&lt;/h2&gt;
+&lt;h2 id=&quot;{{ group.grouper }}&quot;&gt;{{ group.grouper|capfirst }}&lt;/h2&gt;
 
 &lt;table class=&quot;xfull&quot;&gt;
 {% for model in group.list %}
 &lt;tr&gt;
-&lt;th&gt;&lt;a href=&quot;{{ model.name }}/&quot;&gt;{{ model.class }}&lt;/a&gt;&lt;/th&gt;
+&lt;th&gt;&lt;a href=&quot;{{ model.app_label }}.{{ model.object_name.lower }}/&quot;&gt;{{ model.object_name }}&lt;/a&gt;&lt;/th&gt;
 &lt;/tr&gt;
 {% endfor %}
 &lt;/table&gt;
@@ -32,11 +33,11 @@
 {% block sidebar %}
 &lt;div id=&quot;content-related&quot; class=&quot;sidebar&quot;&gt;
 &lt;div class=&quot;module&quot;&gt;
-&lt;h2&gt;Model Groups Quick List&lt;/h2&gt;
+&lt;h2&gt;Model groups&lt;/h2&gt;
 &lt;ul&gt;
-{% regroup models|dictsort:&quot;module&quot; by module as grouped_models %}
+{% regroup models by app_label as grouped_models %}
 {% for group in grouped_models %}
-    &lt;li&gt;&lt;a href=&quot;#{{ group.grouper }}&quot;&gt;{{ group.grouper }}&lt;/a&gt;&lt;/li&gt;
+    &lt;li&gt;&lt;a href=&quot;#{{ group.grouper }}&quot;&gt;{{ group.grouper|capfirst }}&lt;/a&gt;&lt;/li&gt;
 {% endfor %}
 &lt;/ul&gt;
 &lt;/div&gt;</diff>
      <filename>django/contrib/admin/templates/admin_doc/model_index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; Templates &amp;rsaquo; {{ name }}&lt;/div&gt;{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/template_detail.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block coltype %}colSM{% endblock %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; filters&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/template_filter_index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block coltype %}colSM{% endblock %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; Tags&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/template_tag_index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;Views&lt;/a&gt; &amp;rsaquo; {{ name }}&lt;/div&gt;{% endblock %}
 {% block userlinks %}&lt;a href=&quot;../../../password_change/&quot;&gt;{% trans 'Change password' %}&lt;/a&gt; / &lt;a href=&quot;../../../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/view_detail.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block coltype %}colSM{% endblock %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../../&quot;&gt;Home&lt;/a&gt; &amp;rsaquo; &lt;a href=&quot;../&quot;&gt;Documentation&lt;/a&gt; &amp;rsaquo; Views&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/admin_doc/view_index.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;{% trans 'Home' %}&lt;/a&gt;&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/registration/logged_out.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;{% trans 'Home' %}&lt;/a&gt; &amp;rsaquo; {% trans 'Password change' %}&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/registration/password_change_done.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 {% block userlinks %}&lt;a href=&quot;../doc/&quot;&gt;{% trans 'Documentation' %}&lt;/a&gt; / {% trans 'Change password' %} / &lt;a href=&quot;../logout/&quot;&gt;{% trans 'Log out' %}&lt;/a&gt;{% endblock %}
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;{% trans 'Home' %}&lt;/a&gt; &amp;rsaquo; {% trans 'Password change' %}&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/registration/password_change_form.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;{% trans 'Home' %}&lt;/a&gt; &amp;rsaquo; {% trans 'Password reset' %}&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/registration/password_reset_done.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-{% extends &quot;admin/base_site&quot; %}
+{% extends &quot;admin/base_site.html&quot; %}
 {% load i18n %}
 
 {% block breadcrumbs %}&lt;div class=&quot;breadcrumbs&quot;&gt;&lt;a href=&quot;../&quot;&gt;{% trans 'Home' %}&lt;/a&gt; &amp;rsaquo; {% trans 'Password reset' %}&lt;/div&gt;{% endblock %}</diff>
      <filename>django/contrib/admin/templates/registration/password_reset_form.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,20 @@
 {% load admin_modify adminmedia %}
 {% output_all bound_field.form_fields %}
 {% if bound_field.raw_id_admin %}
-{% if bound_field.field.rel.limit_choices_to %}
-    &lt;a href=&quot;../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/?{% for limit_choice in bound_field.field.rel.limit_choices_to.items %}{% if not forloop.first %}{{&quot;&amp;&quot;|escape}}{% endif %}{{ limit_choice|join:&quot;=&quot; }}{% endfor %}&quot; class=&quot;related-lookup&quot; id=&quot;lookup_{{ bound_field.element_id }}&quot; onclick=&quot;return showRelatedObjectLookupPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/selector-search.gif&quot; width=&quot;16&quot; height=&quot;16&quot; alt=&quot;Lookup&quot;&gt;&lt;/a&gt;
-{% else %}
-    &lt;a href=&quot;../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/&quot; class=&quot;related-lookup&quot; id=&quot;lookup_{{ bound_field.element_id }}&quot; onclick=&quot;return showRelatedObjectLookupPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/selector-search.gif&quot; width=&quot;16&quot; height=&quot;16&quot; alt=&quot;Lookup&quot;&gt;&lt;/a&gt;
-{% endif %}
+    {% if bound_field.field.rel.limit_choices_to %}
+        &lt;a href=&quot;{{ bound_field.related_url }}?{% for limit_choice in bound_field.field.rel.limit_choices_to.items %}{% if not forloop.first %}&amp;amp;{% endif %}{{ limit_choice|join:&quot;=&quot; }}{% endfor %}&quot; class=&quot;related-lookup&quot; id=&quot;lookup_{{ bound_field.element_id }}&quot; onclick=&quot;return showRelatedObjectLookupPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/selector-search.gif&quot; width=&quot;16&quot; height=&quot;16&quot; alt=&quot;Lookup&quot;&gt;&lt;/a&gt;
+    {% else %}
+        &lt;a href=&quot;{{ bound_field.related_url }}&quot; class=&quot;related-lookup&quot; id=&quot;lookup_{{ bound_field.element_id }}&quot; onclick=&quot;return showRelatedObjectLookupPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/selector-search.gif&quot; width=&quot;16&quot; height=&quot;16&quot; alt=&quot;Lookup&quot;&gt;&lt;/a&gt;
+    {% endif %}
 {% else %}
 {% if bound_field.needs_add_label %}
-    &lt;a href=&quot;../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/add/&quot; class=&quot;add-another&quot; id=&quot;add_{{ bound_field.element_id }}&quot; onclick=&quot;return showAddAnotherPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/icon_addlink.gif&quot; width=&quot;10&quot; height=&quot;10&quot; alt=&quot;Add Another&quot;/&gt;&lt;/a&gt;
+    &lt;a href=&quot;{{ bound_field.related_url }}add/&quot; class=&quot;add-another&quot; id=&quot;add_{{ bound_field.element_id }}&quot; onclick=&quot;return showAddAnotherPopup(this);&quot;&gt; &lt;img src=&quot;{% admin_media_prefix %}img/admin/icon_addlink.gif&quot; width=&quot;10&quot; height=&quot;10&quot; alt=&quot;Add Another&quot;/&gt;&lt;/a&gt;
 {% endif %}{% endif %}
+{% if change %}
+    {% if bound_field.field.primary_key %}
+        {{ bound_field.original_value }}
+    {% endif %}
+    {% if bound_field.raw_id_admin %}
+        {% if bound_field.existing_display %}&amp;nbsp;&lt;strong&gt;{{ bound_field.existing_display|truncatewords:&quot;14&quot; }}&lt;/strong&gt;{% endif %}
+    {% endif %}
+{% endif %}</diff>
      <filename>django/contrib/admin/templates/widget/foreign.html</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-{% include &quot;widget/foreign&quot; %}
+{% include &quot;widget/foreign.html&quot; %}</diff>
      <filename>django/contrib/admin/templates/widget/many_to_many.html</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1,2 @@
-{% include &quot;widget/foreign&quot; %}
+{% if add %}{% include &quot;widget/foreign.html&quot; %}{% endif %}
+{% if change %}{% if bound_field.existing_display %}&amp;nbsp;&lt;strong&gt;{{ bound_field.existing_display|truncatewords:&quot;14&quot; }}&lt;/strong&gt;{% endif %}{% endif %}</diff>
      <filename>django/contrib/admin/templates/widget/one_to_one.html</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,15 @@
-from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, DEFAULT_RESULTS_PER_PAGE, ALL_VAR
+from django import template
+from django.conf import settings
+from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR
 from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
 from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS
-from django.core import meta, template
 from django.core.exceptions import ObjectDoesNotExist
+from django.db import models
 from django.utils import dateformat
 from django.utils.html import escape
 from django.utils.text import capfirst
 from django.utils.translation import get_date_formats
-from django.conf.settings import ADMIN_MEDIA_PREFIX
-from django.core.template import Library
+from django.template import Library
 
 register = Library()
 
@@ -16,11 +17,11 @@ DOT = '.'
 
 def paginator_number(cl,i):
     if i == DOT:
-       return '... '
+        return '... '
     elif i == cl.page_num:
-       return '&lt;span class=&quot;this-page&quot;&gt;%d&lt;/span&gt; ' % (i+1)
+        return '&lt;span class=&quot;this-page&quot;&gt;%d&lt;/span&gt; ' % (i+1)
     else:
-       return '&lt;a href=&quot;%s&quot;%s&gt;%d&lt;/a&gt; ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class=&quot;end&quot;' or ''), i+1)
+        return '&lt;a href=&quot;%s&quot;%s&gt;%d&lt;/a&gt; ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class=&quot;end&quot;' or ''), i+1)
 paginator_number = register.simple_tag(paginator_number)
 
 def pagination(cl):
@@ -64,7 +65,7 @@ def pagination(cl):
         'ALL_VAR': ALL_VAR,
         '1': 1,
     }
-pagination = register.inclusion_tag('admin/pagination')(pagination)
+pagination = register.inclusion_tag('admin/pagination.html')(pagination)
 
 def result_headers(cl):
     lookup_opts = cl.lookup_opts
@@ -72,22 +73,22 @@ def result_headers(cl):
     for i, field_name in enumerate(lookup_opts.admin.list_display):
         try:
             f = lookup_opts.get_field(field_name)
-        except meta.FieldDoesNotExist:
+        except models.FieldDoesNotExist:
             # For non-field list_display values, check for the function
             # attribute &quot;short_description&quot;. If that doesn't exist, fall
-            # back to the method name. And __repr__ is a special-case.
-            if field_name == '__repr__':
+            # back to the method name. And __str__ is a special-case.
+            if field_name == '__str__':
                 header = lookup_opts.verbose_name
             else:
-                func = getattr(cl.mod.Klass, field_name) # Let AttributeErrors propagate.
+                attr = getattr(cl.model, field_name) # Let AttributeErrors propagate.
                 try:
-                    header = func.short_description
+                    header = attr.short_description
                 except AttributeError:
-                    header = func.__name__.replace('_', ' ')
+                    header = field_name.replace('_', ' ')
             # Non-field list_display values don't get ordering capability.
             yield {&quot;text&quot;: header}
         else:
-            if isinstance(f.rel, meta.ManyToOneRel) and f.null:
+            if isinstance(f.rel, models.ManyToOneRel) and f.null:
                 yield {&quot;text&quot;: f.verbose_name}
             else:
                 th_classes = []
@@ -108,34 +109,37 @@ def items_for_result(cl, result):
         row_class = ''
         try:
             f = cl.lookup_opts.get_field(field_name)
-        except meta.FieldDoesNotExist:
-            # For non-field list_display values, the value is a method
-            # name. Execute the method.
+        except models.FieldDoesNotExist:
+            # For non-field list_display values, the value is either a method
+            # or a property.
             try:
-                func = getattr(result, field_name)
-                result_repr = str(func())
+                attr = getattr(result, field_name)
+                allow_tags = getattr(attr, 'allow_tags', False)
+                if callable(attr):
+                    attr = attr()
+                result_repr = str(attr)
             except AttributeError, ObjectDoesNotExist:
                 result_repr = EMPTY_CHANGELIST_VALUE
             else:
                 # Strip HTML tags in the resulting text, except if the
                 # function has an &quot;allow_tags&quot; attribute set to True.
-                if not getattr(func, 'allow_tags', False):
+                if not allow_tags:
                     result_repr = escape(result_repr)
         else:
             field_val = getattr(result, f.attname)
 
-            if isinstance(f.rel, meta.ManyToOneRel):
+            if isinstance(f.rel, models.ManyToOneRel):
                 if field_val is not None:
-                    result_repr = getattr(result, 'get_%s' % f.name)()
+                    result_repr = getattr(result, f.name)
                 else:
                     result_repr = EMPTY_CHANGELIST_VALUE
             # Dates and times are special: They're formatted in a certain way.
-            elif isinstance(f, meta.DateField) or isinstance(f, meta.TimeField):
+            elif isinstance(f, models.DateField) or isinstance(f, models.TimeField):
                 if field_val:
                     (date_format, datetime_format, time_format) = get_date_formats()
-                    if isinstance(f, meta.DateTimeField):
+                    if isinstance(f, models.DateTimeField):
                         result_repr = capfirst(dateformat.format(field_val, datetime_format))
-                    elif isinstance(f, meta.TimeField):
+                    elif isinstance(f, models.TimeField):
                         result_repr = capfirst(dateformat.time_format(field_val, time_format))
                     else:
                         result_repr = capfirst(dateformat.format(field_val, date_format))
@@ -143,15 +147,15 @@ def items_for_result(cl, result):
                     result_repr = EMPTY_CHANGELIST_VALUE
                 row_class = ' class=&quot;nowrap&quot;'
             # Booleans are special: We use images.
-            elif isinstance(f, meta.BooleanField) or isinstance(f, meta.NullBooleanField):
+            elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField):
                 BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
-                result_repr = '&lt;img src=&quot;%simg/admin/icon-%s.gif&quot; alt=&quot;%s&quot; /&gt;' % (ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
+                result_repr = '&lt;img src=&quot;%simg/admin/icon-%s.gif&quot; alt=&quot;%s&quot; /&gt;' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
             # ImageFields are special: Use a thumbnail.
-            elif isinstance(f, meta.ImageField):
+            elif isinstance(f, models.ImageField):
                 from django.parts.media.photos import get_thumbnail_url
                 result_repr = '&lt;img src=&quot;%s&quot; alt=&quot;%s&quot; title=&quot;%s&quot; /&gt;' % (get_thumbnail_url(getattr(result, 'get_%s_url' % f.name)(), '120'), field_val, field_val)
             # FloatFields are special: Zero-pad the decimals.
-            elif isinstance(f, meta.FloatField):
+            elif isinstance(f, models.FloatField):
                 if field_val is not None:
                     result_repr = ('%%.%sf' % f.decimal_places) % field_val
                 else:
@@ -163,7 +167,7 @@ def items_for_result(cl, result):
             else:
                 result_repr = escape(str(field_val))
         if result_repr == '':
-                result_repr = '&amp;nbsp;'
+            result_repr = '&amp;nbsp;'
         if first: # First column is a special case
             first = False
             url = cl.url_for_result(result)
@@ -181,28 +185,20 @@ def result_list(cl):
     return {'cl': cl,
             'result_headers': list(result_headers(cl)),
             'results': list(results(cl))}
-result_list = register.inclusion_tag(&quot;admin/change_list_results&quot;)(result_list)
+result_list = register.inclusion_tag(&quot;admin/change_list_results.html&quot;)(result_list)
 
 def date_hierarchy(cl):
-    lookup_opts, params, lookup_params, lookup_mod = \
-      cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod
-
-    if lookup_opts.admin.date_hierarchy:
-        field_name = lookup_opts.admin.date_hierarchy
-
+    if cl.lookup_opts.admin.date_hierarchy:
+        field_name = cl.lookup_opts.admin.date_hierarchy
         year_field = '%s__year' % field_name
         month_field = '%s__month' % field_name
         day_field = '%s__day' % field_name
         field_generic = '%s__' % field_name
-        year_lookup = params.get(year_field)
-        month_lookup = params.get(month_field)
-        day_lookup = params.get(day_field)
-
-        def link(d):
-            return cl.get_query_string(d, [field_generic])
+        year_lookup = cl.params.get(year_field)
+        month_lookup = cl.params.get(month_field)
+        day_lookup = cl.params.get(day_field)
 
-        def get_dates(unit, params):
-            return getattr(lookup_mod, 'get_%s_list' % field_name)(unit, **params)
+        link = lambda d: cl.get_query_string(d, [field_generic])
 
         if year_lookup and month_lookup and day_lookup:
             month_name = MONTHS[int(month_lookup)]
@@ -215,9 +211,7 @@ def date_hierarchy(cl):
                 'choices': [{'title': &quot;%s %s&quot; % (month_name, day_lookup)}]
             }
         elif year_lookup and month_lookup:
-            date_lookup_params = lookup_params.copy()
-            date_lookup_params.update({year_field: year_lookup, month_field: month_lookup})
-            days = get_dates('day', date_lookup_params)
+            days = cl.query_set.filter(**{year_field: year_lookup, month_field: month_lookup}).dates(field_name, 'day')
             return {
                 'show': True,
                 'back': {
@@ -230,9 +224,7 @@ def date_hierarchy(cl):
                 } for day in days]
             }
         elif year_lookup:
-            date_lookup_params = lookup_params.copy()
-            date_lookup_params.update({year_field: year_lookup})
-            months = get_dates('month', date_lookup_params)
+            months = cl.query_set.filter(**{year_field: year_lookup}).dates(field_name, 'month')
             return {
                 'show' : True,
                 'back': {
@@ -240,20 +232,20 @@ def date_hierarchy(cl):
                     'title': _('All dates')
                 },
                 'choices': [{
-                    'link': link( {year_field: year_lookup, month_field: month.month}),
-                    'title': &quot;%s %s&quot; % (month.strftime('%B') ,  month.year)
+                    'link': link({year_field: year_lookup, month_field: month.month}),
+                    'title': &quot;%s %s&quot; % (month.strftime('%B'), month.year)
                 } for month in months]
             }
         else:
-            years = get_dates('year', lookup_params)
+            years = cl.query_set.dates(field_name, 'year')
             return {
                 'show': True,
                 'choices': [{
                     'link': link({year_field: year.year}),
                     'title': year.year
-                } for year in years ]
+                } for year in years]
             }
-date_hierarchy = register.inclusion_tag('admin/date_hierarchy')(date_hierarchy)
+date_hierarchy = register.inclusion_tag('admin/date_hierarchy.html')(date_hierarchy)
 
 def search_form(cl):
     return {
@@ -261,12 +253,12 @@ def search_form(cl):
         'show_result_count': cl.result_count != cl.full_result_count and not cl.opts.one_to_one_field,
         'search_var': SEARCH_VAR
     }
-search_form = register.inclusion_tag('admin/search_form')(search_form)
+search_form = register.inclusion_tag('admin/search_form.html')(search_form)
 
 def filter(cl, spec):
     return {'title': spec.title(), 'choices' : list(spec.choices(cl))}
-filter = register.inclusion_tag('admin/filter')(filter)
+filter = register.inclusion_tag('admin/filter.html')(filter)
 
 def filters(cl):
     return {'cl': cl}
-filters = register.inclusion_tag('admin/filters')(filters)
+filters = register.inclusion_tag('admin/filters.html')(filters)</diff>
      <filename>django/contrib/admin/templatetags/admin_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,13 @@
-from django.core import template, template_loader, meta
+from django import template
+from django.contrib.admin.views.main import AdminBoundField
+from django.template import loader
 from django.utils.html import escape
 from django.utils.text import capfirst
 from django.utils.functional import curry
-from django.contrib.admin.views.main import AdminBoundField
-from django.core.meta.fields import BoundField, Field
-from django.core.meta import BoundRelatedObject, TABULAR, STACKED
-from django.conf.settings import ADMIN_MEDIA_PREFIX
+from django.db import models
+from django.db.models.fields import Field
+from django.db.models.related import BoundRelatedObject
+from django.conf import settings
 import re
 
 register = template.Library()
@@ -16,30 +18,28 @@ def class_name_to_underscored(name):
     return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
 
 def include_admin_script(script_path):
-    return '&lt;script type=&quot;text/javascript&quot; src=&quot;%s%s&quot;&gt;&lt;/script&gt;' % (ADMIN_MEDIA_PREFIX, script_path)
+    return '&lt;script type=&quot;text/javascript&quot; src=&quot;%s%s&quot;&gt;&lt;/script&gt;' % (settings.ADMIN_MEDIA_PREFIX, script_path)
 include_admin_script = register.simple_tag(include_admin_script)
 
-def submit_row(context, bound_manipulator):
+def submit_row(context):
+    opts = context['opts']
     change = context['change']
-    add = context['add']
-    show_delete = context['show_delete']
-    has_delete_permission = context['has_delete_permission']
     is_popup = context['is_popup']
     return {
-        'onclick_attrib': (bound_manipulator.ordered_objects and change
+        'onclick_attrib': (opts.get_ordered_objects() and change
                             and 'onclick=&quot;submitOrderForm();&quot;' or ''),
-        'show_delete_link': (not is_popup and has_delete_permission
-                              and (change or show_delete)),
-        'show_save_as_new': not is_popup and change and bound_manipulator.save_as,
-        'show_save_and_add_another': not is_popup and (not bound_manipulator.save_as or add),
-        'show_save_and_continue': not is_popup,
+        'show_delete_link': (not is_popup and context['has_delete_permission']
+                              and (change or context['show_delete'])),
+        'show_save_as_new': not is_popup and change and opts.admin.save_as,
+        'show_save_and_add_another': not is_popup and (not opts.admin.save_as or context['add']),
+        'show_save_and_continue': not is_popup and context['has_change_permission'],
         'show_save': True
     }
-submit_row = register.inclusion_tag('admin/submit_line', takes_context=True)(submit_row)
+submit_row = register.inclusion_tag('admin/submit_line.html', takes_context=True)(submit_row)
 
 def field_label(bound_field):
     class_names = []
-    if isinstance(bound_field.field, meta.BooleanField):
+    if isinstance(bound_field.field, models.BooleanField):
         class_names.append(&quot;vCheckboxLabel&quot;)
         colon = &quot;&quot;
     else:
@@ -64,16 +64,15 @@ class FieldWidgetNode(template.Node):
         if not cls.nodelists.has_key(klass):
             try:
                 field_class_name = klass.__name__
-                template_name = &quot;widget/%s&quot; % \
-                    class_name_to_underscored(field_class_name)
-                nodelist = template_loader.get_template(template_name).nodelist
+                template_name = &quot;widget/%s.html&quot; % class_name_to_underscored(field_class_name)
+                nodelist = loader.get_template(template_name).nodelist
             except template.TemplateDoesNotExist:
                 super_klass = bool(klass.__bases__) and klass.__bases__[0] or None
                 if super_klass and super_klass != Field:
                     nodelist = cls.get_nodelist(super_klass)
                 else:
                     if not cls.default:
-                        cls.default = template_loader.get_template(&quot;widget/default&quot;).nodelist
+                        cls.default = loader.get_template(&quot;widget/default.html&quot;).nodelist
                     nodelist = cls.default
 
             cls.nodelists[klass] = nodelist
@@ -97,21 +96,22 @@ class FieldWrapper(object):
         self.field = field
 
     def needs_header(self):
-        return not isinstance(self.field, meta.AutoField)
+        return not isinstance(self.field, models.AutoField)
 
     def header_class_attribute(self):
         return self.field.blank and ' class=&quot;optional&quot;' or ''
 
     def use_raw_id_admin(self):
-         return isinstance(self.field.rel, (meta.ManyToOneRel, meta.ManyToManyRel)) \
+        return isinstance(self.field.rel, (models.ManyToOneRel, models.ManyToManyRel)) \
             and self.field.rel.raw_id_admin
 
 class FormFieldCollectionWrapper(object):
-    def __init__(self, field_mapping, fields):
+    def __init__(self, field_mapping, fields, index):
         self.field_mapping = field_mapping
         self.fields = fields
         self.bound_fields = [AdminBoundField(field, self.field_mapping, field_mapping['original'])
                              for field in self.fields]
+        self.index = index
 
 class TabularBoundRelatedObject(BoundRelatedObject):
     def __init__(self, related_object, field_mapping, original):
@@ -120,29 +120,25 @@ class TabularBoundRelatedObject(BoundRelatedObject):
 
         fields = self.relation.editable_fields()
 
-        self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping, fields)
-                                               for field_mapping in self.field_mappings]
+        self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping, fields, i)
+                                               for (i,field_mapping) in self.field_mappings.items() ]
         self.original_row_needed = max([fw.use_raw_id_admin() for fw in self.field_wrapper_list])
         self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url')
 
     def template_name(self):
-        return &quot;admin/edit_inline_tabular&quot;
+        return &quot;admin/edit_inline_tabular.html&quot;
 
 class StackedBoundRelatedObject(BoundRelatedObject):
     def __init__(self, related_object, field_mapping, original):
         super(StackedBoundRelatedObject, self).__init__(related_object, field_mapping, original)
         fields = self.relation.editable_fields()
-        self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping ,fields)
-                                               for field_mapping in self.field_mappings]
+        self.field_mappings.fill()
+        self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping ,fields, i)
+                                               for (i,field_mapping) in self.field_mappings.items()]
         self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url')
 
     def template_name(self):
-        return &quot;admin/edit_inline_stacked&quot;
-
-bound_related_object_overrides = {
-    TABULAR: TabularBoundRelatedObject,
-    STACKED: StackedBoundRelatedObject,
-}
+        return &quot;admin/edit_inline_stacked.html&quot;
 
 class EditInlineNode(template.Node):
     def __init__(self, rel_var):
@@ -150,21 +146,16 @@ class EditInlineNode(template.Node):
 
     def render(self, context):
         relation = template.resolve_variable(self.rel_var, context)
-
         context.push()
-
-        klass = relation.field.rel.edit_inline
-        bound_related_object_class = bound_related_object_overrides.get(klass, klass)
-
+        if relation.field.rel.edit_inline == models.TABULAR:
+            bound_related_object_class = TabularBoundRelatedObject
+        else:
+            bound_related_object_class = StackedBoundRelatedObject
         original = context.get('original', None)
-
         bound_related_object = relation.bind(context['form'], original, bound_related_object_class)
         context['bound_related_object'] = bound_related_object
-
-        t = template_loader.get_template(bound_related_object.template_name())
-
+        t = loader.get_template(bound_related_object.template_name())
         output = t.render(context)
-
         context.pop()
         return output
 
@@ -191,30 +182,30 @@ auto_populated_field_script = register.simple_tag(auto_populated_field_script)
 
 def filter_interface_script_maybe(bound_field):
     f = bound_field.field
-    if f.rel and isinstance(f.rel, meta.ManyToManyRel) and f.rel.filter_interface:
-       return '&lt;script type=&quot;text/javascript&quot;&gt;addEvent(window, &quot;load&quot;, function(e) {' \
+    if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
+        return '&lt;script type=&quot;text/javascript&quot;&gt;addEvent(window, &quot;load&quot;, function(e) {' \
               ' SelectFilter.init(&quot;id_%s&quot;, &quot;%s&quot;, %s, &quot;%s&quot;); });&lt;/script&gt;\n' % (
-              f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)
+              f.name, f.verbose_name, f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
     else:
         return ''
 filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)
 
-def do_one_arg_tag(node_factory, parser,token):
-    tokens = token.contents.split()
-    if len(tokens) != 2:
-        raise template.TemplateSyntaxError(&quot;%s takes 1 argument&quot; % tokens[0])
-    return node_factory(tokens[1])
-
-def register_one_arg_tag(node):
-    tag_name = class_name_to_underscored(node.__name__)
-    parse_func = curry(do_one_arg_tag, node)
-    register.tag(tag_name, parse_func)
+def field_widget(parser, token):
+    bits = token.contents.split()
+    if len(bits) != 2:
+        raise template.TemplateSyntaxError, &quot;%s takes 1 argument&quot; % bits[0]
+    return FieldWidgetNode(bits[1])
+field_widget = register.tag(field_widget)
 
-register_one_arg_tag(FieldWidgetNode)
-register_one_arg_tag(EditInlineNode)
+def edit_inline(parser, token):
+    bits = token.contents.split()
+    if len(bits) != 2:
+        raise template.TemplateSyntaxError, &quot;%s takes 1 argument&quot; % bits[0]
+    return EditInlineNode(bits[1])
+edit_inline = register.tag(edit_inline)
 
 def admin_field_line(context, argument_val):
-    if (isinstance(argument_val, BoundField)):
+    if isinstance(argument_val, AdminBoundField):
         bound_fields = [argument_val]
     else:
         bound_fields = [bf for bf in argument_val]
@@ -229,7 +220,7 @@ def admin_field_line(context, argument_val):
                 break
 
     # Assumes BooleanFields won't be stacked next to each other!
-    if isinstance(bound_fields[0].field, meta.BooleanField):
+    if isinstance(bound_fields[0].field, models.BooleanField):
         class_names.append('checkbox-row')
 
     return {
@@ -238,8 +229,4 @@ def admin_field_line(context, argument_val):
         'bound_fields': bound_fields,
         'class_names': &quot; &quot;.join(class_names),
     }
-admin_field_line = register.inclusion_tag('admin/field_line', takes_context=True)(admin_field_line)
-
-def object_pk(bound_manip, ordered_obj):
-    return bound_manip.get_ordered_object_pk(ordered_obj)
-object_pk = register.simple_tag(object_pk)
+admin_field_line = register.inclusion_tag('admin/field_line.html', takes_context=True)(admin_field_line)</diff>
      <filename>django/contrib/admin/templatetags/admin_modify.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
-from django.core import template
+from django import template
+from django.db.models import get_models
 
 register = template.Library()
 
@@ -7,20 +8,24 @@ class AdminApplistNode(template.Node):
         self.varname = varname
 
     def render(self, context):
-        from django.core import meta
+        from django.db import models
         from django.utils.text import capfirst
         app_list = []
         user = context['user']
 
-        for app in meta.get_installed_model_modules():
-            app_label = app.__name__[app.__name__.rindex('.')+1:]
+        for app in models.get_apps():
+            # Determine the app_label.
+            app_models = get_models(app)
+            if not app_models:
+                continue
+            app_label = app_models[0]._meta.app_label
+
             has_module_perms = user.has_module_perms(app_label)
 
             if has_module_perms:
                 model_list = []
-                for m in app._MODELS:
+                for m in app_models:
                     if m._meta.admin:
-                        module_name = m._meta.module_name
                         perms = {
                             'add': user.has_perm(&quot;%s.%s&quot; % (app_label, m._meta.get_add_permission())),
                             'change': user.has_perm(&quot;%s.%s&quot; % (app_label, m._meta.get_change_permission())),
@@ -32,7 +37,7 @@ class AdminApplistNode(template.Node):
                         if True in perms.values():
                             model_list.append({
                                 'name': capfirst(m._meta.verbose_name_plural),
-                                'admin_url': '%s/%s/' % (app_label, m._meta.module_name),
+                                'admin_url': '%s/%s/' % (app_label, m.__name__.lower()),
                                 'perms': perms,
                             })
 </diff>
      <filename>django/contrib/admin/templatetags/adminapplist.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,11 @@
-from django.core.template import Library
+from django.template import Library
+
 register = Library()
 
 def admin_media_prefix():
     try:
-        from django.conf.settings import ADMIN_MEDIA_PREFIX
+        from django.conf import settings
     except ImportError:
         return ''
-    return ADMIN_MEDIA_PREFIX
+    return settings.ADMIN_MEDIA_PREFIX
 admin_media_prefix = register.simple_tag(admin_media_prefix)</diff>
      <filename>django/contrib/admin/templatetags/adminmedia.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
-from django.models.admin import log
-from django.core import template
+from django import template
+from django.contrib.admin.models import LogEntry
 
 register = template.Library()
 
@@ -13,7 +13,7 @@ class AdminLogNode(template.Node):
     def render(self, context):
         if self.user is not None and not self.user.isdigit():
             self.user = context[self.user].id
-        context[self.varname] = log.get_list(user__id__exact=self.user, limit=self.limit, select_related=True)
+        context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit]
         return ''
 
 class DoGetAdminLog:</diff>
      <filename>django/contrib/admin/templatetags/log.py</filename>
    </modified>
    <modified>
      <diff>@@ -82,18 +82,18 @@ ROLES = {
 
 def create_reference_role(rolename, urlbase):
     def _role(name, rawtext, text, lineno, inliner, options={}, content=[]):
-        node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text)), **options)
+        node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text.lower())), **options)
         return [node], []
     docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
 
 def default_reference_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
     context = inliner.document.settings.default_reference_context
-    node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text)), **options)
+    node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text.lower())), **options)
     return [node], []
 
 if docutils_is_available:
     docutils.parsers.rst.roles.register_canonical_role('cmsreference', default_reference_role)
     docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'cmsreference'
 
-    for (name, urlbase) in ROLES.items():
+    for name, urlbase in ROLES.items():
         create_reference_role(name, urlbase)</diff>
      <filename>django/contrib/admin/utils.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
-from django.core.extensions import DjangoContext, render_to_response
-from django.conf.settings import SECRET_KEY
-from django.models.auth import users
-from django.utils import httpwrappers
+from django import http, template
+from django.conf import settings
+from django.contrib.auth.models import User, SESSION_KEY
+from django.shortcuts import render_to_response
 from django.utils.translation import gettext_lazy
 import base64, datetime, md5
 import cPickle as pickle
@@ -19,22 +19,22 @@ def _display_login_form(request, error_message=''):
         post_data = _encode_post_data(request.POST)
     else:
         post_data = _encode_post_data({})
-    return render_to_response('admin/login', {
+    return render_to_response('admin/login.html', {
         'title': _('Log in'),
         'app_path': request.path,
         'post_data': post_data,
         'error_message': error_message
-    }, context_instance=DjangoContext(request))
+    }, context_instance=template.RequestContext(request))
 
 def _encode_post_data(post_data):
     pickled = pickle.dumps(post_data)
-    pickled_md5 = md5.new(pickled + SECRET_KEY).hexdigest()
+    pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
     return base64.encodestring(pickled + pickled_md5)
 
 def _decode_post_data(encoded_data):
     encoded_data = base64.decodestring(encoded_data)
     pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
-    if md5.new(pickled + SECRET_KEY).hexdigest() != tamper_check:
+    if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
         from django.core.exceptions import SuspiciousOperation
         raise SuspiciousOperation, &quot;User may have tampered with session cookie.&quot;
     return pickle.loads(pickled)
@@ -53,7 +53,7 @@ def staff_member_required(view_func):
                 request.POST = _decode_post_data(request.POST['post_data'])
             return view_func(request, *args, **kwargs)
 
-        assert hasattr(request, 'session'), &quot;The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.middleware.sessions.SessionMiddleware'.&quot;
+        assert hasattr(request, 'session'), &quot;The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'.&quot;
 
         # If this isn't already the login page, display it.
         if not request.POST.has_key(LOGIN_FORM_KEY):
@@ -71,14 +71,14 @@ def staff_member_required(view_func):
         # Check the password.
         username = request.POST.get('username', '')
         try:
-            user = users.get_object(username__exact=username, is_staff__exact=True)
-        except users.UserDoesNotExist:
+            user = User.objects.get(username=username, is_staff=True)
+        except User.DoesNotExist:
             message = ERROR_MESSAGE
             if '@' in username:
                 # Mistakenly entered e-mail address instead of username? Look it up.
                 try:
-                    user = users.get_object(email__exact=username)
-                except users.UserDoesNotExist:
+                    user = User.objects.get(email=username)
+                except User.DoesNotExist:
                     message = _(&quot;Usernames cannot contain the '@' character.&quot;)
                 else:
                     message = _(&quot;Your e-mail address is not your username. Try '%s' instead.&quot;) % user.username
@@ -87,7 +87,7 @@ def staff_member_required(view_func):
         # The user data is correct; log in the user in and continue.
         else:
             if user.check_password(request.POST.get('password', '')):
-                request.session[users.SESSION_KEY] = user.id
+                request.session[SESSION_KEY] = user.id
                 user.last_login = datetime.datetime.now()
                 user.save()
                 if request.POST.has_key('post_data'):
@@ -99,7 +99,7 @@ def staff_member_required(view_func):
                         return view_func(request, *args, **kwargs)
                     else:
                         request.session.delete_test_cookie()
-                        return httpwrappers.HttpResponseRedirect(request.path)
+                        return http.HttpResponseRedirect(request.path)
             else:
                 return _display_login_form(request, ERROR_MESSAGE)
 </diff>
      <filename>django/contrib/admin/views/decorators.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,14 @@
-from django.core import meta
-from django import templatetags
+from django import template, templatetags
+from django.template import RequestContext
 from django.conf import settings
 from django.contrib.admin.views.decorators import staff_member_required
-from django.models.core import sites
-from django.core.extensions import DjangoContext, render_to_response
-from django.core.exceptions import Http404, ViewDoesNotExist
-from django.core import template, urlresolvers
+from django.db import models
+from django.shortcuts import render_to_response
+from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
+from django.http import Http404, get_host
+from django.core import urlresolvers
 from django.contrib.admin import utils
+from django.contrib.sites.models import Site
 import inspect, os, re
 
 # Exclude methods starting with these strings from documentation
@@ -15,15 +17,15 @@ MODEL_METHODS_EXCLUDE = ('_', 'add_', 'delete', 'save', 'set_')
 def doc_index(request):
     if not utils.docutils_is_available:
         return missing_docutils_page(request)
-    return render_to_response('admin_doc/index', context_instance=DjangoContext(request))
+    return render_to_response('admin_doc/index.html', context_instance=RequestContext(request))
 doc_index = staff_member_required(doc_index)
 
 def bookmarklets(request):
     # Hack! This couples this view to the URL it lives at.
     admin_root = request.path[:-len('doc/bookmarklets/')]
-    return render_to_response('admin_doc/bookmarklets', {
-        'admin_url': &quot;%s://%s%s&quot; % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', request.META['HTTP_HOST'], admin_root),
-    }, context_instance=DjangoContext(request))
+    return render_to_response('admin_doc/bookmarklets.html', {
+        'admin_url': &quot;%s://%s%s&quot; % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', get_host(request), admin_root),
+    }, context_instance=RequestContext(request))
 bookmarklets = staff_member_required(bookmarklets)
 
 def template_tag_index(request):
@@ -54,7 +56,7 @@ def template_tag_index(request):
                 'library': tag_library,
             })
 
-    return render_to_response('admin_doc/template_tag_index', {'tags': tags}, context_instance=DjangoContext(request))
+    return render_to_response('admin_doc/template_tag_index.html', {'tags': tags}, context_instance=RequestContext(request))
 template_tag_index = staff_member_required(template_tag_index)
 
 def template_filter_index(request):
@@ -84,16 +86,20 @@ def template_filter_index(request):
                 'meta': metadata,
                 'library': tag_library,
             })
-    return render_to_response('admin_doc/template_filter_index', {'filters': filters}, context_instance=DjangoContext(request))
+    return render_to_response('admin_doc/template_filter_index.html', {'filters': filters}, context_instance=RequestContext(request))
 template_filter_index = staff_member_required(template_filter_index)
 
 def view_index(request):
     if not utils.docutils_is_available:
         return missing_docutils_page(request)
 
+    if settings.ADMIN_FOR:
+        settings_modules = [__import__(m, '', '', ['']) for m in settings.ADMIN_FOR]
+    else:
+        settings_modules = [settings]
+
     views = []
-    for site_settings_module in settings.ADMIN_FOR:
-        settings_mod = __import__(site_settings_module, '', '', [''])
+    for settings_mod in settings_modules:
         urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
         view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
         for (func, regex) in view_functions:
@@ -101,10 +107,10 @@ def view_index(request):
                 'name': func.__name__,
                 'module': func.__module__,
                 'site_id': settings_mod.SITE_ID,
-                'site': sites.get_object(pk=settings_mod.SITE_ID),
+                'site': Site.objects.get(pk=settings_mod.SITE_ID),
                 'url': simplify_regex(regex),
             })
-    return render_to_response('admin_doc/view_index', {'views': views}, context_instance=DjangoContext(request))
+    return render_to_response('admin_doc/view_index.html', {'views': views}, context_instance=RequestContext(request))
 view_index = staff_member_required(view_index)
 
 def view_detail(request, view):
@@ -123,51 +129,63 @@ def view_detail(request, view):
         body = utils.parse_rst(body, 'view', 'view:' + view)
     for key in metadata:
         metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view)
-    return render_to_response('admin_doc/view_detail', {
+    return render_to_response('admin_doc/view_detail.html', {
         'name': view,
         'summary': title,
         'body': body,
         'meta': metadata,
-    }, context_instance=DjangoContext(request))
+    }, context_instance=RequestContext(request))
 view_detail = staff_member_required(view_detail)
 
 def model_index(request):
     if not utils.docutils_is_available:
         return missing_docutils_page(request)
 
-    models = []
-    for app in meta.get_installed_model_modules():
-        for model in app._MODELS:
-            opts = model._meta
-            models.append({
-                'name': '%s.%s' % (opts.app_label, opts.module_name),
-                'module': opts.app_label,
-                'class': opts.module_name,
-            })
-    return render_to_response('admin_doc/model_index', {'models': models}, context_instance=DjangoContext(request))
+    m_list = [m._meta for m in models.get_models()]
+    return render_to_response('admin_doc/model_index.html', {'models': m_list}, context_instance=RequestContext(request))
 model_index = staff_member_required(model_index)
 
-def model_detail(request, model):
+def model_detail(request, app_label, model_name):
     if not utils.docutils_is_available:
         return missing_docutils_page(request)
 
+    # Get the model class.
     try:
-        model = meta.get_app(model)
-    except ImportError:
-        raise Http404
-    opts = model.Klass._meta
+        app_mod = models.get_app(app_label)
+    except ImproperlyConfigured:
+        raise Http404, &quot;App %r not found&quot; % app_label
+    model = None
+    for m in models.get_models(app_mod):
+        if m._meta.object_name.lower() == model_name:
+            model = m
+            break
+    if model is None:
+        raise Http404, &quot;Model %r not found in app %r&quot; % (model_name, app_label)
 
-    # Gather fields/field descriptions
+    opts = model._meta
+
+    # Gather fields/field descriptions.
     fields = []
     for field in opts.fields:
+        # ForeignKey is a special case since the field will actually be a
+        # descriptor that returns the other object
+        if isinstance(field, models.ForeignKey):
+            data_type = related_object_name = field.rel.to.__name__
+            app_label = field.rel.to._meta.app_label
+            verbose = utils.parse_rst((&quot;the related `%s.%s` object&quot;  % (app_label, data_type)), 'model', 'model:' + data_type)
+        else:
+            data_type = get_readable_field_data_type(field)
+            verbose = field.verbose_name
         fields.append({
             'name': field.name,
-            'data_type': get_readable_field_data_type(field),
-            'verbose': field.verbose_name,
+            'data_type': data_type,
+            'verbose': verbose,
             'help': field.help_text,
         })
-    for func_name, func in model.Klass.__dict__.items():
-        if callable(func) and len(inspect.getargspec(func)[0]) == 0:
+
+    # Gather model methods.
+    for func_name, func in model.__dict__.items():
+        if (inspect.isfunction(func) and len(inspect.getargspec(func)[0]) == 1):
             try:
                 for exclude in MODEL_METHODS_EXCLUDE:
                     if func_name.startswith(exclude):
@@ -182,12 +200,26 @@ def model_detail(request, model):
                 'data_type': get_return_data_type(func_name),
                 'verbose': verbose,
             })
-    return render_to_response('admin_doc/model_detail', {
-        'name': '%s.%s' % (opts.app_label, opts.module_name),
-        'summary': &quot;Fields on %s objects&quot; % opts.verbose_name,
+
+    # Gather related objects
+    for rel in opts.get_all_related_objects():
+        verbose = &quot;related `%s.%s` objects&quot; % (rel.opts.app_label, rel.opts.object_name)
+        accessor = rel.get_accessor_name()
+        fields.append({
+            'name' : &quot;%s.all&quot; % accessor,
+            'verbose' : utils.parse_rst(&quot;all &quot; + verbose , 'model', 'model:' + opts.module_name),
+        })
+        fields.append({
+            'name' : &quot;%s.count&quot; % accessor,
+            'verbose' : utils.parse_rst(&quot;number of &quot; + verbose , 'model', 'model:' + opts.module_name),
+        })
+
+    return render_to_response('admin_doc/model_detail.html', {
+        'name': '%s.%s' % (opts.app_label, opts.object_name),
+        'summary': &quot;Fields on %s objects&quot; % opts.object_name,
         'description': model.__doc__,
         'fields': fields,
-    }, context_instance=DjangoContext(request))
+    }, context_instance=RequestContext(request))
 model_detail = staff_member_required(model_detail)
 
 def template_detail(request, template):
@@ -201,13 +233,13 @@ def template_detail(request, template):
                 'exists': os.path.exists(template_file),
                 'contents': lambda: os.path.exists(template_file) and open(template_file).read() or '',
                 'site_id': settings_mod.SITE_ID,
-                'site': sites.get_object(pk=settings_mod.SITE_ID),
+                'site': Site.objects.get(pk=settings_mod.SITE_ID),
                 'order': list(settings_mod.TEMPLATE_DIRS).index(dir),
             })
-    return render_to_response('admin_doc/template_detail', {
+    return render_to_response('admin_doc/template_detail.html', {
         'name': template,
         'templates': templates,
-    }, context_instance=DjangoContext(request))
+    }, context_instance=RequestContext(request))
 template_detail = staff_member_required(template_detail)
 
 ####################
@@ -216,7 +248,7 @@ template_detail = staff_member_required(template_detail)
 
 def missing_docutils_page(request):
     &quot;&quot;&quot;Display an error message for people without docutils&quot;&quot;&quot;
-    return render_to_response('admin_doc/missing_docutils')
+    return render_to_response('admin_doc/missing_docutils.html')
 
 def load_all_installed_template_libraries():
     # Load/register all template tag libraries from installed apps.
@@ -271,9 +303,6 @@ DATA_TYPE_MAPPING = {
 }
 
 def get_readable_field_data_type(field):
-    # ForeignKey is a special case. Use the field type of the relation.
-    if field.get_internal_type() == 'ForeignKey':
-        field = field.rel.get_related_field()
     return DATA_TYPE_MAPPING[field.get_internal_type()] % field.__dict__
 
 def extract_views_from_urlpatterns(urlpatterns, base=''):
@@ -295,15 +324,23 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
             raise TypeError, &quot;%s does not appear to be a urlpattern object&quot; % p
     return views
 
-# Clean up urlpattern regexes into something somewhat readable by Mere Humans:
-# turns something like &quot;^(?P&lt;sport_slug&gt;\w+)/athletes/(?P&lt;athlete_slug&gt;\w+)/$&quot;
-# into &quot;&lt;sport_slug&gt;/athletes/&lt;athlete_slug&gt;/&quot;
-
 named_group_matcher = re.compile(r'\(\?P(&lt;\w+&gt;).+?\)')
+non_named_group_matcher = re.compile(r'\(.*?\)')
 
 def simplify_regex(pattern):
+    &quot;&quot;&quot;
+    Clean up urlpattern regexes into something somewhat readable by Mere Humans:
+    turns something like &quot;^(?P&lt;sport_slug&gt;\w+)/athletes/(?P&lt;athlete_slug&gt;\w+)/$&quot;
+    into &quot;&lt;sport_slug&gt;/athletes/&lt;athlete_slug&gt;/&quot;
+    &quot;&quot;&quot;
+    # handle named groups first
     pattern = named_group_matcher.sub(lambda m: m.group(1), pattern)
-    pattern = pattern.replace('^', '').replace('$', '').replace('?', '').replace('//', '/')
+
+    # handle non-named groups
+    pattern = non_named_group_matcher.sub(&quot;&lt;var&gt;&quot;, pattern)
+
+    # clean up any outstanding regex-y characters.
+    pattern = pattern.replace('^', '').replace('$', '').replace('?', '').replace('//', '/').replace('\\', '')
     if not pattern.startswith('/'):
         pattern = '/' + pattern
     return pattern</diff>
      <filename>django/contrib/admin/views/doc.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,32 +1,34 @@
-# Generic admin views.
-from django.contrib.admin.views.decorators import staff_member_required
+from django import forms, template
+from django.conf import settings
 from django.contrib.admin.filterspecs import FilterSpec
-from django.core import formfields, meta, template
-from django.core.template import loader
-from django.core.meta.fields import BoundField, BoundFieldLine, BoundFieldSet
-from django.core.exceptions import Http404, ImproperlyConfigured, ObjectDoesNotExist, PermissionDenied
-from django.core.extensions import DjangoContext as Context
-from django.core.extensions import get_object_or_404, render_to_response
+from django.contrib.admin.views.decorators import staff_member_required
+from django.views.decorators.cache import never_cache
+from django.contrib.contenttypes.models import ContentType
+from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist, PermissionDenied
 from django.core.paginator import ObjectPaginator, InvalidPage
-from django.conf.settings import ADMIN_MEDIA_PREFIX
-try:
-    from django.models.admin import log
-except ImportError:
-    raise ImproperlyConfigured, &quot;You don't have 'django.contrib.admin' in INSTALLED_APPS.&quot;
-from django.utils.html import escape
-from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
-from django.utils.text import capfirst, get_text_list
+from django.shortcuts import get_object_or_404, render_to_response
+from django.db import models
+from django.db.models.query import handle_legacy_orderlist, QuerySet
+from django.http import Http404, HttpResponse, HttpResponseRedirect
+from django.template import loader
 from django.utils import dateformat
 from django.utils.dates import MONTHS
 from django.utils.html import escape
+from django.utils.text import capfirst, get_text_list
 import operator
 
-# The system will display a &quot;Show all&quot; link only if the total result count
-# is less than or equal to this setting.
-MAX_SHOW_ALL_ALLOWED = 200
+from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
+if not LogEntry._meta.installed:
+    raise ImproperlyConfigured, &quot;You'll need to put 'django.contrib.admin' in your INSTALLED_APPS setting before you can use the admin application.&quot;
 
-DEFAULT_RESULTS_PER_PAGE = 100
+if 'django.core.context_processors.auth' not in settings.TEMPLATE_CONTEXT_PROCESSORS:
+    raise ImproperlyConfigured, &quot;You'll need to put 'django.core.context_processors.auth' in your TEMPLATE_CONTEXT_PROCESSORS setting before you can use the admin application.&quot;
+
+# The system will display a &quot;Show all&quot; link on the change list only if the
+# total result count is less than or equal to this setting.
+MAX_SHOW_ALL_ALLOWED = 200
 
+# Changelist settings
 ALL_VAR = 'all'
 ORDER_VAR = 'o'
 ORDER_TYPE_VAR = 'ot'
@@ -34,229 +36,59 @@ PAGE_VAR = 'p'
 SEARCH_VAR = 'q'
 IS_POPUP_VAR = 'pop'
 
-# Text to display within changelist table cells if the value is blank.
+# Text to display within change-list table cells if the value is blank.
 EMPTY_CHANGELIST_VALUE = '(None)'
 
-def _get_mod_opts(app_label, module_name):
-    &quot;Helper function that returns a tuple of (module, opts), raising Http404 if necessary.&quot;
-    try:
-        mod = meta.get_module(app_label, module_name)
-    except ImportError:
-        raise Http404 # Invalid app or module name. Maybe it's not in INSTALLED_APPS.
-    opts = mod.Klass._meta
-    if not opts.admin:
-        raise Http404 # This object is valid but has no admin interface.
-    return mod, opts
-
-def index(request):
-    return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=Context(request))
-index = staff_member_required(index)
+use_raw_id_admin = lambda field: isinstance(field.rel, (models.ManyToOneRel, models.ManyToManyRel)) and field.rel.raw_id_admin
 
 class IncorrectLookupParameters(Exception):
     pass
 
-class ChangeList(object):
-    def __init__(self, request, app_label, module_name):
-        self.get_modules_and_options(app_label, module_name, request)
-        self.get_search_parameters(request)
-        self.get_ordering()
-        self.query = request.GET.get(SEARCH_VAR, '')
-        self.get_lookup_params()
-        self.get_results(request)
-        self.title = (self.is_popup
-                      and _('Select %s') % self.opts.verbose_name
-                      or _('Select %s to change') % self.opts.verbose_name)
-        self.get_filters(request)
-        self.pk_attname = self.lookup_opts.pk.attname
-
-    def get_filters(self, request):
-        self.filter_specs = []
-        if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field:
-            filter_fields = [self.lookup_opts.get_field(field_name) \
-                              for field_name in self.lookup_opts.admin.list_filter]
-            for f in filter_fields:
-                spec = FilterSpec.create(f, request, self.params)
-                if spec and spec.has_output():
-                    self.filter_specs.append(spec)
-        self.has_filters = bool(self.filter_specs)
-
-    def get_query_string(self, new_params={}, remove=[]):
-        p = self.params.copy()
-        for r in remove:
-            for k in p.keys():
-                if k.startswith(r):
-                    del p[k]
-        for k, v in new_params.items():
-            if p.has_key(k) and v is None:
-                del p[k]
-            elif v is not None:
-                p[k] = v
-        return '?' + '&amp;amp;'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
-
-    def get_modules_and_options(self, app_label, module_name, request):
-        self.mod, self.opts = _get_mod_opts(app_label, module_name)
-        if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()):
-            raise PermissionDenied
-
-        self.lookup_mod, self.lookup_opts = self.mod, self.opts
-
-    def get_search_parameters(self, request):
-        # Get search parameters from the query string.
-        try:
-            self.page_num = int(request.GET.get(PAGE_VAR, 0))
-        except ValueError:
-            self.page_num = 0
-        self.show_all = request.GET.has_key(ALL_VAR)
-        self.is_popup = request.GET.has_key(IS_POPUP_VAR)
-        self.params = dict(request.GET.items())
-        if self.params.has_key(PAGE_VAR):
-            del self.params[PAGE_VAR]
-
-    def get_results(self, request):
-        lookup_mod, lookup_params, show_all, page_num = \
-            self.lookup_mod, self.lookup_params, self.show_all, self.page_num
-        # Get the results.
-        try:
-            paginator = ObjectPaginator(lookup_mod, lookup_params, DEFAULT_RESULTS_PER_PAGE)
-        # Naked except! Because we don't have any other way of validating &quot;params&quot;.
-        # They might be invalid if the keyword arguments are incorrect, or if the
-        # values are not in the correct type (which would result in a database
-        # error).
-        except:
-            raise IncorrectLookupParameters()
-
-        # Get the total number of objects, with no filters applied.
-        real_lookup_params = lookup_params.copy()
-        del real_lookup_params['order_by']
-        if real_lookup_params:
-            full_result_count = lookup_mod.get_count()
-        else:
-            full_result_count = paginator.hits
-        del real_lookup_params
-        result_count = paginator.hits
-        can_show_all = result_count &lt;= MAX_SHOW_ALL_ALLOWED
-        multi_page = result_count &gt; DEFAULT_RESULTS_PER_PAGE
-
-        # Get the list of objects to display on this page.
-        if (show_all and can_show_all) or not multi_page:
-            result_list = lookup_mod.get_list(**lookup_params)
-        else:
-            try:
-                result_list = paginator.get_page(page_num)
-            except InvalidPage:
-                result_list = []
-        (self.result_count, self.full_result_count, self.result_list,
-            self.can_show_all, self.multi_page, self.paginator) = (result_count,
-                  full_result_count, result_list, can_show_all, multi_page, paginator )
-
-    def url_for_result(self, result):
-        return &quot;%s/&quot; % getattr(result, self.pk_attname)
-
-    def get_ordering(self):
-        lookup_opts, params = self.lookup_opts, self.params
-        # For ordering, first check the &quot;ordering&quot; parameter in the admin options,
-        # then check the object's default ordering. If neither of those exist,
-        # order descending by ID by default. Finally, look for manually-specified
-        # ordering from the query string.
-        ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
-
-        # Normalize it to new-style ordering.
-        ordering = meta.handle_legacy_orderlist(ordering)
-
-        if ordering[0].startswith('-'):
-            order_field, order_type = ordering[0][1:], 'desc'
-        else:
-            order_field, order_type = ordering[0], 'asc'
-        if params.has_key(ORDER_VAR):
+def quote(s):
+    &quot;&quot;&quot;
+    Ensure that primary key values do not confuse the admin URLs by escaping
+    any '/', '_' and ':' characters. Similar to urllib.quote, except that the
+    quoting is slightly different so that it doesn't get autoamtically
+    unquoted by the web browser.
+    &quot;&quot;&quot;
+    if type(s) != type(''):
+        return s
+    res = list(s)
+    for i in range(len(res)):
+        c = res[i]
+        if c in ':/_':
+            res[i] = '_%02X' % ord(c)
+    return ''.join(res)
+
+def unquote(s):
+    &quot;&quot;&quot;
+    Undo the effects of quote(). Based heavily on urllib.unquote().
+    &quot;&quot;&quot;
+    mychr = chr
+    myatoi = int
+    list = s.split('_')
+    res = [list[0]]
+    myappend = res.append
+    del list[0]
+    for item in list:
+        if item[1:2]:
             try:
-                try:
-                    f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
-                except meta.FieldDoesNotExist:
-                    pass
-                else:
-                    if not isinstance(f.rel, meta.ManyToOneRel) or not f.null:
-                        order_field = f.name
-            except (IndexError, ValueError):
-                pass # Invalid ordering specified. Just use the default.
-        if params.has_key(ORDER_TYPE_VAR) and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
-            order_type = params[ORDER_TYPE_VAR]
-        self.order_field, self.order_type = order_field, order_type
-
-    def get_lookup_params(self):
-        # Prepare the lookup parameters for the API lookup.
-        (params, order_field, lookup_opts, order_type, opts, query) = \
-           (self.params, self.order_field, self.lookup_opts, self.order_type, self.opts, self.query)
-
-        lookup_params = params.copy()
-        for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
-            if lookup_params.has_key(i):
-                del lookup_params[i]
-        # If the order-by field is a field with a relationship, order by the value
-        # in the related table.
-        lookup_order_field = order_field
-        try:
-            f = lookup_opts.get_field(order_field)
-        except meta.FieldDoesNotExist:
-            pass
-        else:
-            if isinstance(lookup_opts.get_field(order_field).rel, meta.ManyToOneRel):
-                f = lookup_opts.get_field(order_field)
-                rel_ordering = f.rel.to.ordering and f.rel.to.ordering[0] or f.rel.to.pk.column
-                lookup_order_field = '%s.%s' % (f.rel.to.db_table, rel_ordering)
-        # Use select_related if one of the list_display options is a field with a
-        # relationship.
-        if lookup_opts.admin.list_select_related:
-            lookup_params['select_related'] = True
+                myappend(mychr(myatoi(item[:2], 16))
+                     + item[2:])
+            except ValueError:
+                myappend('_' + item)
         else:
-            for field_name in lookup_opts.admin.list_display:
-                try:
-                    f = lookup_opts.get_field(field_name)
-                except meta.FieldDoesNotExist:
-                    pass
-                else:
-                    if isinstance(f.rel, meta.ManyToOneRel):
-                        lookup_params['select_related'] = True
-                        break
-        lookup_params['order_by'] = ((order_type == 'desc' and '-' or '') + lookup_order_field,)
-        if lookup_opts.admin.search_fields and query:
-            complex_queries = []
-            for bit in query.split():
-                or_queries = []
-                for field_name in lookup_opts.admin.search_fields:
-                    or_queries.append(meta.Q(**{'%s__icontains' % field_name: bit}))
-                complex_queries.append(reduce(operator.or_, or_queries))
-            lookup_params['complex'] = reduce(operator.and_, complex_queries)
-        if opts.one_to_one_field:
-            lookup_params.update(opts.one_to_one_field.rel.limit_choices_to)
-        self.lookup_params = lookup_params
-
-def change_list(request, app_label, module_name):
-    try:
-        cl = ChangeList(request, app_label, module_name)
-    except IncorrectLookupParameters:
-        return HttpResponseRedirect(request.path)
-
-    c = Context(request, {
-        'title': cl.title,
-        'is_popup': cl.is_popup,
-        'cl' : cl
-    })
-    c.update({'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}),
-    return render_to_response(['admin/%s/%s/change_list' % (app_label, cl.opts.object_name.lower()),
-                               'admin/%s/change_list' % app_label,
-                               'admin/change_list'], context_instance=c)
-change_list = staff_member_required(change_list)
+            myappend('_' + item)
+    return &quot;&quot;.join(res)
 
-use_raw_id_admin = lambda field: isinstance(field.rel, (meta.ManyToOneRel, meta.ManyToManyRel)) and field.rel.raw_id_admin
-
-def get_javascript_imports(opts,auto_populated_fields, ordered_objects, field_sets):
+def get_javascript_imports(opts, auto_populated_fields, field_sets):
 # Put in any necessary JavaScript imports.
     js = ['js/core.js', 'js/admin/RelatedObjectLookups.js']
     if auto_populated_fields:
         js.append('js/urlify.js')
-    if opts.has_field_type(meta.DateTimeField) or opts.has_field_type(meta.TimeField) or opts.has_field_type(meta.DateField):
+    if opts.has_field_type(models.DateTimeField) or opts.has_field_type(models.TimeField) or opts.has_field_type(models.DateField):
         js.extend(['js/calendar.js', 'js/admin/DateTimeShortcuts.js'])
-    if ordered_objects:
+    if opts.get_ordered_objects():
         js.extend(['js/getElementsBySelector.js', 'js/dom-drag.js' , 'js/admin/ordering.js'])
     if opts.admin.js:
         js.extend(opts.admin.js)
@@ -264,29 +96,30 @@ def get_javascript_imports(opts,auto_populated_fields, ordered_objects, field_se
     for field_set in field_sets:
         if not seen_collapse and 'collapse' in field_set.classes:
             seen_collapse = True
-            js.append('js/admin/CollapsedFieldsets.js' )
+            js.append('js/admin/CollapsedFieldsets.js')
 
         for field_line in field_set:
             try:
                 for f in field_line:
-                    if f.rel and isinstance(f, meta.ManyToManyField) and f.rel.filter_interface:
+                    if f.rel and isinstance(f, models.ManyToManyField) and f.rel.filter_interface:
                         js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js'])
                         raise StopIteration
             except StopIteration:
                 break
     return js
 
-class AdminBoundField(BoundField):
+class AdminBoundField(object):
     def __init__(self, field, field_mapping, original):
-        super(AdminBoundField, self).__init__(field, field_mapping, original)
-
+        self.field = field
+        self.original = original
+        self.form_fields = [field_mapping[name] for name in self.field.get_manipulator_field_names('')]
         self.element_id = self.form_fields[0].get_id()
-        self.has_label_first = not isinstance(self.field, meta.BooleanField)
+        self.has_label_first = not isinstance(self.field, models.BooleanField)
         self.raw_id_admin = use_raw_id_admin(field)
-        self.is_date_time = isinstance(field, meta.DateTimeField)
-        self.is_file_field = isinstance(field, meta.FileField)
-        self.needs_add_label = field.rel and isinstance(field.rel, meta.ManyToOneRel) or isinstance(field.rel, meta.ManyToManyRel) and field.rel.to.admin
-        self.hidden = isinstance(self.field, meta.AutoField)
+        self.is_date_time = isinstance(field, models.DateTimeField)
+        self.is_file_field = isinstance(field, models.FileField)
+        self.needs_add_label = field.rel and isinstance(field.rel, models.ManyToOneRel) or isinstance(field.rel, models.ManyToManyRel) and field.rel.to._meta.admin
+        self.hidden = isinstance(self.field, models.AutoField)
         self.first = False
 
         classes = []
@@ -298,26 +131,22 @@ class AdminBoundField(BoundField):
             self.cell_class_attribute = ' class=&quot;%s&quot; ' % ' '.join(classes)
         self._repr_filled = False
 
-    def _fetch_existing_display(self, func_name):
-        class_dict = self.original.__class__.__dict__
-        func = class_dict.get(func_name)
-        return func(self.original)
-
-    def _fill_existing_display(self):
-        if getattr(self, '_display_filled', False):
-            return
-        # HACK
-        if isinstance(self.field.rel, meta.ManyToOneRel):
-             func_name = 'get_%s' % self.field.name
-             self._display = self._fetch_existing_display(func_name)
-        elif isinstance(self.field.rel, meta.ManyToManyRel):
-            func_name = 'get_%s_list' % self.field.rel.singular
-            self._display =  &quot;, &quot;.join([str(obj) for obj in self._fetch_existing_display(func_name)])
-        self._display_filled = True
+        if field.rel:
+            self.related_url = '../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
+
+    def original_value(self):
+        if self.original:
+            return self.original.__dict__[self.field.column]
 
     def existing_display(self):
-        self._fill_existing_display()
-        return self._display
+        try:
+            return self._display
+        except AttributeError:
+            if isinstance(self.field.rel, models.ManyToOneRel):
+                self._display = getattr(self.original, 'get_%s' % self.field.name)()
+            elif isinstance(self.field.rel, models.ManyToManyRel):
+                self._display = &quot;, &quot;.join([str(obj) for obj in getattr(self.original, 'get_%s_list' % self.field.rel.singular)()])
+            return self._display
 
     def __repr__(self):
         return repr(self.__dict__)
@@ -325,94 +154,114 @@ class AdminBoundField(BoundField):
     def html_error_list(self):
         return &quot; &quot;.join([form_field.html_error_list() for form_field in self.form_fields if form_field.errors])
 
-class AdminBoundFieldLine(BoundFieldLine):
+    def original_url(self):
+        if self.is_file_field and self.original and self.field.attname:
+            url_method = getattr(self.original, 'get_%s_url' % self.field.attname)
+            if callable(url_method):
+                return url_method()
+        return ''
+
+class AdminBoundFieldLine(object):
     def __init__(self, field_line, field_mapping, original):
-        super(AdminBoundFieldLine, self).__init__(field_line, field_mapping, original, AdminBoundField)
+        self.bound_fields = [field.bind(field_mapping, original, AdminBoundField) for field in field_line]
         for bound_field in self:
             bound_field.first = True
             break
 
-class AdminBoundFieldSet(BoundFieldSet):
+    def __iter__(self):
+        for bound_field in self.bound_fields:
+            yield bound_field
+
+    def __len__(self):
+        return len(self.bound_fields)
+
+class AdminBoundFieldSet(object):
     def __init__(self, field_set, field_mapping, original):
-        super(AdminBoundFieldSet, self).__init__(field_set, field_mapping, original, AdminBoundFieldLine)
-
-class BoundManipulator(object):
-    def __init__(self, opts, manipulator, field_mapping):
-        self.inline_related_objects = opts.get_followed_related_objects(manipulator.follow)
-        self.original = hasattr(manipulator, 'original_object') and manipulator.original_object or None
-        self.bound_field_sets = [field_set.bind(field_mapping, self.original, AdminBoundFieldSet)
-                                 for field_set in opts.admin.get_field_sets(opts)]
-        self.ordered_objects = opts.get_ordered_objects()[:]
-
-class AdminBoundManipulator(BoundManipulator):
-    def __init__(self, opts, manipulator, field_mapping):
-        super(AdminBoundManipulator, self).__init__(opts, manipulator, field_mapping)
-        field_sets = opts.admin.get_field_sets(opts)
-
-        self.auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
-        self.javascript_imports = get_javascript_imports(opts, self.auto_populated_fields, self.ordered_objects, field_sets);
-
-        self.coltype = self.ordered_objects and 'colMS' or 'colM'
-        self.has_absolute_url = hasattr(opts.get_model_module().Klass, 'get_absolute_url')
-        self.form_enc_attrib = opts.has_field_type(meta.FileField) and \
-                                'enctype=&quot;multipart/form-data&quot; ' or ''
-
-        self.first_form_field_id = self.bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0].get_id();
-        self.ordered_object_pk_names = [o.pk.name for o in self.ordered_objects]
-
-        self.save_on_top = opts.admin.save_on_top
-        self.save_as = opts.admin.save_as
-
-        self.content_type_id = opts.get_content_type_id()
-        self.verbose_name_plural = opts.verbose_name_plural
-        self.verbose_name = opts.verbose_name
-        self.object_name = opts.object_name
-
-    def get_ordered_object_pk(self, ordered_obj):
-        for name in self.ordered_object_pk_names:
-            if hasattr(ordered_obj, name):
-                return str(getattr(ordered_obj, name))
-        return &quot;&quot;
-
-def render_change_form(opts, manipulator, app_label, context, add=False, change=False, show_delete=False, form_url=''):
+        self.name = field_set.name
+        self.classes = field_set.classes
+        self.description = field_set.description
+        self.bound_field_lines = [field_line.bind(field_mapping, original, AdminBoundFieldLine) for field_line in field_set]
+
+    def __iter__(self):
+        for bound_field_line in self.bound_field_lines:
+            yield bound_field_line
+
+    def __len__(self):
+        return len(self.bound_field_lines)
+
+def render_change_form(model, manipulator, context, add=False, change=False, form_url=''):
+    opts = model._meta
+    app_label = opts.app_label
+    auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
+    field_sets = opts.admin.get_field_sets(opts)
+    original = getattr(manipulator, 'original_object', None)
+    bound_field_sets = [field_set.bind(context['form'], original, AdminBoundFieldSet) for field_set in field_sets]
+    first_form_field_id = bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0].get_id();
+    ordered_objects = opts.get_ordered_objects()
+    inline_related_objects = opts.get_followed_related_objects(manipulator.follow)
     extra_context = {
         'add': add,
         'change': change,
-        'bound_manipulator': AdminBoundManipulator(opts, manipulator, context['form']),
         'has_delete_permission': context['perms'][app_label][opts.get_delete_permission()],
+        'has_change_permission': context['perms'][app_label][opts.get_change_permission()],
+        'has_file_field': opts.has_field_type(models.FileField),
+        'has_absolute_url': hasattr(model, 'get_absolute_url'),
+        'auto_populated_fields': auto_populated_fields,
+        'bound_field_sets': bound_field_sets,
+        'first_form_field_id': first_form_field_id,
+        'javascript_imports': get_javascript_imports(opts, auto_populated_fields, field_sets),
+        'ordered_objects': ordered_objects,
+        'inline_related_objects': inline_related_objects,
         'form_url': form_url,
-        'app_label': app_label,
+        'opts': opts,
+        'content_type_id': ContentType.objects.get_for_model(model).id,
     }
     context.update(extra_context)
-    return render_to_response([&quot;admin/%s/%s/change_form&quot; % (app_label, opts.object_name.lower() ),
-                               &quot;admin/%s/change_form&quot; % app_label ,
-                               &quot;admin/change_form&quot;], context_instance=context)
+    return render_to_response([
+        &quot;admin/%s/%s/change_form.html&quot; % (app_label, opts.object_name.lower()),
+        &quot;admin/%s/change_form.html&quot; % app_label,
+        &quot;admin/change_form.html&quot;], context_instance=context)
 
-def log_add_message(user, opts,manipulator,new_object):
-    pk_value = getattr(new_object, opts.pk.attname)
-    log.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), log.ADDITION)
+def index(request):
+    return render_to_response('admin/index.html', {'title': _('Site administration')}, context_instance=template.RequestContext(request))
+index = staff_member_required(never_cache(index))
+
+def add_stage(request, app_label, model_name, show_delete=False, form_url='', post_url=None, post_url_continue='../%s/', object_id_override=None):
+    model = models.get_model(app_label, model_name)
+    if model is None:
+        raise Http404, &quot;App %r, model %r, not found&quot; % (app_label, model_name)
+    opts = model._meta
 
-def add_stage(request, app_label, module_name, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/', object_id_override=None):
-    mod, opts = _get_mod_opts(app_label, module_name)
     if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
         raise PermissionDenied
-    manipulator = mod.AddManipulator()
+
+    if post_url is None:
+        if request.user.has_perm(app_label + '.' + opts.get_change_permission()):
+            # redirect to list view
+            post_url = '../'
+        else:
+            # Object list will give 'Permission Denied', so go back to admin home
+            post_url = '../../../'
+
+    manipulator = model.AddManipulator()
     if request.POST:
         new_data = request.POST.copy()
-        if opts.has_field_type(meta.FileField):
+
+        if opts.has_field_type(models.FileField):
             new_data.update(request.FILES)
+
         errors = manipulator.get_validation_errors(new_data)
         manipulator.do_html2python(new_data)
 
-        if not errors and not request.POST.has_key(&quot;_preview&quot;):
+        if not errors:
             new_object = manipulator.save(new_data)
-            log_add_message(request.user, opts,manipulator,new_object)
-            msg = _('The %(name)s &quot;%(obj)s&quot; was added successfully.') % {'name':opts.verbose_name, 'obj':new_object}
-            pk_value = getattr(new_object,opts.pk.attname)
+            pk_value = new_object._get_pk_val()
+            LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), ADDITION)
+            msg = _('The %(name)s &quot;%(obj)s&quot; was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
             # Here, we distinguish between different save types by checking for
             # the presence of keys in request.POST.
             if request.POST.has_key(&quot;_continue&quot;):
-                request.user.add_message(msg + ' ' + _(&quot;You may edit it again below.&quot;))
+                request.user.message_set.create(message=msg + ' ' + _(&quot;You may edit it again below.&quot;))
                 if request.POST.has_key(&quot;_popup&quot;):
                     post_url_continue += &quot;?_popup=1&quot;
                 return HttpResponseRedirect(post_url_continue % pk_value)
@@ -420,10 +269,10 @@ def add_stage(request, app_label, module_name, show_delete=False, form_url='', p
                 return HttpResponse('&lt;script type=&quot;text/javascript&quot;&gt;opener.dismissAddAnotherPopup(window, %s, &quot;%s&quot;);&lt;/script&gt;' % \
                     (pk_value, str(new_object).replace('&quot;', '\\&quot;')))
             elif request.POST.has_key(&quot;_addanother&quot;):
-                request.user.add_message(msg + ' ' + (_(&quot;You may add another %s below.&quot;) % opts.verbose_name))
+                request.user.message_set.create(message=msg + ' ' + (_(&quot;You may add another %s below.&quot;) % opts.verbose_name))
                 return HttpResponseRedirect(request.path)
             else:
-                request.user.add_message(msg)
+                request.user.message_set.create(message=msg)
                 return HttpResponseRedirect(post_url)
     else:
         # Add default data.
@@ -435,73 +284,80 @@ def add_stage(request, app_label, module_name, show_delete=False, form_url='', p
         errors = {}
 
     # Populate the FormWrapper.
-    form = formfields.FormWrapper(manipulator, new_data, errors, edit_inline=True)
+    form = forms.FormWrapper(manipulator, new_data, errors)
 
-    c = Context(request, {
+    c = template.RequestContext(request, {
         'title': _('Add %s') % opts.verbose_name,
         'form': form,
         'is_popup': request.REQUEST.has_key('_popup'),
         'show_delete': show_delete,
     })
+
     if object_id_override is not None:
         c['object_id'] = object_id_override
 
-    return render_change_form(opts, manipulator, app_label, c, add=True)
-add_stage = staff_member_required(add_stage)
-
-def log_change_message(user, opts,manipulator,new_object):
-    pk_value = getattr(new_object, opts.pk.column)
-    # Construct the change message.
-    change_message = []
-    if manipulator.fields_added:
-        change_message.append(_('Added %s.') % get_text_list(manipulator.fields_added, _('and')))
-    if manipulator.fields_changed:
-        change_message.append(_('Changed %s.') % get_text_list(manipulator.fields_changed, _('and')))
-    if manipulator.fields_deleted:
-        change_message.append(_('Deleted %s.') % get_text_list(manipulator.fields_deleted, _('and')))
-    change_message = ' '.join(change_message)
-    if not change_message:
-        change_message = _('No fields changed.')
-    log.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), log.CHANGE, change_message)
-
-def change_stage(request, app_label, module_name, object_id):
-    mod, opts = _get_mod_opts(app_label, module_name)
+    return render_change_form(model, manipulator, c, add=True)
+add_stage = staff_member_required(never_cache(add_stage))
+
+def change_stage(request, app_label, model_name, object_id):
+    model = models.get_model(app_label, model_name)
+    object_id = unquote(object_id)
+    if model is None:
+        raise Http404, &quot;App %r, model %r, not found&quot; % (app_label, model_name)
+    opts = model._meta
+
     if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
         raise PermissionDenied
+
     if request.POST and request.POST.has_key(&quot;_saveasnew&quot;):
-        return add_stage(request, app_label, module_name, form_url='../add/')
+        return add_stage(request, app_label, model_name, form_url='../../add/')
+
     try:
-        manipulator = mod.ChangeManipulator(object_id)
+        manipulator = model.ChangeManipulator(object_id)
     except ObjectDoesNotExist:
         raise Http404
 
     if request.POST:
         new_data = request.POST.copy()
-        if opts.has_field_type(meta.FileField):
+
+        if opts.has_field_type(models.FileField):
             new_data.update(request.FILES)
 
         errors = manipulator.get_validation_errors(new_data)
-
         manipulator.do_html2python(new_data)
-        if not errors and not request.POST.has_key(&quot;_preview&quot;):
+
+        if not errors:
             new_object = manipulator.save(new_data)
-            log_change_message(request.user,opts,manipulator,new_object)
-            msg = _('The %(name)s &quot;%(obj)s&quot; was changed successfully.') % {'name': opts.verbose_name, 'obj':new_object}
-            pk_value = getattr(new_object,opts.pk.attname)
+            pk_value = new_object._get_pk_val()
+
+            # Construct the change message.
+            change_message = []
+            if manipulator.fields_added:
+                change_message.append(_('Added %s.') % get_text_list(manipulator.fields_added, _('and')))
+            if manipulator.fields_changed:
+                change_message.append(_('Changed %s.') % get_text_list(manipulator.fields_changed, _('and')))
+            if manipulator.fields_deleted:
+                change_message.append(_('Deleted %s.') % get_text_list(manipulator.fields_deleted, _('and')))
+            change_message = ' '.join(change_message)
+            if not change_message:
+                change_message = _('No fields changed.')
+            LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message)
+
+            msg = _('The %(name)s &quot;%(obj)s&quot; was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
             if request.POST.has_key(&quot;_continue&quot;):
-                request.user.add_message(msg + ' ' + _(&quot;You may edit it again below.&quot;))
+                request.user.message_set.create(message=msg + ' ' + _(&quot;You may edit it again below.&quot;))
                 if request.REQUEST.has_key('_popup'):
                     return HttpResponseRedirect(request.path + &quot;?_popup=1&quot;)
                 else:
                     return HttpResponseRedirect(request.path)
             elif request.POST.has_key(&quot;_saveasnew&quot;):
-                request.user.add_message(_('The %(name)s &quot;%(obj)s&quot; was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object})
+                request.user.message_set.create(message=_('The %(name)s &quot;%(obj)s&quot; was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object})
                 return HttpResponseRedirect(&quot;../%s/&quot; % pk_value)
             elif request.POST.has_key(&quot;_addanother&quot;):
-                request.user.add_message(msg + ' ' + (_(&quot;You may add another %s below.&quot;) % opts.verbose_name))
+                request.user.message_set.create(message=msg + ' ' + (_(&quot;You may add another %s below.&quot;) % opts.verbose_name))
                 return HttpResponseRedirect(&quot;../add/&quot;)
             else:
-                request.user.add_message(msg)
+                request.user.message_set.create(message=msg)
                 return HttpResponseRedirect(&quot;../&quot;)
     else:
         # Populate new_data with a &quot;flattened&quot; version of the current data.
@@ -519,7 +375,7 @@ def change_stage(request, app_label, module_name, object_id):
         errors = {}
 
     # Populate the FormWrapper.
-    form = formfields.FormWrapper(manipulator, new_data, errors, edit_inline = True)
+    form = forms.FormWrapper(manipulator, new_data, errors)
     form.original = manipulator.original_object
     form.order_objects = []
 
@@ -528,20 +384,19 @@ def change_stage(request, app_label, module_name, object_id):
         wrt = related.opts.order_with_respect_to
         if wrt and wrt.rel and wrt.rel.to == opts:
             func = getattr(manipulator.original_object, 'get_%s_list' %
-                    related.get_method_name_part())
+                    related.get_accessor_name())
             orig_list = func()
             form.order_objects.extend(orig_list)
 
-    c = Context(request, {
+    c = template.RequestContext(request, {
         'title': _('Change %s') % opts.verbose_name,
         'form': form,
         'object_id': object_id,
         'original': manipulator.original_object,
-        'is_popup' : request.REQUEST.has_key('_popup')
+        'is_popup': request.REQUEST.has_key('_popup'),
     })
-
-    return render_change_form(opts,manipulator, app_label, c, change=True)
-change_stage = staff_member_required(change_stage)
+    return render_change_form(model, manipulator, c, change=True)
+change_stage = staff_member_required(never_cache(change_stage))
 
 def _nest_help(obj, depth, val):
     current = obj
@@ -559,10 +414,10 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
         if related.opts in opts_seen:
             continue
         opts_seen.append(related.opts)
-        rel_opts_name = related.get_method_name_part()
-        if isinstance(related.field.rel, meta.OneToOneRel):
+        rel_opts_name = related.get_accessor_name()
+        if isinstance(related.field.rel, models.OneToOneRel):
             try:
-                sub_obj = getattr(obj, 'get_%s' % rel_opts_name)()
+                sub_obj = getattr(obj, rel_opts_name)
             except ObjectDoesNotExist:
                 pass
             else:
@@ -579,12 +434,12 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
                 else:
                     # Display a link to the admin page.
                     nh(deleted_objects, current_depth, ['%s: &lt;a href=&quot;../../../../%s/%s/%s/&quot;&gt;%s&lt;/a&gt;' % \
-                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.module_name,
-                        getattr(sub_obj, related.opts.pk.attname), sub_obj), []])
+                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(),
+                        sub_obj._get_pk_val(), sub_obj), []])
                 _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
         else:
             has_related_objs = False
-            for sub_obj in getattr(obj, 'get_%s_list' % rel_opts_name)():
+            for sub_obj in getattr(obj, rel_opts_name).all():
                 has_related_objs = True
                 if related.field.rel.edit_inline or not related.opts.admin:
                     # Don't display link to edit, because it either has no
@@ -593,7 +448,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
                 else:
                     # Display a link to the admin page.
                     nh(deleted_objects, current_depth, ['%s: &lt;a href=&quot;../../../../%s/%s/%s/&quot;&gt;%s&lt;/a&gt;' % \
-                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.module_name, getattr(sub_obj, related.opts.pk.attname), escape(str(sub_obj))), []])
+                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(str(sub_obj))), []])
                 _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
             # If there were related objects, and the user doesn't have
             # permission to delete them, add the missing perm to perms_needed.
@@ -605,21 +460,21 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
         if related.opts in opts_seen:
             continue
         opts_seen.append(related.opts)
-        rel_opts_name = related.get_method_name_part()
+        rel_opts_name = related.get_accessor_name()
         has_related_objs = False
-        for sub_obj in getattr(obj, 'get_%s_list' % rel_opts_name)():
+        for sub_obj in getattr(obj, rel_opts_name).all():
             has_related_objs = True
             if related.field.rel.edit_inline or not related.opts.admin:
                 # Don't display link to edit, because it either has no
                 # admin or is edited inline.
                 nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
-                    {'fieldname': related.field.name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
+                    {'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
             else:
                 # Display a link to the admin page.
                 nh(deleted_objects, current_depth, [
-                    (_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.name, 'name':related.opts.verbose_name}) + \
+                    (_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.verbose_name, 'name':related.opts.verbose_name}) + \
                     (' &lt;a href=&quot;../../../../%s/%s/%s/&quot;&gt;%s&lt;/a&gt;' % \
-                        (related.opts.app_label, related.opts.module_name, getattr(sub_obj, related.opts.pk.attname), escape(str(sub_obj)))), []])
+                        (related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(str(sub_obj)))), []])
         # If there were related objects, and the user doesn't have
         # permission to change them, add the missing perm to perms_needed.
         if related.opts.admin and has_related_objs:
@@ -627,12 +482,16 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
             if not user.has_perm(p):
                 perms_needed.add(related.opts.verbose_name)
 
-def delete_stage(request, app_label, module_name, object_id):
+def delete_stage(request, app_label, model_name, object_id):
     import sets
-    mod, opts = _get_mod_opts(app_label, module_name)
+    model = models.get_model(app_label, model_name)
+    object_id = unquote(object_id)
+    if model is None:
+        raise Http404, &quot;App %r, model %r, not found&quot; % (app_label, model_name)
+    opts = model._meta
     if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
         raise PermissionDenied
-    obj = get_object_or_404(mod, pk=object_id)
+    obj = get_object_or_404(model, pk=object_id)
 
     # Populate deleted_objects, a data structure of all related objects that
     # will also be deleted.
@@ -645,28 +504,240 @@ def delete_stage(request, app_label, module_name, object_id):
             raise PermissionDenied
         obj_display = str(obj)
         obj.delete()
-        log.log_action(request.user.id, opts.get_content_type_id(), object_id, obj_display, log.DELETION)
-        request.user.add_message(_('The %(name)s &quot;%(obj)s&quot; was deleted successfully.') % {'name':opts.verbose_name, 'obj':obj_display})
+        LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, object_id, obj_display, DELETION)
+        request.user.message_set.create(message=_('The %(name)s &quot;%(obj)s&quot; was deleted successfully.') % {'name': opts.verbose_name, 'obj': obj_display})
         return HttpResponseRedirect(&quot;../../&quot;)
-    return render_to_response('admin/delete_confirmation', {
+    extra_context = {
         &quot;title&quot;: _(&quot;Are you sure?&quot;),
         &quot;object_name&quot;: opts.verbose_name,
         &quot;object&quot;: obj,
         &quot;deleted_objects&quot;: deleted_objects,
         &quot;perms_lacking&quot;: perms_needed,
-    }, context_instance=Context(request))
-delete_stage = staff_member_required(delete_stage)
-
-def history(request, app_label, module_name, object_id):
-    mod, opts = _get_mod_opts(app_label, module_name)
-    action_list = log.get_list(object_id__exact=object_id, content_type__id__exact=opts.get_content_type_id(),
-        order_by=(&quot;action_time&quot;,), select_related=True)
+        &quot;opts&quot;: model._meta,
+    }
+    return render_to_response([&quot;admin/%s/%s/delete_confirmation.html&quot; % (app_label, opts.object_name.lower() ),
+                               &quot;admin/%s/delete_confirmation.html&quot; % app_label ,
+                               &quot;admin/delete_confirmation.html&quot;], extra_context, context_instance=template.RequestContext(request))
+delete_stage = staff_member_required(never_cache(delete_stage))
+
+def history(request, app_label, model_name, object_id):
+    model = models.get_model(app_label, model_name)
+    object_id = unquote(object_id)
+    if model is None:
+        raise Http404, &quot;App %r, model %r, not found&quot; % (app_label, model_name)
+    action_list = LogEntry.objects.filter(object_id=object_id,
+        content_type__id__exact=ContentType.objects.get_for_model(model).id).select_related().order_by('action_time')
     # If no history was found, see whether this object even exists.
-    obj = get_object_or_404(mod, pk=object_id)
-    return render_to_response('admin/object_history', {
+    obj = get_object_or_404(model, pk=object_id)
+    extra_context = {
         'title': _('Change history: %s') % obj,
         'action_list': action_list,
-        'module_name': capfirst(opts.verbose_name_plural),
+        'module_name': capfirst(model._meta.verbose_name_plural),
         'object': obj,
-    }, context_instance=Context(request))
-history = staff_member_required(history)
+    }
+    return render_to_response([&quot;admin/%s/%s/object_history.html&quot; % (app_label, model._meta.object_name.lower()),
+                               &quot;admin/%s/object_history.html&quot; % app_label ,
+                               &quot;admin/object_history.html&quot;], extra_context, context_instance=template.RequestContext(request))
+history = staff_member_required(never_cache(history))
+
+class ChangeList(object):
+    def __init__(self, request, model):
+        self.model = model
+        self.opts = model._meta
+        self.lookup_opts = self.opts
+        self.manager = self.opts.admin.manager
+
+        # Get search parameters from the query string.
+        try:
+            self.page_num = int(request.GET.get(PAGE_VAR, 0))
+        except ValueError:
+            self.page_num = 0
+        self.show_all = request.GET.has_key(ALL_VAR)
+        self.is_popup = request.GET.has_key(IS_POPUP_VAR)
+        self.params = dict(request.GET.items())
+        if self.params.has_key(PAGE_VAR):
+            del self.params[PAGE_VAR]
+
+        self.order_field, self.order_type = self.get_ordering()
+        self.query = request.GET.get(SEARCH_VAR, '')
+        self.query_set = self.get_query_set()
+        self.get_results(request)
+        self.title = (self.is_popup and _('Select %s') % self.opts.verbose_name or _('Select %s to change') % self.opts.verbose_name)
+        self.filter_specs, self.has_filters = self.get_filters(request)
+        self.pk_attname = self.lookup_opts.pk.attname
+
+    def get_filters(self, request):
+        filter_specs = []
+        if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field:
+            filter_fields = [self.lookup_opts.get_field(field_name) \
+                              for field_name in self.lookup_opts.admin.list_filter]
+            for f in filter_fields:
+                spec = FilterSpec.create(f, request, self.params)
+                if spec and spec.has_output():
+                    filter_specs.append(spec)
+        return filter_specs, bool(filter_specs)
+
+    def get_query_string(self, new_params={}, remove=[]):
+        p = self.params.copy()
+        for r in remove:
+            for k in p.keys():
+                if k.startswith(r):
+                    del p[k]
+        for k, v in new_params.items():
+            if p.has_key(k) and v is None:
+                del p[k]
+            elif v is not None:
+                p[k] = v
+        return '?' + '&amp;amp;'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
+
+    def get_results(self, request):
+        paginator = ObjectPaginator(self.query_set, self.lookup_opts.admin.list_per_page)
+
+        # Get the number of objects, with admin filters applied.
+        try:
+            result_count = paginator.hits
+        # Naked except! Because we don't have any other way of validating
+        # &quot;params&quot;. They might be invalid if the keyword arguments are
+        # incorrect, or if the values are not in the correct type (which would
+        # result in a database error).
+        except:
+            raise IncorrectLookupParameters
+
+        # Get the total number of objects, with no admin filters applied.
+        # Perform a slight optimization: Check to see whether any filters were
+        # given. If not, use paginator.hits to calculate the number of objects,
+        # because we've already done paginator.hits and the value is cached.
+        if isinstance(self.query_set._filters, models.Q) and not self.query_set._filters.kwargs:
+            full_result_count = result_count
+        else:
+            full_result_count = self.manager.count()
+
+        can_show_all = result_count &lt;= MAX_SHOW_ALL_ALLOWED
+        multi_page = result_count &gt; self.lookup_opts.admin.list_per_page
+
+        # Get the list of objects to display on this page.
+        if (self.show_all and can_show_all) or not multi_page:
+            result_list = list(self.query_set)
+        else:
+            try:
+                result_list = paginator.get_page(self.page_num)
+            except InvalidPage:
+                result_list = ()
+
+        self.result_count = result_count
+        self.full_result_count = full_result_count
+        self.result_list = result_list
+        self.can_show_all = can_show_all
+        self.multi_page = multi_page
+        self.paginator = paginator
+
+    def get_ordering(self):
+        lookup_opts, params = self.lookup_opts, self.params
+        # For ordering, first check the &quot;ordering&quot; parameter in the admin options,
+        # then check the object's default ordering. If neither of those exist,
+        # order descending by ID by default. Finally, look for manually-specified
+        # ordering from the query string.
+        ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
+
+        # Normalize it to new-style ordering.
+        ordering = handle_legacy_orderlist(ordering)
+
+        if ordering[0].startswith('-'):
+            order_field, order_type = ordering[0][1:], 'desc'
+        else:
+            order_field, order_type = ordering[0], 'asc'
+        if params.has_key(ORDER_VAR):
+            try:
+                try:
+                    f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
+                except models.FieldDoesNotExist:
+                    pass
+                else:
+                    if not isinstance(f.rel, models.ManyToOneRel) or not f.null:
+                        order_field = f.name
+            except (IndexError, ValueError):
+                pass # Invalid ordering specified. Just use the default.
+        if params.has_key(ORDER_TYPE_VAR) and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
+            order_type = params[ORDER_TYPE_VAR]
+        return order_field, order_type
+
+    def get_query_set(self):
+        qs = self.manager.get_query_set()
+        lookup_params = self.params.copy() # a dictionary of the query string
+        for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
+            if lookup_params.has_key(i):
+                del lookup_params[i]
+
+        # Apply lookup parameters from the query string.
+        qs = qs.filter(**lookup_params)
+
+        # Use select_related() if one of the list_display options is a field
+        # with a relationship.
+        if self.lookup_opts.admin.list_select_related:
+            qs = qs.select_related()
+        else:
+            for field_name in self.lookup_opts.admin.list_display:
+                try:
+                    f = self.lookup_opts.get_field(field_name)
+                except models.FieldDoesNotExist:
+                    pass
+                else:
+                    if isinstance(f.rel, models.ManyToOneRel):
+                        qs = qs.select_related()
+                        break
+
+        # Calculate lookup_order_field.
+        # If the order-by field is a field with a relationship, order by the
+        # value in the related table.
+        lookup_order_field = self.order_field
+        try:
+            f = self.lookup_opts.get_field(self.order_field, many_to_many=False)
+        except models.FieldDoesNotExist:
+            pass
+        else:
+            if isinstance(f.rel, models.OneToOneRel):
+                # For OneToOneFields, don't try to order by the related object's ordering criteria.
+                pass
+            elif isinstance(f.rel, models.ManyToOneRel):
+                rel_ordering = f.rel.to._meta.ordering and f.rel.to._meta.ordering[0] or f.rel.to._meta.pk.column
+                lookup_order_field = '%s.%s' % (f.rel.to._meta.db_table, rel_ordering)
+
+        # Set ordering.
+        qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
+
+        # Apply keyword searches.
+        if self.lookup_opts.admin.search_fields and self.query:
+            for bit in self.query.split():
+                or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields]
+                other_qs = QuerySet(self.model)
+                other_qs = other_qs.filter(reduce(operator.or_, or_queries))
+                qs = qs &amp; other_qs
+
+        if self.opts.one_to_one_field:
+            qs = qs.filter(**self.opts.one_to_one_field.rel.limit_choices_to)
+
+        return qs
+
+    def url_for_result(self, result):
+        return &quot;%s/&quot; % quote(getattr(result, self.pk_attname))
+
+def change_list(request, app_label, model_name):
+    model = models.get_model(app_label, model_name)
+    if model is None:
+        raise Http404, &quot;App %r, model %r, not found&quot; % (app_label, model_name)
+    if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()):
+        raise PermissionDenied
+    try:
+        cl = ChangeList(request, model)
+    except IncorrectLookupParameters:
+        return HttpResponseRedirect(request.path)
+    c = template.RequestContext(request, {
+        'title': cl.title,
+        'is_popup': cl.is_popup,
+        'cl': cl,
+    })
+    c.update({'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}),
+    return render_to_response(['admin/%s/%s/change_list.html' % (app_label, cl.opts.object_name.lower()),
+                               'admin/%s/change_list.html' % app_label,
+                               'admin/change_list.html'], context_instance=c)
+change_list = staff_member_required(never_cache(change_list))</diff>
      <filename>django/contrib/admin/views/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,9 @@
 from django.contrib.admin.views.decorators import staff_member_required
-from django.core import formfields, validators
-from django.core import template
-from django.core.template import loader
-from django.core.extensions import DjangoContext, render_to_response
-from django.models.core import sites
+from django.core import validators
+from django import template, forms
+from django.template import loader
+from django.shortcuts import render_to_response
+from django.contrib.sites.models import Site
 from django.conf import settings
 
 def template_validator(request):
@@ -23,19 +23,19 @@ def template_validator(request):
         errors = manipulator.get_validation_errors(new_data)
         if not errors:
             request.user.add_message('The template is valid.')
-    return render_to_response('admin/template_validator', {
+    return render_to_response('admin/template_validator.html', {
         'title': 'Template validator',
-        'form': formfields.FormWrapper(manipulator, new_data, errors),
-    }, context_instance=DjangoContext(request))
+        'form': forms.FormWrapper(manipulator, new_data, errors),
+    }, context_instance=template.RequestContext(request))
 template_validator = staff_member_required(template_validator)
 
-class TemplateValidator(formfields.Manipulator):
+class TemplateValidator(forms.Manipulator):
     def __init__(self, settings_modules):
         self.settings_modules = settings_modules
-        site_list = sites.get_in_bulk(settings_modules.keys()).values()
+        site_list = Site.objects.get_in_bulk(settings_modules.keys()).values()
         self.fields = (
-            formfields.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
-            formfields.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
+            forms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
+            forms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
         )
 
     def isValidTemplate(self, field_data, all_data):</diff>
      <filename>django/contrib/admin/views/template.py</filename>
    </modified>
    <modified>
      <diff>@@ -0,0 +1,2 @@
+LOGIN_URL = '/accounts/login/'
+REDIRECT_FIELD_NAME = 'next'</diff>
      <filename>django/contrib/auth/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ def authenhandler(req, **kwargs):
     # that so that the following import works
     os.environ.update(req.subprocess_env)
 
-    from django.models.auth import users
+    from django.contrib.auth.models import User
 
     # check for PythonOptions
     _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
@@ -21,14 +21,14 @@ def authenhandler(req, **kwargs):
     superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', &quot;off&quot;))
 
     # check that the username is valid
-    kwargs = {'username__exact': req.user, 'is_active__exact': True}
+    kwargs = {'username': req.user, 'is_active': True}
     if staff_only:
-        kwargs['is_staff__exact'] = True
+        kwargs['is_staff'] = True
     if superuser_only:
-        kwargs['is_superuser__exact'] = True
+        kwargs['is_superuser'] = True
     try:
-        user = users.get_object(**kwargs)
-    except users.UserDoesNotExist:
+        user = User.objects.get(**kwargs)
+    except User.DoesNotExist:
         return apache.HTTP_UNAUTHORIZED
 
     # check the password and any permission given</diff>
      <filename>django/contrib/auth/handlers/modpython.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,48 +1,48 @@
 from django.conf import settings
+from django.contrib.comments.models import Comment, FreeComment
 from django.contrib.syndication.feeds import Feed
 from django.core.exceptions import ObjectDoesNotExist
-from django.models.core import sites
-from django.models.comments import comments, freecomments
+from django.contrib.sites.models import Site
 
 class LatestFreeCommentsFeed(Feed):
     &quot;&quot;&quot;Feed of latest comments on the current site&quot;&quot;&quot;
-    
-    comments_module = freecomments
-    
+
+    comments_class = FreeComment
+
     def title(self):
         if not hasattr(self, '_site'):
-            self._site = sites.get_current()
+            self._site = Site.objects.get_current()
         return &quot;%s comments&quot; % self._site.name
-        
+
     def link(self):
         if not hasattr(self, '_site'):
-            self._site = sites.get_current()
+            self._site = Site.objects.get_current()
         return &quot;http://%s/&quot; % (self._site.domain)
-    
+
     def description(self):
         if not hasattr(self, '_site'):
-            self._site = sites.get_current()
+            self._site = Site.objects.get_current()
         return &quot;Latest comments on %s&quot; % self._site.name
 
     def items(self):
-        return self.comments_module.get_list(**self._get_lookup_kwargs())
+        return self.comments_class.objects.filter(**self._get_lookup_kwargs())
 
     def _get_lookup_kwargs(self):
         return {
-            'site__pk' : settings.SITE_ID,
-            'is_public__exact' : True,
-            'limit' : 40,
+            'site__pk': settings.SITE_ID,
+            'is_public__exact': True,
+            'limit': 40,
         }
 
 class LatestCommentsFeed(LatestFreeCommentsFeed):
     &quot;&quot;&quot;Feed of latest free comments on the current site&quot;&quot;&quot;
-    
-    comments_module = comments
-    
+
+    comments_class = Comment
+
     def _get_lookup_kwargs(self):
         kwargs = LatestFreeCommentsFeed._get_lookup_kwargs(self)
         kwargs['is_removed__exact'] = False
         if settings.COMMENTS_BANNED_USERS_GROUP:
             kwargs['where'] = ['user_id NOT IN (SELECT user_id FROM auth_users_group WHERE group_id = %s)']
             kwargs['params'] = [COMMENTS_BANNED_USERS_GROUP]
-        return kwargs
\ No newline at end of file
+        return kwargs</diff>
      <filename>django/contrib/comments/feeds.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,16 +1,16 @@
-&quot;Custom template tags for user comments&quot;
-
-from django.core import template
-from django.core.template import loader
+from django.contrib.comments.models import Comment, FreeComment
+from django.contrib.comments.models import PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
+from django.contrib.comments.models import MIN_PHOTO_DIMENSION, MAX_PHOTO_DIMENSION
+from django import template
+from django.template import loader
 from django.core.exceptions import ObjectDoesNotExist
-from django.models.comments import comments, freecomments
-from django.models.core import contenttypes
+from django.contrib.contenttypes.models import ContentType
 import re
 
 register = template.Library()
 
-COMMENT_FORM = 'comments/form'
-FREE_COMMENT_FORM = 'comments/freeform'
+COMMENT_FORM = 'comments/form.html'
+FREE_COMMENT_FORM = 'comments/freeform.html'
 
 class CommentFormNode(template.Node):
     def __init__(self, content_type, obj_id_lookup_var, obj_id, free,
@@ -46,24 +46,24 @@ class CommentFormNode(template.Node):
             context['display_form'] = True
         context['target'] = '%s:%s' % (self.content_type.id, self.obj_id)
         options = []
-        for var, abbr in (('photos_required', comments.PHOTOS_REQUIRED),
-                          ('photos_optional', comments.PHOTOS_OPTIONAL),
-                          ('ratings_required', comments.RATINGS_REQUIRED),
-                          ('ratings_optional', comments.RATINGS_OPTIONAL),
-                          ('is_public', comments.IS_PUBLIC)):
+        for var, abbr in (('photos_required', PHOTOS_REQUIRED),
+                          ('photos_optional', PHOTOS_OPTIONAL),
+                          ('ratings_required', RATINGS_REQUIRED),
+                          ('ratings_optional', RATINGS_OPTIONAL),
+                          ('is_public', IS_PUBLIC)):
             context[var] = getattr(self, var)
             if getattr(self, var):
                 options.append(abbr)
         context['options'] = ','.join(options)
         if self.free:
-            context['hash'] = comments.get_security_hash(context['options'], '', '', context['target'])
+            context['hash'] = Comment.objects.get_security_hash(context['options'], '', '', context['target'])
             default_form = loader.get_template(FREE_COMMENT_FORM)
         else:
             context['photo_options'] = self.photo_options
             context['rating_options'] = normalize_newlines(base64.encodestring(self.rating_options).strip())
             if self.rating_options:
-                context['rating_range'], context['rating_choices'] = comments.get_rating_options(self.rating_options)
-            context['hash'] = comments.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target'])
+                context['rating_range'], context['rating_choices'] = Comment.objects.get_rating_options(self.rating_options)
+            context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target'])
             default_form = loader.get_template(COMMENT_FORM)
         output = default_form.render(context)
         context.pop()
@@ -76,13 +76,13 @@ class CommentCountNode(template.Node):
         self.var_name, self.free = var_name, free
 
     def render(self, context):
-        from django.conf.settings import SITE_ID
-        get_count_function = self.free and freecomments.get_count or comments.get_count
+        from django.conf import settings
+        manager = self.free and FreeComment.objects or Comment.objects
         if self.context_var_name is not None:
             self.obj_id = template.resolve_variable(self.context_var_name, context)
-        comment_count = get_count_function(object_id__exact=self.obj_id,
-            content_type__package__label__exact=self.package,
-            content_type__python_module_name__exact=self.module, site__id__exact=SITE_ID)
+        comment_count = manager.filter(object_id__exact=self.obj_id,
+            content_type__app_label__exact=self.package,
+            content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count()
         context[self.var_name] = comment_count
         return ''
 
@@ -95,8 +95,8 @@ class CommentListNode(template.Node):
         self.extra_kwargs = extra_kwargs or {}
 
     def render(self, context):
-        from django.conf.settings import COMMENTS_BANNED_USERS_GROUP, SITE_ID
-        get_list_function = self.free and freecomments.get_list or comments.get_list_with_karma
+        from django.conf import settings
+        get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma
         if self.context_var_name is not None:
             try:
                 self.obj_id = template.resolve_variable(self.context_var_name, context)
@@ -104,26 +104,24 @@ class CommentListNode(template.Node):
                 return ''
         kwargs = {
             'object_id__exact': self.obj_id,
-            'content_type__package__label__exact': self.package,
-            'content_type__python_module_name__exact': self.module,
-            'site__id__exact': SITE_ID,
-            'select_related': True,
-            'order_by': (self.ordering + 'submit_date',),
+            'content_type__app_label__exact': self.package,
+            'content_type__model__exact': self.module,
+            'site__id__exact': settings.SITE_ID,
         }
         kwargs.update(self.extra_kwargs)
-        if not self.free and COMMENTS_BANNED_USERS_GROUP:
-            kwargs['select'] = {'is_hidden': 'user_id IN (SELECT user_id FROM auth_users_groups WHERE group_id = %s)' % COMMENTS_BANNED_USERS_GROUP}
-        comment_list = get_list_function(**kwargs)
+        if not self.free and settings.COMMENTS_BANNED_USERS_GROUP:
+            kwargs['select'] = {'is_hidden': 'user_id IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)' % settings.COMMENTS_BANNED_USERS_GROUP}
+        comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
 
         if not self.free:
             if context.has_key('user') and not context['user'].is_anonymous():
                 user_id = context['user'].id
-                context['user_can_moderate_comments'] = comments.user_is_moderator(context['user'])
+                context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user'])
             else:
                 user_id = None
                 context['user_can_moderate_comments'] = False
             # Only display comments by banned users to those users themselves.
-            if COMMENTS_BANNED_USERS_GROUP:
+            if settings.COMMENTS_BANNED_USERS_GROUP:
                 comment_list = [c for c in comment_list if not c.is_hidden or (user_id == c.user_id)]
 
         context[self.var_name] = comment_list
@@ -157,8 +155,8 @@ class DoCommentForm:
         except ValueError: # unpack list of wrong size
             raise template.TemplateSyntaxError, &quot;Third argument in %r tag must be in the format 'package.module'&quot; % tokens[0]
         try:
-            content_type = contenttypes.get_object(package__label__exact=package, python_module_name__exact=module)
-        except contenttypes.ContentTypeDoesNotExist:
+            content_type = ContentType.objects.get(app_label__exact=package, model__exact=module)
+        except ContentType.DoesNotExist:
             raise template.TemplateSyntaxError, &quot;%r tag has invalid content-type '%s.%s'&quot; % (tokens[0], package, module)
         obj_id_lookup_var, obj_id = None, None
         if tokens[3].isdigit():
@@ -183,8 +181,8 @@ class DoCommentForm:
                         if not opt.isalnum():
                             raise template.TemplateSyntaxError, &quot;Invalid photo directory name in %r tag: '%s'&quot; % (tokens[0], opt)
                     for opt in option_list[1::3] + option_list[2::3]:
-                        if not opt.isdigit() or not (comments.MIN_PHOTO_DIMENSION &lt;= int(opt) &lt;= comments.MAX_PHOTO_DIMENSION):
-                            raise template.TemplateSyntaxError, &quot;Invalid photo dimension in %r tag: '%s'. Only values between %s and %s are allowed.&quot; % (tokens[0], opt, comments.MIN_PHOTO_DIMENSION, comments.MAX_PHOTO_DIMENSION)
+                        if not opt.isdigit() or not (MIN_PHOTO_DIMENSION &lt;= int(opt) &lt;= MAX_PHOTO_DIMENSION):
+                            raise template.TemplateSyntaxError, &quot;Invalid photo dimension in %r tag: '%s'. Only values between %s and %s are allowed.&quot; % (tokens[0], opt, MIN_PHOTO_DIMENSION, MAX_PHOTO_DIMENSION)
                     # VALIDATION ENDS #########################################
                     kwargs[option] = True
                     kwargs['photo_options'] = args
@@ -237,8 +235,8 @@ class DoCommentCount:
         except ValueError: # unpack list of wrong size
             raise template.TemplateSyntaxError, &quot;Third argument in %r tag must be in the format 'package.module'&quot; % tokens[0]
         try:
-            content_type = contenttypes.get_object(package__label__exact=package, python_module_name__exact=module)
-        except contenttypes.ContentTypeDoesNotExist:
+            content_type = ContentType.objects.get(app_label__exact=package, model__exact=module)
+        except ContentType.DoesNotExist:
             raise template.TemplateSyntaxError, &quot;%r tag has invalid content-type '%s.%s'&quot; % (tokens[0], package, module)
         var_name, obj_id = None, None
         if tokens[3].isdigit():
@@ -292,8 +290,8 @@ class DoGetCommentList:
         except ValueError: # unpack list of wrong size
             raise template.TemplateSyntaxError, &quot;Third argument in %r tag must be in the format 'package.module'&quot; % tokens[0]
         try:
-            content_type = contenttypes.get_object(package__label__exact=package, python_module_name__exact=module)
-        except contenttypes.ContentTypeDoesNotExist:
+            content_type = ContentType.objects.get(app_label__exact=package,model__exact=module)
+        except ContentType.DoesNotExist:
             raise template.TemplateSyntaxError, &quot;%r tag has invalid content-type '%s.%s'&quot; % (tokens[0], package, module)
         var_name, obj_id = None, None
         if tokens[3].isdigit():</diff>
      <filename>django/contrib/comments/templatetags/comments.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,17 @@
-from django.core import formfields, validators
+from django.core import validators
+from django import forms
 from django.core.mail import mail_admins, mail_managers
-from django.core.exceptions import Http404, ObjectDoesNotExist
-from django.core.extensions import DjangoContext, render_to_response
-from django.models.auth import users
-from django.models.comments import comments, freecomments
-from django.models.core import contenttypes
-from django.parts.auth.formfields import AuthenticationForm
-from django.utils.httpwrappers import HttpResponseRedirect
+from django.http import Http404
+from django.core.exceptions import ObjectDoesNotExist
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.contrib.auth.models import SESSION_KEY
+from django.contrib.comments.models import Comment, FreeComment, PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.auth.forms import AuthenticationForm
+from django.http import HttpResponseRedirect
 from django.utils.text import normalize_newlines
-from django.conf.settings import BANNED_IPS, COMMENTS_ALLOW_PROFANITIES, COMMENTS_SKETCHY_USERS_GROUP, COMMENTS_FIRST_FEW, SITE_ID
+from django.conf import settings
 from django.utils.translation import ngettext
 import base64, datetime
 
@@ -26,37 +29,37 @@ class PublicCommentManipulator(AuthenticationForm):
             else:
                 return []
         self.fields.extend([
-            formfields.LargeTextField(field_name=&quot;comment&quot;, maxlength=3000, is_required=True,
+            forms.LargeTextField(field_name=&quot;comment&quot;, maxlength=3000, is_required=True,
                 validator_list=[self.hasNoProfanities]),
-            formfields.RadioSelectField(field_name=&quot;rating1&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating1&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 0,
                 validator_list=get_validator_list(1),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating2&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating2&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 1,
                 validator_list=get_validator_list(2),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating3&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating3&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 2,
                 validator_list=get_validator_list(3),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating4&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating4&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 3,
                 validator_list=get_validator_list(4),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating5&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating5&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 4,
                 validator_list=get_validator_list(5),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating6&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating6&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 5,
                 validator_list=get_validator_list(6),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating7&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating7&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 6,
                 validator_list=get_validator_list(7),
             ),
-            formfields.RadioSelectField(field_name=&quot;rating8&quot;, choices=choices,
+            forms.RadioSelectField(field_name=&quot;rating8&quot;, choices=choices,
                 is_required=ratings_required and num_rating_choices &gt; 7,
                 validator_list=get_validator_list(8),
             ),
@@ -69,25 +72,25 @@ class PublicCommentManipulator(AuthenticationForm):
             self.user_cache = user
 
     def hasNoProfanities(self, field_data, all_data):
-        if COMMENTS_ALLOW_PROFANITIES:
+        if settings.COMMENTS_ALLOW_PROFANITIES:
             return
         return validators.hasNoProfanities(field_data, all_data)
 
     def get_comment(self, new_data):
         &quot;Helper function&quot;
-        return comments.Comment(None, self.get_user_id(), new_data[&quot;content_type_id&quot;],
+        return Comment(None, self.get_user_id(), new_data[&quot;content_type_id&quot;],
             new_data[&quot;object_id&quot;], new_data.get(&quot;headline&quot;, &quot;&quot;).strip(),
             new_data[&quot;comment&quot;].strip(), new_data.get(&quot;rating1&quot;, None),
             new_data.get(&quot;rating2&quot;, None), new_data.get(&quot;rating3&quot;, None),
             new_data.get(&quot;rating4&quot;, None), new_data.get(&quot;rating5&quot;, None),
             new_data.get(&quot;rating6&quot;, None), new_data.get(&quot;rating7&quot;, None),
             new_data.get(&quot;rating8&quot;, None), new_data.get(&quot;rating1&quot;, None) is not None,
-            datetime.datetime.now(), new_data[&quot;is_public&quot;], new_data[&quot;ip_address&quot;], False, SITE_ID)
+            datetime.datetime.now(), new_data[&quot;is_public&quot;], new_data[&quot;ip_address&quot;], False, settings.SITE_ID)
 
     def save(self, new_data):
         today = datetime.date.today()
         c = self.get_comment(new_data)
-        for old in comments.get_list(content_type__id__exact=new_data[&quot;content_type_id&quot;],
+        for old in Comment.objects.filter(content_type__id__exact=new_data[&quot;content_type_id&quot;],
             object_id__exact=new_data[&quot;object_id&quot;], user__id__exact=self.get_user_id()):
             # Check that this comment isn't duplicate. (Sometimes people post
             # comments twice by mistake.) If it is, fail silently by pretending
@@ -105,37 +108,37 @@ class PublicCommentManipulator(AuthenticationForm):
         c.save()
         # If the commentor has posted fewer than COMMENTS_FIRST_FEW comments,
         # send the comment to the managers.
-        if self.user_cache.get_comments_comment_count() &lt;= COMMENTS_FIRST_FEW:
+        if self.user_cache.comment_set.count() &lt;= settings.COMMENTS_FIRST_FEW:
             message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
                 'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s') % \
-                {'count': COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
+                {'count': settings.COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
             mail_managers(&quot;Comment posted by rookie user&quot;, message)
-        if COMMENTS_SKETCHY_USERS_GROUP and COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
+        if settings.COMMENTS_SKETCHY_USERS_GROUP and settings.COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
             message = _('This comment was posted by a sketchy user:\n\n%(text)s') % {'text': c.get_as_text()}
             mail_managers(&quot;Comment posted by sketchy user (%s)&quot; % self.user_cache.username, c.get_as_text())
         return c
 
-class PublicFreeCommentManipulator(formfields.Manipulator):
+class PublicFreeCommentManipulator(forms.Manipulator):
     &quot;Manipulator that handles public free (unregistered) comments&quot;
     def __init__(self):
         self.fields = (
-            formfields.TextField(field_name=&quot;person_name&quot;, maxlength=50, is_required=True,
+            forms.TextField(field_name=&quot;person_name&quot;, maxlength=50, is_required=True,
                 validator_list=[self.hasNoProfanities]),
-            formfields.LargeTextField(field_name=&quot;comment&quot;, maxlength=3000, is_required=True,
+            forms.LargeTextField(field_name=&quot;comment&quot;, maxlength=3000, is_required=True,
                 validator_list=[self.hasNoProfanities]),
         )
 
     def hasNoProfanities(self, field_data, all_data):
-        if COMMENTS_ALLOW_PROFANITIES:
+        if settings.COMMENTS_ALLOW_PROFANITIES:
             return
         return validators.hasNoProfanities(field_data, all_data)
 
     def get_comment(self, new_data):
         &quot;Helper function&quot;
-        return freecomments.FreeComment(None, new_data[&quot;content_type_id&quot;],
+        return FreeComment(None, new_data[&quot;content_type_id&quot;],
             new_data[&quot;object_id&quot;], new_data[&quot;comment&quot;].strip(),
             new_data[&quot;person_name&quot;].strip(), datetime.datetime.now(), new_data[&quot;is_public&quot;],
-            new_data[&quot;ip_address&quot;], False, SITE_ID)
+            new_data[&quot;ip_address&quot;], False, settings.SITE_ID)
 
     def save(self, new_data):
         today = datetime.date.today()
@@ -143,7 +146,7 @@ class PublicFreeCommentManipulator(formfields.Manipulator):
         # Check that this comment isn't duplicate. (Sometimes people post
         # comments twice by mistake.) If it is, fail silently by pretending
         # the comment was posted successfully.
-        for old_comment in freecomments.get_list(content_type__id__exact=new_data[&quot;content_type_id&quot;],
+        for old_comment in FreeComment.objects.filter(content_type__id__exact=new_data[&quot;content_type_id&quot;],
             object_id__exact=new_data[&quot;object_id&quot;], person_name__exact=new_data[&quot;person_name&quot;],
             submit_date__year=today.year, submit_date__month=today.month,
             submit_date__day=today.day):
@@ -190,16 +193,16 @@ def post_comment(request):
         raise Http404, _(&quot;One or more of the required fields wasn't submitted&quot;)
     photo_options = request.POST.get('photo_options', '')
     rating_options = normalize_newlines(request.POST.get('rating_options', ''))
-    if comments.get_security_hash(options, photo_options, rating_options, target) != security_hash:
+    if Comment.objects.get_security_hash(options, photo_options, rating_options, target) != security_hash:
         raise Http404, _(&quot;Somebody tampered with the comment form (security violation)&quot;)
     # Now we can be assured the data is valid.
     if rating_options:
-        rating_range, rating_choices = comments.get_rating_options(base64.decodestring(rating_options))
+        rating_range, rating_choices = Comment.objects.get_rating_options(base64.decodestring(rating_options))
     else:
         rating_range, rating_choices = [], []
     content_type_id, object_id = target.split(':') # target is something like '52:5157'
     try:
-        obj = contenttypes.get_object(pk=content_type_id).get_object_for_this_type(pk=object_id)
+        obj = ContentType.objects.get(pk=content_type_id).get_object_for_this_type(pk=object_id)
     except ObjectDoesNotExist:
         raise Http404, _(&quot;The comment form had an invalid 'target' parameter -- the object ID was invalid&quot;)
     option_list = options.split(',') # options is something like 'pa,ra'
@@ -207,20 +210,20 @@ def post_comment(request):
     new_data['content_type_id'] = content_type_id
     new_data['object_id'] = object_id
     new_data['ip_address'] = request.META.get('REMOTE_ADDR')
-    new_data['is_public'] = comments.IS_PUBLIC in option_list
+    new_data['is_public'] = IS_PUBLIC in option_list
     manipulator = PublicCommentManipulator(request.user,
-        ratings_required=comments.RATINGS_REQUIRED in option_list,
+        ratings_required=RATINGS_REQUIRED in option_list,
         ratings_range=rating_range,
         num_rating_choices=len(rating_choices))
     errors = manipulator.get_validation_errors(new_data)
     # If user gave correct username/password and wasn't already logged in, log them in
     # so they don't have to enter a username/password again.
     if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
-        request.session[users.SESSION_KEY] = manipulator.get_user_id()
+        request.session[SESSION_KEY] = manipulator.get_user_id()
     if errors or request.POST.has_key('preview'):
-        class CommentFormWrapper(formfields.FormWrapper):
+        class CommentFormWrapper(forms.FormWrapper):
             def __init__(self, manipulator, new_data, errors, rating_choices):
-                formfields.FormWrapper.__init__(self, manipulator, new_data, errors)
+                forms.FormWrapper.__init__(self, manipulator, new_data, errors)
                 self.rating_choices = rating_choices
             def ratings(self):
                 field_list = [self['rating%d' % (i+1)] for i in range(len(rating_choices))]
@@ -229,22 +232,22 @@ def post_comment(request):
                 return field_list
         comment = errors and '' or manipulator.get_comment(new_data)
         comment_form = CommentFormWrapper(manipulator, new_data, errors, rating_choices)
-        return render_to_response('comments/preview', {
+        return render_to_response('comments/preview.html', {
             'comment': comment,
             'comment_form': comment_form,
             'options': options,
             'target': target,
             'hash': security_hash,
             'rating_options': rating_options,
-            'ratings_optional': comments.RATINGS_OPTIONAL in option_list,
-            'ratings_required': comments.RATINGS_REQUIRED in option_list,
+            'ratings_optional': RATINGS_OPTIONAL in option_list,
+            'ratings_required': RATINGS_REQUIRED in option_list,
             'rating_range': rating_range,
             'rating_choices': rating_choices,
-        }, context_instance=DjangoContext(request))
+        }, context_instance=RequestContext(request))
     elif request.POST.has_key('post'):
         # If the IP is banned, mail the admins, do NOT save the comment, and
         # serve up the &quot;Thanks for posting&quot; page as if the comment WAS posted.
-        if request.META['REMOTE_ADDR'] in BANNED_IPS:
+        if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
             mail_admins(&quot;Banned IP attempted to post comment&quot;, str(request.POST) + &quot;\n\n&quot; + str(request.META))
         else:
             manipulator.do_html2python(new_data)
@@ -279,10 +282,10 @@ def post_free_comment(request):
         options, target, security_hash = request.POST['options'], request.POST['target'], request.POST['gonzo']
     except KeyError:
         raise Http404, _(&quot;One or more of the required fields wasn't submitted&quot;)
-    if comments.get_security_hash(options, '', '', target) != security_hash:
+    if Comment.objects.get_security_hash(options, '', '', target) != security_hash:
         raise Http404, _(&quot;Somebody tampered with the comment form (security violation)&quot;)
     content_type_id, object_id = target.split(':') # target is something like '52:5157'
-    content_type = contenttypes.get_object(pk=content_type_id)
+    content_type = ContentType.objects.get(pk=content_type_id)
     try:
         obj = content_type.get_object_for_this_type(pk=object_id)
     except ObjectDoesNotExist:
@@ -292,22 +295,22 @@ def post_free_comment(request):
     new_data['content_type_id'] = content_type_id
     new_data['object_id'] = object_id
     new_data['ip_address'] = request.META['REMOTE_ADDR']
-    new_data['is_public'] = comments.IS_PUBLIC in option_list
+    new_data['is_public'] = IS_PUBLIC in option_list
     manipulator = PublicFreeCommentManipulator()
     errors = manipulator.get_validation_errors(new_data)
     if errors or request.POST.has_key('preview'):
         comment = errors and '' or manipulator.get_comment(new_data)
-        return render_to_response('comments/free_preview', {
+        return render_to_response('comments/free_preview.html', {
             'comment': comment,
-            'comment_form': formfields.FormWrapper(manipulator, new_data, errors),
+            'comment_form': forms.FormWrapper(manipulator, new_data, errors),
             'options': options,
             'target': target,
             'hash': security_hash,
-        }, context_instance=DjangoContext(request))
+        }, context_instance=RequestContext(request))
     elif request.POST.has_key('post'):
         # If the IP is banned, mail the admins, do NOT save the comment, and
         # serve up the &quot;Thanks for posting&quot; page as if the comment WAS posted.
-        if request.META['REMOTE_ADDR'] in BANNED_IPS:
+        if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
             from django.core.mail import mail_admins
             mail_admins(&quot;Practical joker&quot;, str(request.POST) + &quot;\n\n&quot; + str(request.META))
         else:
@@ -330,8 +333,8 @@ def comment_was_posted(request):
     if request.GET.has_key('c'):
         content_type_id, object_id = request.GET['c'].split(':')
         try:
-            content_type = contenttypes.get_object(pk=content_type_id)
+            content_type = ContentType.objects.get(pk=content_type_id)
             obj = content_type.get_object_for_this_type(pk=object_id)
         except ObjectDoesNotExist:
             pass
-    return render_to_response('comments/posted', {'object': obj}, context_instance=DjangoContext(request))
+    return render_to_response('comments/posted.html', {'object': obj}, context_instance=RequestContext(request))</diff>
      <filename>django/contrib/comments/views/comments.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
-from django.core.exceptions import Http404
-from django.core.extensions import DjangoContext, render_to_response
-from django.models.comments import comments, karma
+from django.http import Http404
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.contrib.comments.models import Comment, KarmaScore
 
 def vote(request, comment_id, vote):
     &quot;&quot;&quot;
@@ -17,12 +18,12 @@ def vote(request, comment_id, vote):
     if request.user.is_anonymous():
         raise Http404, _(&quot;Anonymous users cannot vote&quot;)
     try:
-        comment = comments.get_object(pk=comment_id)
-    except comments.CommentDoesNotExist:
+        comment = Comment.objects.get(pk=comment_id)
+    except Comment.DoesNotExist:
         raise Http404, _(&quot;Invalid comment ID&quot;)
-    if comment.user_id == request.user.id:
+    if comment.user.id == request.user.id:
         raise Http404, _(&quot;No voting for yourself&quot;)
-    karma.vote(request.user.id, comment_id, rating)
+    KarmaScore.objects.vote(request.user.id, comment_id, rating)
     # Reload comment to ensure we have up to date karma count
-    comment = comments.get_object(pk=comment_id)
-    return render_to_response('comments/karma_vote_accepted', {'comment': comment}, context_instance=DjangoContext(request))
+    comment = Comment.objects.get(pk=comment_id)
+    return render_to_response('comments/karma_vote_accepted.html', {'comment': comment}, context_instance=RequestContext(request))</diff>
      <filename>django/contrib/comments/views/karma.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,10 @@
-from django.core.extensions import DjangoContext, render_to_response
-from django.core.exceptions import Http404
-from django.models.comments import comments, moderatordeletions, userflags
-from django.views.decorators.auth import login_required
-from django.utils.httpwrappers import HttpResponseRedirect
-from django.conf.settings import SITE_ID
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.http import Http404
+from django.contrib.comments.models import Comment, ModeratorDeletion, UserFlag
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponseRedirect
+from django.conf import settings
 
 def flag(request, comment_id):
     &quot;&quot;&quot;
@@ -14,22 +15,16 @@ def flag(request, comment_id):
         comment
             the flagged `comments.comments` object
     &quot;&quot;&quot;
-    try:
-        comment = comments.get_object(pk=comment_id, site__id__exact=SITE_ID)
-    except comments.CommentDoesNotExist:
-        raise Http404
+    comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
     if request.POST:
-        userflags.flag(comment, request.user)
+        UserFlag.objects.flag(comment, request.user)
         return HttpResponseRedirect('%sdone/' % request.path)
-    return render_to_response('comments/flag_verify', {'comment': comment}, context_instance=DjangoContext(request))
+    return render_to_response('comments/flag_verify.html', {'comment': comment}, context_instance=RequestContext(request))
 flag = login_required(flag)
 
 def flag_done(request, comment_id):
-    try:
-        comment = comments.get_object(pk=comment_id, site__id__exact=SITE_ID)
-    except comments.CommentDoesNotExist:
-        raise Http404
-    return render_to_response('comments/flag_done', {'comment': comment}, context_instance=DjangoContext(request))
+    comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
+    return render_to_response('comments/flag_done.html', {'comment': comment}, context_instance=RequestContext(request))
 
 def delete(request, comment_id):
     &quot;&quot;&quot;
@@ -40,26 +35,20 @@ def delete(request, comment_id):
         comment
             the flagged `comments.comments` object
     &quot;&quot;&quot;
-    try:
-        comment = comments.get_object(pk=comment_id, site__id__exact=SITE_ID)
-    except comments.CommentDoesNotExist:
-        raise Http404
-    if not comments.user_is_moderator(request.user):
+    comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
+    if not Comment.objects.user_is_moderator(request.user):
         raise Http404
     if request.POST:
         # If the comment has already been removed, silently fail.
         if not comment.is_removed:
             comment.is_removed = True
             comment.save()
-            m = moderatordeletions.ModeratorDeletion(None, request.user.id, comment.id, None)
+            m = ModeratorDeletion(None, request.user.id, comment.id, None)
             m.save()
         return HttpResponseRedirect('%sdone/' % request.path)
-    return render_to_response('comments/delete_verify', {'comment': comment}, context_instance=DjangoContext(request))
+    return render_to_response('comments/delete_verify.html', {'comment': comment}, context_instance=RequestContext(request))
 delete = login_required(delete)
 
 def delete_done(request, comment_id):
-    try:
-        comment = comments.get_object(pk=comment_id, site__id__exact=SITE_ID)
-    except comments.CommentDoesNotExist:
-        raise Http404
-    return render_to_response('comments/delete_done', {'comment': comment}, context_instance=DjangoContext(request))
+    comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
+    return render_to_response('comments/delete_done.html', {'comment': comment}, context_instance=RequestContext(request))</diff>
      <filename>django/contrib/comments/views/userflags.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 from django.contrib.flatpages.views import flatpage
-from django.core.extensions import Http404
-from django.conf.settings import DEBUG
+from django.http import Http404
+from django.conf import settings
 
 class FlatpageFallbackMiddleware:
     def process_response(self, request, response):
@@ -13,6 +13,6 @@ class FlatpageFallbackMiddleware:
         except Http404:
             return response
         except:
-            if DEBUG:
+            if settings.DEBUG:
                 raise
             return response</diff>
      <filename>django/contrib/flatpages/middleware.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,10 @@
-from django.core import template_loader
-from django.core.extensions import get_object_or_404, DjangoContext
-from django.models.flatpages import flatpages
-from django.utils.httpwrappers import HttpResponse
-from django.conf.settings import SITE_ID
+from django.contrib.flatpages.models import FlatPage
+from django.template import loader, RequestContext
+from django.shortcuts import get_object_or_404
+from django.http import HttpResponse
+from django.conf import settings
 
-DEFAULT_TEMPLATE = 'flatpages/default'
+DEFAULT_TEMPLATE = 'flatpages/default.html'
 
 def flatpage(request, url):
     &quot;&quot;&quot;
@@ -12,24 +12,24 @@ def flatpage(request, url):
 
     Models: `flatpages.flatpages`
     Templates: Uses the template defined by the ``template_name`` field,
-        or `flatpages/default` if template_name is not defined.
+        or `flatpages/default.html` if template_name is not defined.
     Context:
         flatpage
             `flatpages.flatpages` object
     &quot;&quot;&quot;
     if not url.startswith('/'):
         url = &quot;/&quot; + url
-    f = get_object_or_404(flatpages, url__exact=url, sites__id__exact=SITE_ID)
+    f = get_object_or_404(FlatPage, url__exact=url, sites__id__exact=settings.SITE_ID)
     # If registration is required for accessing this page, and the user isn't
     # logged in, redirect to the login page.
     if f.registration_required and request.user.is_anonymous():
-        from django.views.auth.login import redirect_to_login
+        from django.contrib.auth.views import redirect_to_login
         return redirect_to_login(request.path)
     if f.template_name:
-        t = template_loader.select_template((f.template_name, DEFAULT_TEMPLATE))
+        t = loader.select_template((f.template_name, DEFAULT_TEMPLATE))
     else:
-        t = template_loader.get_template(DEFAULT_TEMPLATE)
-    c = DjangoContext(request, {
+        t = loader.get_template(DEFAULT_TEMPLATE)
+    c = RequestContext(request, {
         'flatpage': f,
     })
     return HttpResponse(t.render(c))</diff>
      <filename>django/contrib/flatpages/views.py</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,8 @@ In each case, if the required library is not installed, the filter will
 silently fail and return the un-marked-up text.
 &quot;&quot;&quot;
 
-from django.core import template
+from django import template
+from django.conf import settings
 
 register = template.Library()
 
@@ -22,6 +23,8 @@ def textile(value):
     try:
         import textile
     except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError, &quot;Error in {% textile %} filter: The Python textile library isn't installed.&quot;
         return value
     else:
         return textile.textile(value)
@@ -30,6 +33,8 @@ def markdown(value):
     try:
         import markdown
     except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError, &quot;Error in {% markdown %} filter: The Python markdown library isn't installed.&quot;
         return value
     else:
         return markdown.markdown(value)
@@ -38,6 +43,8 @@ def restructuredtext(value):
     try:
         from docutils.core import publish_parts
     except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError, &quot;Error in {% restructuredtext %} filter: The Python docutils library isn't installed.&quot;
         return value
     else:
         parts = publish_parts(source=value, writer_name=&quot;html4css1&quot;)</diff>
      <filename>django/contrib/markup/templatetags/markup.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
-from django.models.redirects import redirects
-from django.utils import httpwrappers
-from django.conf.settings import APPEND_SLASH, SITE_ID
+from django.contrib.redirects.models import Redirect
+from django import http
+from django.conf import settings
 
 class RedirectFallbackMiddleware:
     def process_response(self, request, response):
@@ -8,20 +8,20 @@ class RedirectFallbackMiddleware:
             return response # No need to check for a redirect for non-404 responses.
         path = request.get_full_path()
         try:
-            r = redirects.get_object(site__id__exact=SITE_ID, old_path__exact=path)
-        except redirects.RedirectDoesNotExist:
+            r = Redirect.objects.get(site__id__exact=settings.SITE_ID, old_path=path)
+        except Redirect.DoesNotExist:
             r = None
-        if r is None and APPEND_SLASH:
+        if r is None and settings.APPEND_SLASH:
             # Try removing the trailing slash.
             try:
-                r = redirects.get_object(site__id__exact=SITE_ID,
-                    old_path__exact=path[:path.rfind('/')]+path[path.rfind('/')+1:])
-            except redirects.RedirectDoesNotExist:
+                r = Redirect.objects.get(site__id__exact=settings.SITE_ID,
+                    old_path=path[:path.rfind('/')]+path[path.rfind('/')+1:])
+            except Redirect.DoesNotExist:
                 pass
         if r is not None:
             if r == '':
-                return httpwrappers.HttpResponseGone()
-            return httpwrappers.HttpResponsePermanentRedirect(r.new_path)
+                return http.HttpResponseGone()
+            return http.HttpResponsePermanentRedirect(r.new_path)
 
         # No redirect was found. Return the response.
         return response</diff>
      <filename>django/contrib/redirects/middleware.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,8 @@
 from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
-from django.core.template import Context, loader, Template, TemplateDoesNotExist
-from django.models.core import sites
+from django.template import Context, loader, Template, TemplateDoesNotExist
+from django.contrib.sites.models import Site
 from django.utils import feedgenerator
-from django.conf.settings import LANGUAGE_CODE, SETTINGS_MODULE
+from django.conf import settings
 
 def add_domain(domain, url):
     if not url.startswith('http://'):
@@ -60,7 +60,7 @@ class Feed:
         else:
             obj = None
 
-        current_site = sites.get_current()
+        current_site = Site.objects.get_current()
         link = self.__get_dynamic_attr('link', obj)
         link = add_domain(current_site.domain, link)
 
@@ -68,7 +68,7 @@ class Feed:
             title = self.__get_dynamic_attr('title', obj),
             link = link,
             description = self.__get_dynamic_attr('description', obj),
-            language = LANGUAGE_CODE.decode(),
+            language = settings.LANGUAGE_CODE.decode(),
             feed_url = add_domain(current_site, self.feed_url),
             author_name = self.__get_dynamic_attr('author_name', obj),
             author_link = self.__get_dynamic_attr('author_link', obj),
@@ -76,11 +76,11 @@ class Feed:
         )
 
         try:
-            title_template = loader.get_template('feeds/%s_title' % self.slug)
+            title_template = loader.get_template('feeds/%s_title.html' % self.slug)
         except TemplateDoesNotExist:
             title_template = Template('{{ obj }}')
         try:
-            description_template = loader.get_template('feeds/%s_description' % self.slug)
+            description_template = loader.get_template('feeds/%s_description.html' % self.slug)
         except TemplateDoesNotExist:
             description_template = Template('{{ obj }}')
 </diff>
      <filename>django/contrib/syndication/feeds.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,5 @@
 from django.contrib.syndication import feeds
-from django.core.exceptions import Http404
-from django.utils.httpwrappers import HttpResponse
+from django.http import HttpResponse, Http404
 
 def feed(request, url, feed_dict=None):
     if not feed_dict:</diff>
      <filename>django/contrib/syndication/views.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 &quot;Database cache backend.&quot;
 
 from django.core.cache.backends.base import BaseCache
-from django.core.db import db, DatabaseError
+from django.db import connection, transaction
 import base64, time
 from datetime import datetime
 try:
@@ -25,7 +25,7 @@ class CacheClass(BaseCache):
             self._cull_frequency = 3
 
     def get(self, key, default=None):
-        cursor = db.cursor()
+        cursor = connection.cursor()
         cursor.execute(&quot;SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s&quot; % self._table, [key])
         row = cursor.fetchone()
         if row is None:
@@ -33,14 +33,14 @@ class CacheClass(BaseCache):
         now = datetime.now()
         if row[2] &lt; now:
             cursor.execute(&quot;DELETE FROM %s WHERE cache_key = %%s&quot; % self._table, [key])
-            db.commit()
+            transaction.commit_unless_managed()
             return default
         return pickle.loads(base64.decodestring(row[1]))
 
     def set(self, key, value, timeout=None):
         if timeout is None:
             timeout = self.default_timeout
-        cursor = db.cursor()
+        cursor = connection.cursor()
         cursor.execute(&quot;SELECT COUNT(*) FROM %s&quot; % self._table)
         num = cursor.fetchone()[0]
         now = datetime.now().replace(microsecond=0)
@@ -58,15 +58,15 @@ class CacheClass(BaseCache):
             # To be threadsafe, updates/inserts are allowed to fail silently
             pass
         else:
-            db.commit()
+            transaction.commit_unless_managed()
 
     def delete(self, key):
-        cursor = db.cursor()
+        cursor = connection.cursor()
         cursor.execute(&quot;DELETE FROM %s WHERE cache_key = %%s&quot; % self._table, [key])
-        db.commit()
+        transaction.commit_unless_managed()
 
     def has_key(self, key):
-        cursor = db.cursor()
+        cursor = connection.cursor()
         cursor.execute(&quot;SELECT cache_key FROM %s WHERE cache_key = %%s&quot; % self._table, [key])
         return cursor.fetchone() is not None
 </diff>
      <filename>django/core/cache/backends/db.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,10 +4,10 @@ template context. Each function takes the request object as its only parameter
 and returns a dictionary to add to the context.
 
 These are referenced from the setting TEMPLATE_CONTEXT_PROCESSORS and used by
-DjangoContext.
+RequestContext.
 &quot;&quot;&quot;
 
-from django.conf.settings import DEBUG, INTERNAL_IPS, LANGUAGES, LANGUAGE_CODE
+from django.conf import settings
 
 def auth(request):
     &quot;&quot;&quot;
@@ -23,19 +23,19 @@ def auth(request):
 def debug(request):
     &quot;Returns context variables helpful for debugging.&quot;
     context_extras = {}
-    if DEBUG and request.META.get('REMOTE_ADDR') in INTERNAL_IPS:
+    if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
         context_extras['debug'] = True
-        from django.core import db
-        context_extras['sql_queries'] = db.db.queries
+        from django.db import connection
+        context_extras['sql_queries'] = connection.queries
     return context_extras
 
 def i18n(request):
     context_extras = {}
-    context_extras['LANGUAGES'] = LANGUAGES
+    context_extras['LANGUAGES'] = settings.LANGUAGES
     if hasattr(request, 'LANGUAGE_CODE'):
         context_extras['LANGUAGE_CODE'] = request.LANGUAGE_CODE
     else:
-        context_extras['LANGUAGE_CODE'] = LANGUAGE_CODE
+        context_extras['LANGUAGE_CODE'] = settings.LANGUAGE_CODE
     return context_extras
 
 def request(request):</diff>
      <filename>django/core/context_processors.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,8 @@
 &quot;Global Django exceptions&quot;
 
-from django.core.template import SilentVariableFailure
-
-class Http404(Exception):
-    pass
-
-class ObjectDoesNotExist(SilentVariableFailure):
+class ObjectDoesNotExist(Exception):
     &quot;The requested object does not exist&quot;
-    pass
+    silent_variable_failure = True
 
 class SuspiciousOperation(Exception):
     &quot;The user did something suspicious&quot;</diff>
      <filename>django/core/exceptions.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,6 @@
-from django.utils import httpwrappers
+from django.core import signals
+from django.dispatch import dispatcher
+from django import http
 import sys
 
 class BaseHandler:
@@ -48,12 +50,9 @@ class BaseHandler:
 
     def get_response(self, path, request):
         &quot;Returns an HttpResponse object for the given HttpRequest&quot;
-        from django.core import db, exceptions, urlresolvers
+        from django.core import exceptions, urlresolvers
         from django.core.mail import mail_admins
-        from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF
-
-        # Reset query list per request.
-        db.db.queries = []
+        from django.conf import settings
 
         # Apply request middleware
         for middleware_method in self._request_middleware:
@@ -61,7 +60,7 @@ class BaseHandler:
             if response:
                 return response
 
-        resolver = urlresolvers.RegexURLResolver(r'^/', ROOT_URLCONF)
+        resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
         try:
             callback, callback_args, callback_kwargs = resolver.resolve(path)
 
@@ -88,30 +87,23 @@ class BaseHandler:
                 raise ValueError, &quot;The view %s.%s didn't return an HttpResponse object.&quot; % (callback.__module__, callback.func_name)
 
             return response
-        except exceptions.Http404, e:
-            if DEBUG:
+        except http.Http404, e:
+            if settings.DEBUG:
                 return self.get_technical_error_response(request, is404=True, exception=e)
             else:
                 callback, param_dict = resolver.resolve404()
                 return callback(request, **param_dict)
-        except db.DatabaseError:
-            db.db.rollback()
-            if DEBUG:
-                return self.get_technical_error_response(request)
-            else:
-                subject = 'Database error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
-                message = &quot;%s\n\n%s&quot; % (self._get_traceback(), request)
-                mail_admins(subject, message, fail_silently=True)
-                return self.get_friendly_error_response(request, resolver)
         except exceptions.PermissionDenied:
-            return httpwrappers.HttpResponseForbidden('&lt;h1&gt;Permission denied&lt;/h1&gt;')
+            return http.HttpResponseForbidden('&lt;h1&gt;Permission denied&lt;/h1&gt;')
         except: # Handle everything else, including SuspiciousOperation, etc.
-            if DEBUG:
+            if settings.DEBUG:
                 return self.get_technical_error_response(request)
             else:
                 # Get the exception info now, in case another exception is thrown later.
                 exc_info = sys.exc_info()
-                subject = 'Coding error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
+                receivers = dispatcher.send(signal=signals.got_request_exception)
+                # When DEBUG is False, send an error message to the admins.
+                subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
                 try:
                     request_repr = repr(request)
                 except:
@@ -123,7 +115,7 @@ class BaseHandler:
     def get_friendly_error_response(self, request, resolver):
         &quot;&quot;&quot;
         Returns an HttpResponse that displays a PUBLIC error message for a
-        fundamental database or coding error.
+        fundamental error.
         &quot;&quot;&quot;
         from django.core import urlresolvers
         callback, param_dict = resolver.resolve500()
@@ -132,7 +124,7 @@ class BaseHandler:
     def get_technical_error_response(self, request, is404=False, exception=None):
         &quot;&quot;&quot;
         Returns an HttpResponse that displays a TECHNICAL error message for a
-        fundamental database or coding error.
+        fundamental error.
         &quot;&quot;&quot;
         from django.views import debug
         if is404:</diff>
      <filename>django/core/handlers/base.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,8 @@
 from django.core.handlers.base import BaseHandler
-from django.utils import datastructures, httpwrappers
+from django.core import signals
+from django.dispatch import dispatcher
+from django.utils import datastructures
+from django import http
 from pprint import pformat
 import os
 
@@ -7,15 +10,15 @@ import os
 # settings) until after ModPythonHandler has been called; otherwise os.environ
 # won't be set up correctly (with respect to settings).
 
-class ModPythonRequest(httpwrappers.HttpRequest):
+class ModPythonRequest(http.HttpRequest):
     def __init__(self, req):
         self._req = req
         self.path = req.uri
 
     def __repr__(self):
-        return '&lt;ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s,\nuser:%s&gt;' % \
+        return '&lt;ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s&gt;' % \
             (self.path, pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
-            pformat(self.META), pformat(self.user))
+            pformat(self.META))
 
     def get_full_path(self):
         return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
@@ -23,18 +26,18 @@ class ModPythonRequest(httpwrappers.HttpRequest):
     def _load_post_and_files(self):
         &quot;Populates self._post and self._files&quot;
         if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'):
-            self._post, self._files = httpwrappers.parse_file_upload(self._req.headers_in, self.raw_post_data)
+            self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
         else:
-            self._post, self._files = httpwrappers.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
+            self._post, self._files = http.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
 
     def _get_request(self):
         if not hasattr(self, '_request'):
-           self._request = datastructures.MergeDict(self.POST, self.GET)
+            self._request = datastructures.MergeDict(self.POST, self.GET)
         return self._request
 
     def _get_get(self):
         if not hasattr(self, '_get'):
-            self._get = httpwrappers.QueryDict(self._req.args)
+            self._get = http.QueryDict(self._req.args)
         return self._get
 
     def _set_get(self, get):
@@ -50,7 +53,7 @@ class ModPythonRequest(httpwrappers.HttpRequest):
 
     def _get_cookies(self):
         if not hasattr(self, '_cookies'):
-            self._cookies = httpwrappers.parse_cookie(self._req.headers_in.get('cookie', ''))
+            self._cookies = http.parse_cookie(self._req.headers_in.get('cookie', ''))
         return self._cookies
 
     def _set_cookies(self, cookies):
@@ -95,22 +98,6 @@ class ModPythonRequest(httpwrappers.HttpRequest):
             self._raw_post_data = self._req.read()
             return self._raw_post_data
 
-    def _get_user(self):
-        if not hasattr(self, '_user'):
-            from django.models.auth import users
-            try:
-                user_id = self.session[users.SESSION_KEY]
-                if not user_id:
-                    raise ValueError
-                self._user = users.get_object(pk=user_id)
-            except (AttributeError, KeyError, ValueError, users.UserDoesNotExist):
-                from django.parts.auth import anonymoususers
-                self._user = anonymoususers.AnonymousUser()
-        return self._user
-
-    def _set_user(self, user):
-        self._user = user
-
     GET = property(_get_get, _set_get)
     POST = property(_get_post, _set_post)
     COOKIES = property(_get_cookies, _set_cookies)
@@ -118,7 +105,6 @@ class ModPythonRequest(httpwrappers.HttpRequest):
     META = property(_get_meta)
     REQUEST = property(_get_request)
     raw_post_data = property(_get_raw_post_data)
-    user = property(_get_user, _set_user)
 
 class ModPythonHandler(BaseHandler):
     def __call__(self, req):
@@ -128,7 +114,6 @@ class ModPythonHandler(BaseHandler):
         # now that the environ works we can see the correct settings, so imports
         # that use settings now can work
         from django.conf import settings
-        from django.core import db
 
         if settings.ENABLE_PSYCO:
             import psyco
@@ -138,15 +123,17 @@ class ModPythonHandler(BaseHandler):
         if self._request_middleware is None:
             self.load_middleware()
 
+        dispatcher.send(signal=signals.request_started)
         try:
             request = ModPythonRequest(req)
             response = self.get_response(req.uri, request)
-        finally:
-            db.db.close()
 
-        # Apply response middleware
-        for middleware_method in self._response_middleware:
-            response = middleware_method(request, response)
+            # Apply response middleware
+            for middleware_method in self._response_middleware:
+                response = middleware_method(request, response)
+
+        finally:
+            dispatcher.send(signal=signals.request_finished)
 
         # Convert our custom HttpResponse object back into the mod_python req.
         populate_apache_request(response, req)</diff>
      <filename>django/core/handlers/modpython.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,8 @@
 from django.core.handlers.base import BaseHandler
-from django.utils import datastructures, httpwrappers
+from django.core import signals
+from django.dispatch import dispatcher
+from django.utils import datastructures
+from django import http
 from pprint import pformat
 
 # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
@@ -47,7 +50,7 @@ STATUS_CODE_TEXT = {
     505: 'HTTP VERSION NOT SUPPORTED',
 }
 
-class WSGIRequest(httpwrappers.HttpRequest):
+class WSGIRequest(http.HttpRequest):
     def __init__(self, environ):
         self.environ = environ
         self.path = environ['PATH_INFO']
@@ -60,7 +63,7 @@ class WSGIRequest(httpwrappers.HttpRequest):
             pformat(self.META))
 
     def get_full_path(self):
-        return '%s%s' % (self.path, self.environ['QUERY_STRING'] and ('?' + self.environ['QUERY_STRING']) or '')
+        return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
 
     def _load_post_and_files(self):
         # Populates self._post and self._files
@@ -68,21 +71,21 @@ class WSGIRequest(httpwrappers.HttpRequest):
             if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
                 header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
                 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
-                self._post, self._files = httpwrappers.parse_file_upload(header_dict, self.raw_post_data)
+                self._post, self._files = http.parse_file_upload(header_dict, self.raw_post_data)
             else:
-                self._post, self._files = httpwrappers.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
+                self._post, self._files = http.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
         else:
-            self._post, self._files = httpwrappers.QueryDict(''), datastructures.MultiValueDict()
+            self._post, self._files = http.QueryDict(''), datastructures.MultiValueDict()
 
     def _get_request(self):
         if not hasattr(self, '_request'):
-           self._request = datastructures.MergeDict(self.POST, self.GET)
+            self._request = datastructures.MergeDict(self.POST, self.GET)
         return self._request
 
     def _get_get(self):
         if not hasattr(self, '_get'):
             # The WSGI spec says 'QUERY_STRING' may be absent.
-            self._get = httpwrappers.QueryDict(self.environ.get('QUERY_STRING', ''))
+            self._get = http.QueryDict(self.environ.get('QUERY_STRING', ''))
         return self._get
 
     def _set_get(self, get):
@@ -98,7 +101,7 @@ class WSGIRequest(httpwrappers.HttpRequest):
 
     def _get_cookies(self):
         if not hasattr(self, '_cookies'):
-            self._cookies = httpwrappers.parse_cookie(self.environ.get('HTTP_COOKIE', ''))
+            self._cookies = http.parse_cookie(self.environ.get('HTTP_COOKIE', ''))
         return self._cookies
 
     def _set_cookies(self, cookies):
@@ -116,34 +119,16 @@ class WSGIRequest(httpwrappers.HttpRequest):
             self._raw_post_data = self.environ['wsgi.input'].read(int(self.environ[&quot;CONTENT_LENGTH&quot;]))
             return self._raw_post_data
 
-    def _get_user(self):
-        if not hasattr(self, '_user'):
-            from django.models.auth import users
-            try:
-                user_id = self.session[users.SESSION_KEY]
-                if not user_id:
-                    raise ValueError
-                self._user = users.get_object(pk=user_id)
-            except (AttributeError, KeyError, ValueError, users.UserDoesNotExist):
-                from django.parts.auth import anonymoususers
-                self._user = anonymoususers.AnonymousUser()
-        return self._user
-
-    def _set_user(self, user):
-        self._user = user
-
     GET = property(_get_get, _set_get)
     POST = property(_get_post, _set_post)
     COOKIES = property(_get_cookies, _set_cookies)
     FILES = property(_get_files)
     REQUEST = property(_get_request)
     raw_post_data = property(_get_raw_post_data)
-    user = property(_get_user, _set_user)
 
 class WSGIHandler(BaseHandler):
     def __call__(self, environ, start_response):
         from django.conf import settings
-        from django.core import db
 
         if settings.ENABLE_PSYCO:
             import psyco
@@ -154,15 +139,17 @@ class WSGIHandler(BaseHandler):
         if self._request_middleware is None:
             self.load_middleware()
 
+        dispatcher.send(signal=signals.request_started)
         try:
             request = WSGIRequest(environ)
             response = self.get_response(request.path, request)
-        finally:
-            db.db.close()
 
-        # Apply response middleware
-        for middleware_method in self._response_middleware:
-            response = middleware_method(request, response)
+            # Apply response middleware
+            for middleware_method in self._response_middleware:
+                response = middleware_method(request, response)
+
+        finally:
+            dispatcher.send(signal=signals.request_finished)
 
         try:
             status_text = STATUS_CODE_TEXT[response.status_code]</diff>
      <filename>django/core/handlers/wsgi.py</filename>
    </modified>
    <modified>
      <diff>@@ -46,9 +46,18 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST
         msg['Subject'] = subject
         msg['From'] = from_email
         msg['To'] = ', '.join(recipient_list)
-        server.sendmail(from_email, recipient_list, msg.as_string())
-        num_sent += 1
-    server.quit()
+        try:
+            server.sendmail(from_email, recipient_list, msg.as_string())
+            num_sent += 1
+        except:
+            if not fail_silently:
+                raise
+    try:
+        server.quit()
+    except:
+        if fail_silently:
+            return
+        raise
     return num_sent
 
 def mail_admins(subject, message, fail_silently=False):</diff>
      <filename>django/core/mail.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,10 @@
 # development-server initialization.
 
 import django
-import os, re, sys, textwrap
+from django.core.exceptions import ImproperlyConfigured
+import os, re, shutil, sys, textwrap
 from optparse import OptionParser
+from django.utils import termcolors
 
 # For Python 2.3
 if not hasattr(__builtins__, 'set'):
@@ -17,7 +19,7 @@ MODULE_TEMPLATE = '''    {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(cha
     &lt;/tr&gt;
     {%% endif %%}'''
 
-APP_ARGS = '[modelmodule ...]'
+APP_ARGS = '[appname ...]'
 
 # Use django.__path__[0] because we don't know which directory django into
 # which has been installed.
@@ -25,38 +27,46 @@ PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
 
 INVALID_PROJECT_NAMES = ('django', 'test')
 
-def _get_packages_insert(app_label):
-    from django.core.db import db
-    return &quot;INSERT INTO %s (%s, %s) VALUES ('%s', '%s');&quot; % \
-        (db.quote_name('packages'), db.quote_name('label'), db.quote_name('name'),
-        app_label, app_label)
-
-def _get_permission_codename(action, opts):
-    return '%s_%s' % (action, opts.object_name.lower())
-
-def _get_all_permissions(opts):
-    &quot;Returns (codename, name) for all permissions in the given opts.&quot;
-    perms = []
-    if opts.admin:
-        for action in ('add', 'change', 'delete'):
-            perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name)))
-    return perms + list(opts.permissions)
-
-def _get_permission_insert(name, codename, opts):
-    from django.core.db import db
-    return &quot;INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');&quot; % \
-        (db.quote_name('auth_permissions'), db.quote_name('name'), db.quote_name('package'),
-        db.quote_name('codename'), name.replace(&quot;'&quot;, &quot;''&quot;), opts.app_label, codename)
-
-def _get_contenttype_insert(opts):
-    from django.core.db import db
-    return &quot;INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');&quot; % \
-        (db.quote_name('content_types'), db.quote_name('name'), db.quote_name('package'),
-        db.quote_name('python_module_name'), opts.verbose_name, opts.app_label, opts.module_name)
+# Set up the terminal color scheme.
+class dummy: pass
+style = dummy()
+style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
+style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
+style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
+style.SQL_COLTYPE = termcolors.make_style(fg='green')
+style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
+style.SQL_TABLE = termcolors.make_style(opts=('bold',))
+del dummy
+
+def disable_termcolors():
+    class dummy:
+        def __getattr__(self, attr):
+            return lambda x: x
+    global style
+    style = dummy()
+
+# Disable terminal coloring if somebody's piping the output.
+if (not sys.stdout.isatty()) or (sys.platform == 'win32'):
+    disable_termcolors()
 
 def _is_valid_dir_name(s):
     return bool(re.search(r'^\w+$', s))
 
+def _get_installed_models(table_list):
+    &quot;Gets a set of all models that are installed, given a list of existing tables&quot;
+    from django.db import models
+    all_models = []
+    for app in models.get_apps():
+        for model in models.get_models(app):
+            all_models.append(model)
+    return set([m for m in all_models if m._meta.db_table in table_list])
+
+def _get_table_list():
+    &quot;Gets a list of all db tables that are physically installed.&quot;
+    from django.db import connection, get_introspection_module
+    cursor = connection.cursor()
+    return get_introspection_module().get_table_list(cursor)
+
 # If the foreign key points to an AutoField, a PositiveIntegerField or a
 # PositiveSmallIntegerField, the foreign key should be an IntegerField, not the
 # referred field type. Otherwise, the foreign key should be the same type of
@@ -67,304 +77,429 @@ def get_version():
     &quot;Returns the version as a human-format string.&quot;
     from django import VERSION
     v = '.'.join([str(i) for i in VERSION[:-1]])
-    if VERSION[3]:
-        v += ' (%s)' % VERSION[3]
+    if VERSION[-1]:
+        v += ' (%s)' % VERSION[-1]
     return v
 
-def get_sql_create(mod):
-    &quot;Returns a list of the CREATE TABLE SQL statements for the given module.&quot;
-    from django.core import db, meta
+def get_sql_create(app):
+    &quot;Returns a list of the CREATE TABLE SQL statements for the given app.&quot;
+    from django.db import get_creation_module, models
+    data_types = get_creation_module().DATA_TYPES
+
+    if not data_types:
+        # This must be the &quot;dummy&quot; database backend, which means the user
+        # hasn't set DATABASE_ENGINE.
+        sys.stderr.write(style.ERROR(&quot;Error: Django doesn't know which syntax to use for your SQL statements,\n&quot; +
+            &quot;because you haven't specified the DATABASE_ENGINE setting.\n&quot; +
+            &quot;Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n&quot;))
+        sys.exit(1)
+
+    # Get installed models, so we generate REFERENCES right
+    installed_models = _get_installed_models(_get_table_list())
+
     final_output = []
-    for klass in mod._MODELS:
-        opts = klass._meta
-        table_output = []
-        for f in opts.fields:
-            if isinstance(f, meta.ForeignKey):
-                rel_field = f.rel.get_related_field()
-                data_type = get_rel_data_type(rel_field)
-            else:
-                rel_field = f
-                data_type = f.get_internal_type()
-            col_type = db.DATA_TYPES[data_type]
-            if col_type is not None:
-                field_output = [db.db.quote_name(f.column), col_type % rel_field.__dict__]
-                field_output.append('%sNULL' % (not f.null and 'NOT ' or ''))
-                if f.unique:
-                    field_output.append('UNIQUE')
-                if f.primary_key:
-                    field_output.append('PRIMARY KEY')
-                if f.rel:
-                    field_output.append('REFERENCES %s (%s)' % \
-                        (db.db.quote_name(f.rel.to.db_table),
-                        db.db.quote_name(f.rel.to.get_field(f.rel.field_name).column)))
-                table_output.append(' '.join(field_output))
-        if opts.order_with_respect_to:
-            table_output.append('%s %s NULL' % (db.db.quote_name('_order'), db.DATA_TYPES['IntegerField']))
-        for field_constraints in opts.unique_together:
-            table_output.append('UNIQUE (%s)' % \
-                &quot;, &quot;.join([db.db.quote_name(opts.get_field(f).column) for f in field_constraints]))
-
-        full_statement = ['CREATE TABLE %s (' % db.db.quote_name(opts.db_table)]
-        for i, line in enumerate(table_output): # Combine and add commas.
-            full_statement.append('    %s%s' % (line, i &lt; len(table_output)-1 and ',' or ''))
-        full_statement.append(');')
-        final_output.append('\n'.join(full_statement))
-
-    for klass in mod._MODELS:
-        opts = klass._meta
-        for f in opts.many_to_many:
-            table_output = ['CREATE TABLE %s (' % db.db.quote_name(f.get_m2m_db_table(opts))]
-            table_output.append('    %s %s NOT NULL PRIMARY KEY,' % (db.db.quote_name('id'), db.DATA_TYPES['AutoField']))
-            table_output.append('    %s %s NOT NULL REFERENCES %s (%s),' % \
-                (db.db.quote_name(opts.object_name.lower() + '_id'),
-                db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__,
-                db.db.quote_name(opts.db_table),
-                db.db.quote_name(opts.pk.column)))
-            table_output.append('    %s %s NOT NULL REFERENCES %s (%s),' % \
-                (db.db.quote_name(f.rel.to.object_name.lower() + '_id'),
-                db.DATA_TYPES[get_rel_data_type(f.rel.to.pk)] % f.rel.to.pk.__dict__,
-                db.db.quote_name(f.rel.to.db_table),
-                db.db.quote_name(f.rel.to.pk.column)))
-            table_output.append('    UNIQUE (%s, %s)' % \
-                (db.db.quote_name(opts.object_name.lower() + '_id'),
-                db.db.quote_name(f.rel.to.object_name.lower() + '_id')))
-            table_output.append(');')
-            final_output.append('\n'.join(table_output))
+    models_output = set(installed_models)
+    pending_references = {}
+
+    app_models = models.get_models(app)
+
+    for klass in app_models:
+        output, references = _get_sql_model_create(klass, models_output)
+        final_output.extend(output)
+        pending_references.update(references)
+        final_output.extend(_get_sql_for_pending_references(klass, pending_references))
+        # Keep track of the fact that we've created the table for this model.
+        models_output.add(klass)
+
+    # Create the many-to-many join tables.
+    for klass in app_models:
+        final_output.extend(_get_many_to_many_sql_for_model(klass))
+
+    # Handle references to tables that are from other apps
+    # but don't exist physically
+    not_installed_models = set(pending_references.keys())
+    if not_installed_models:
+        final_output.append('-- The following references should be added but depend on non-existant tables:')
+        for klass in not_installed_models:
+            final_output.extend(['-- ' + sql for sql in
+                _get_sql_for_pending_references(klass, pending_references)])
+
     return final_output
-get_sql_create.help_doc = &quot;Prints the CREATE TABLE SQL statements for the given model module name(s).&quot;
+get_sql_create.help_doc = &quot;Prints the CREATE TABLE SQL statements for the given app name(s).&quot;
 get_sql_create.args = APP_ARGS
 
-def get_sql_delete(mod):
-    &quot;Returns a list of the DROP TABLE SQL statements for the given module.&quot;
-    from django.core import db
+def _get_sql_model_create(klass, models_already_seen=set()):
+    &quot;&quot;&quot;
+    Get the SQL required to create a single model.
+
+    Returns list_of_sql, pending_references_dict
+    &quot;&quot;&quot;
+    from django.db import backend, get_creation_module, models
+    data_types = get_creation_module().DATA_TYPES
+
+    opts = klass._meta
+    final_output = []
+    table_output = []
+    pending_references = {}
+    for f in opts.fields:
+        if isinstance(f, models.ForeignKey):
+            rel_field = f.rel.get_related_field()
+            data_type = get_rel_data_type(rel_field)
+        else:
+            rel_field = f
+            data_type = f.get_internal_type()
+        col_type = data_types[data_type]
+        if col_type is not None:
+            # Make the definition (e.g. 'foo VARCHAR(30)') for this field.
+            field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
+                style.SQL_COLTYPE(col_type % rel_field.__dict__)]
+            field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
+            if f.unique:
+                field_output.append(style.SQL_KEYWORD('UNIQUE'))
+            if f.primary_key:
+                field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
+            if f.rel:
+                if f.rel.to in models_already_seen:
+                    field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
+                        style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
+                        style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')'
+                    )
+                else:
+                    # We haven't yet created the table to which this field
+                    # is related, so save it for later.
+                    pr = pending_references.setdefault(f.rel.to, []).append((klass, f))
+            table_output.append(' '.join(field_output))
+    if opts.order_with_respect_to:
+        table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \
+            style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \
+            style.SQL_KEYWORD('NULL'))
+    for field_constraints in opts.unique_together:
+        table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \
+            &quot;, &quot;.join([backend.quote_name(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints]))
+
+    full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(backend.quote_name(opts.db_table)) + ' (']
+    for i, line in enumerate(table_output): # Combine and add commas.
+        full_statement.append('    %s%s' % (line, i &lt; len(table_output)-1 and ',' or ''))
+    full_statement.append(');')
+    final_output.append('\n'.join(full_statement))
+
+    return final_output, pending_references
+
+def _get_sql_for_pending_references(klass, pending_references):
+    &quot;&quot;&quot;
+    Get any ALTER TABLE statements to add constraints after the fact.
+    &quot;&quot;&quot;
+    from django.db import backend, get_creation_module
+    data_types = get_creation_module().DATA_TYPES
+
+    final_output = []
+    if backend.supports_constraints:
+        opts = klass._meta
+        if klass in pending_references:
+            for rel_class, f in pending_references[klass]:
+                rel_opts = rel_class._meta
+                r_table = rel_opts.db_table
+                r_col = f.column
+                table = opts.db_table
+                col = opts.get_field(f.rel.field_name).column
+                final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
+                    (backend.quote_name(r_table),
+                    backend.quote_name('%s_referencing_%s_%s' % (r_col, table, col)),
+                    backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
+            del pending_references[klass]
+    return final_output
+
+def _get_many_to_many_sql_for_model(klass):
+    from django.db import backend, get_creation_module
+    data_types = get_creation_module().DATA_TYPES
+
+    opts = klass._meta
+    final_output = []
+    for f in opts.many_to_many:
+        table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
+            style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
+        table_output.append('    %s %s %s,' % \
+            (style.SQL_FIELD(backend.quote_name('id')),
+            style.SQL_COLTYPE(data_types['AutoField']),
+            style.SQL_KEYWORD('NOT NULL PRIMARY KEY')))
+        table_output.append('    %s %s %s %s (%s),' % \
+            (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
+            style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
+            style.SQL_KEYWORD('NOT NULL REFERENCES'),
+            style.SQL_TABLE(backend.quote_name(opts.db_table)),
+            style.SQL_FIELD(backend.quote_name(opts.pk.column))))
+        table_output.append('    %s %s %s %s (%s),' % \
+            (style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
+            style.SQL_COLTYPE(data_types[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__),
+            style.SQL_KEYWORD('NOT NULL REFERENCES'),
+            style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
+            style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column))))
+        table_output.append('    %s (%s, %s)' % \
+            (style.SQL_KEYWORD('UNIQUE'),
+            style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
+            style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name()))))
+        table_output.append(');')
+        final_output.append('\n'.join(table_output))
+    return final_output
+
+def get_sql_delete(app):
+    &quot;Returns a list of the DROP TABLE SQL statements for the given app.&quot;
+    from django.db import backend, connection, models, get_introspection_module
+    introspection = get_introspection_module()
+
+    # This should work even if a connecton isn't available
     try:
-        cursor = db.db.cursor()
+        cursor = connection.cursor()
     except:
         cursor = None
 
-    # Determine whether the admin log table exists. It only exists if the
-    # person has installed the admin app.
-    try:
-        if cursor is not None:
-            # Check whether the table exists.
-            cursor.execute(&quot;SELECT 1 FROM %s LIMIT 1&quot; % db.db.quote_name('django_admin_log'))
-    except:
-        # The table doesn't exist, so it doesn't need to be dropped.
-        db.db.rollback()
-        admin_log_exists = False
+    # Figure out which tables already exist
+    if cursor:
+        table_names = introspection.get_table_list(cursor)
     else:
-        admin_log_exists = True
+        table_names = []
 
     output = []
 
     # Output DROP TABLE statements for standard application tables.
-    for klass in mod._MODELS:
-        try:
-            if cursor is not None:
-                # Check whether the table exists.
-                cursor.execute(&quot;SELECT 1 FROM %s LIMIT 1&quot; % db.db.quote_name(klass._meta.db_table))
-        except:
-            # The table doesn't exist, so it doesn't need to be dropped.
-            db.db.rollback()
-        else:
-            output.append(&quot;DROP TABLE %s;&quot; % db.db.quote_name(klass._meta.db_table))
+    to_delete = set()
+
+    references_to_delete = {}
+    app_models = models.get_models(app)
+    for klass in app_models:
+        if cursor and klass._meta.db_table in table_names:
+            # The table exists, so it needs to be dropped
+            opts = klass._meta
+            for f in opts.fields:
+                if f.rel and f.rel.to not in to_delete:
+                    references_to_delete.setdefault(f.rel.to, []).append( (klass, f) )
+
+            to_delete.add(klass)
+
+    for klass in app_models:
+        if cursor and klass._meta.db_table in table_names:
+            # Drop the table now
+            output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
+                style.SQL_TABLE(backend.quote_name(klass._meta.db_table))))
+            if backend.supports_constraints and references_to_delete.has_key(klass):
+                for rel_class, f in references_to_delete[klass]:
+                    table = rel_class._meta.db_table
+                    col = f.column
+                    r_table = klass._meta.db_table
+                    r_col = klass._meta.get_field(f.rel.field_name).column
+                    output.append('%s %s %s %s;' % \
+                        (style.SQL_KEYWORD('ALTER TABLE'),
+                        style.SQL_TABLE(backend.quote_name(table)),
+                        style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
+                        style.SQL_FIELD(backend.quote_name(&quot;%s_referencing_%s_%s&quot; % (col, r_table, r_col)))))
+                del references_to_delete[klass]
 
     # Output DROP TABLE statements for many-to-many tables.
-    for klass in mod._MODELS:
+    for klass in app_models:
         opts = klass._meta
         for f in opts.many_to_many:
-            try:
-                if cursor is not None:
-                    cursor.execute(&quot;SELECT 1 FROM %s LIMIT 1&quot; % db.db.quote_name(f.get_m2m_db_table(opts)))
-            except:
-                db.db.rollback()
-            else:
-                output.append(&quot;DROP TABLE %s;&quot; % db.db.quote_name(f.get_m2m_db_table(opts)))
-
-    app_label = mod._MODELS[0]._meta.app_label
-
-    # Delete from packages, auth_permissions, content_types.
-    output.append(&quot;DELETE FROM %s WHERE %s = '%s';&quot; % \
-        (db.db.quote_name('packages'), db.db.quote_name('label'), app_label))
-    output.append(&quot;DELETE FROM %s WHERE %s = '%s';&quot; % \
-        (db.db.quote_name('auth_permissions'), db.db.quote_name('package'), app_label))
-    output.append(&quot;DELETE FROM %s WHERE %s = '%s';&quot; % \
-        (db.db.quote_name('content_types'), db.db.quote_name('package'), app_label))
-
-    # Delete from the admin log.
-    if cursor is not None:
-        cursor.execute(&quot;SELECT %s FROM %s WHERE %s = %%s&quot; % \
-            (db.db.quote_name('id'), db.db.quote_name('content_types'),
-            db.db.quote_name('package')), [app_label])
-        if admin_log_exists:
-            for row in cursor.fetchall():
-                output.append(&quot;DELETE FROM %s WHERE %s = %s;&quot; % \
-                    (db.db.quote_name('django_admin_log'), db.db.quote_name('content_type_id'), row[0]))
+            if cursor and f.m2m_db_table() in table_names:
+                output.append(&quot;%s %s;&quot; % (style.SQL_KEYWORD('DROP TABLE'),
+                    style.SQL_TABLE(backend.quote_name(f.m2m_db_table()))))
+
+    app_label = app_models[0]._meta.app_label
 
     # Close database connection explicitly, in case this output is being piped
     # directly into a database client, to avoid locking issues.
-    if cursor is not None:
+    if cursor:
         cursor.close()
-        db.db.close()
+        connection.close()
 
     return output[::-1] # Reverse it, to deal with table dependencies.
-get_sql_delete.help_doc = &quot;Prints the DROP TABLE SQL statements for the given model module name(s).&quot;
+get_sql_delete.help_doc = &quot;Prints the DROP TABLE SQL statements for the given app name(s).&quot;
 get_sql_delete.args = APP_ARGS
 
-def get_sql_reset(mod):
+def get_sql_reset(app):
     &quot;Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module.&quot;
-    return get_sql_delete(mod) + get_sql_all(mod)
-get_sql_reset.help_doc = &quot;Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given model module name(s).&quot;
+    return get_sql_delete(app) + get_sql_all(app)
+get_sql_reset.help_doc = &quot;Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s).&quot;
 get_sql_reset.args = APP_ARGS
 
-def get_sql_initial_data(mod):
-    &quot;Returns a list of the initial INSERT SQL statements for the given module.&quot;
-    from django.core import db
+def get_sql_initial_data_for_model(model):
+    from django.db import models
+    from django.conf import settings
+
+    opts = model._meta
+    app_dir = os.path.normpath(os.path.join(os.path.dirname(models.get_app(model._meta.app_label).__file__), 'sql'))
     output = []
-    app_label = mod._MODELS[0]._meta.app_label
-    output.append(_get_packages_insert(app_label))
-    app_dir = os.path.normpath(os.path.join(os.path.dirname(mod.__file__), '..', 'sql'))
-    for klass in mod._MODELS:
-        opts = klass._meta
 
-        # Add custom SQL, if it's available.
-        sql_files = [os.path.join(app_dir, opts.module_name + '.' + db.DATABASE_ENGINE +  '.sql'),
-                     os.path.join(app_dir, opts.module_name + '.sql')]
-        for sql_file in sql_files:
-            if os.path.exists(sql_file):
-                fp = open(sql_file)
-                output.append(fp.read())
-                fp.close()
-
-        # Content types.
-        output.append(_get_contenttype_insert(opts))
-        # Permissions.
-        for codename, name in _get_all_permissions(opts):
-            output.append(_get_permission_insert(name, codename, opts))
+    # Find custom SQL, if it's available.
+    sql_files = [os.path.join(app_dir, &quot;%s.%s.sql&quot; % (opts.object_name.lower(), settings.DATABASE_ENGINE)),
+                 os.path.join(app_dir, &quot;%s.sql&quot; % opts.object_name.lower())]
+    for sql_file in sql_files:
+        if os.path.exists(sql_file):
+            fp = open(sql_file)
+            output.append(fp.read())
+            fp.close()
+
+    return output
+
+def get_sql_initial_data(app):
+    &quot;Returns a list of the initial INSERT SQL statements for the given app.&quot;
+    from django.db.models import get_models
+    output = []
+
+    app_models = get_models(app)
+    app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
+
+    for klass in app_models:
+        output.extend(get_sql_initial_data_for_model(klass))
+
     return output
-get_sql_initial_data.help_doc = &quot;Prints the initial INSERT SQL statements for the given model module name(s).&quot;
+get_sql_initial_data.help_doc = &quot;Prints the initial INSERT SQL statements for the given app name(s).&quot;
 get_sql_initial_data.args = APP_ARGS
 
-def get_sql_sequence_reset(mod):
-    &quot;Returns a list of the SQL statements to reset PostgreSQL sequences for the given module.&quot;
-    from django.core import db, meta
+def get_sql_sequence_reset(app):
+    &quot;Returns a list of the SQL statements to reset PostgreSQL sequences for the given app.&quot;
+    from django.db import backend, models
     output = []
-    for klass in mod._MODELS:
+    for klass in models.get_models(app):
         for f in klass._meta.fields:
-            if isinstance(f, meta.AutoField):
-                output.append(&quot;SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));&quot; % \
-                    (klass._meta.db_table, f.column, db.db.quote_name(f.column),
-                    db.db.quote_name(klass._meta.db_table)))
+            if isinstance(f, models.AutoField):
+                output.append(&quot;%s setval('%s', (%s max(%s) %s %s));&quot; % \
+                    (style.SQL_KEYWORD('SELECT'),
+                    style.SQL_FIELD('%s_%s_seq' % (klass._meta.db_table, f.column)),
+                    style.SQL_KEYWORD('SELECT'),
+                    style.SQL_FIELD(backend.quote_name(f.column)),
+                    style.SQL_KEYWORD('FROM'),
+                    style.SQL_TABLE(backend.quote_name(klass._meta.db_table))))
+                break # Only one AutoField is allowed per model, so don't bother continuing.
         for f in klass._meta.many_to_many:
-            output.append(&quot;SELECT setval('%s_id_seq', (SELECT max(%s) FROM %s));&quot; % \
-                (f.get_m2m_db_table(klass._meta), db.db.quote_name('id'), f.get_m2m_db_table(klass._meta)))
+            output.append(&quot;%s setval('%s', (%s max(%s) %s %s));&quot; % \
+                (style.SQL_KEYWORD('SELECT'),
+                style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
+                style.SQL_KEYWORD('SELECT'),
+                style.SQL_FIELD(backend.quote_name('id')),
+                style.SQL_KEYWORD('FROM'),
+                style.SQL_TABLE(f.m2m_db_table())))
     return output
-get_sql_sequence_reset.help_doc = &quot;Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s).&quot;
+get_sql_sequence_reset.help_doc = &quot;Prints the SQL statements for resetting PostgreSQL sequences for the given app name(s).&quot;
 get_sql_sequence_reset.args = APP_ARGS
 
-def get_sql_indexes(mod):
-    &quot;Returns a list of the CREATE INDEX SQL statements for the given module.&quot;
-    from django.core.db import db
+def get_sql_indexes(app):
+    &quot;Returns a list of the CREATE INDEX SQL statements for the given app.&quot;
+    from django.db import backend, models
     output = []
-    for klass in mod._MODELS:
+
+    for klass in models.get_models(app):
         for f in klass._meta.fields:
             if f.db_index:
-                unique = f.unique and &quot;UNIQUE &quot; or &quot;&quot;
-                output.append(&quot;CREATE %sINDEX %s_%s ON %s (%s);&quot; % \
-                    (unique, klass._meta.db_table, f.column,
-                    db.quote_name(klass._meta.db_table), db.quote_name(f.column)))
+                unique = f.unique and 'UNIQUE ' or ''
+                output.append(
+                    style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
+                    style.SQL_TABLE('%s_%s' % (klass._meta.db_table, f.column)) + ' ' + \
+                    style.SQL_KEYWORD('ON') + ' ' + \
+                    style.SQL_TABLE(backend.quote_name(klass._meta.db_table)) + ' ' + \
+                    &quot;(%s);&quot; % style.SQL_FIELD(backend.quote_name(f.column))
+                )
     return output
 get_sql_indexes.help_doc = &quot;Prints the CREATE INDEX SQL statements for the given model module name(s).&quot;
 get_sql_indexes.args = APP_ARGS
 
-def get_sql_all(mod):
-    &quot;Returns a list of CREATE TABLE SQL and initial-data insert for the given module.&quot;
-    return get_sql_create(mod) + get_sql_initial_data(mod)
-get_sql_all.help_doc = &quot;Prints the CREATE TABLE and initial-data SQL statements for the given model module name(s).&quot;
+def get_sql_all(app):
+    &quot;Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module.&quot;
+    return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app)
+get_sql_all.help_doc = &quot;Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s).&quot;
 get_sql_all.args = APP_ARGS
 
-def has_no_records(cursor):
-    &quot;Returns True if the cursor, having executed a query, returned no records.&quot;
-    # This is necessary due to an inconsistency in the DB-API spec.
-    # cursor.rowcount can be -1 (undetermined), according to
-    # http://www.python.org/peps/pep-0249.html
-    if cursor.rowcount &lt; 0:
-        return cursor.fetchone() is None
-    return cursor.rowcount &lt; 1
-
-def database_check(mod):
-    &quot;Checks that everything is properly installed in the database for the given module.&quot;
-    from django.core import db
-    cursor = db.db.cursor()
-    app_label = mod._MODELS[0]._meta.app_label
-
-    # Check that the package exists in the database.
-    cursor.execute(&quot;SELECT 1 FROM %s WHERE %s = %%s&quot; % \
-        (db.db.quote_name('packages'), db.db.quote_name('label')), [app_label])
-    if has_no_records(cursor):
-#         sys.stderr.write(&quot;The '%s' package isn't installed.\n&quot; % app_label)
-        print _get_packages_insert(app_label)
-
-    # Check that the permissions and content types are in the database.
-    perms_seen = {}
-    contenttypes_seen = {}
-    for klass in mod._MODELS:
-        opts = klass._meta
-        perms = _get_all_permissions(opts)
-        perms_seen.update(dict(perms))
-        contenttypes_seen[opts.module_name] = 1
-        for codename, name in perms:
-            cursor.execute(&quot;SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s&quot; % \
-                (db.db.quote_name('auth_permissions'), db.db.quote_name('package'),
-                db.db.quote_name('codename')), (app_label, codename))
-            if has_no_records(cursor):
-#                 sys.stderr.write(&quot;The '%s.%s' permission doesn't exist.\n&quot; % (app_label, codename))
-                print _get_permission_insert(name, codename, opts)
-        cursor.execute(&quot;SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s&quot; % \
-            (db.db.quote_name('content_types'), db.db.quote_name('package'),
-            db.db.quote_name('python_module_name')), (app_label, opts.module_name))
-        if has_no_records(cursor):
-#             sys.stderr.write(&quot;The '%s.%s' content type doesn't exist.\n&quot; % (app_label, opts.module_name))
-            print _get_contenttype_insert(opts)
-
-    # Check that there aren't any *extra* permissions in the DB that the model
-    # doesn't know about.
-    cursor.execute(&quot;SELECT %s FROM %s WHERE %s = %%s&quot; % \
-        (db.db.quote_name('codename'), db.db.quote_name('auth_permissions'),
-        db.db.quote_name('package')), (app_label,))
-    for row in cursor.fetchall():
-        try:
-            perms_seen[row[0]]
-        except KeyError:
-#             sys.stderr.write(&quot;A permission called '%s.%s' was found in the database but not in the model.\n&quot; % (app_label, row[0]))
-            print &quot;DELETE FROM %s WHERE %s='%s' AND %s = '%s';&quot; % \
-                (db.db.quote_name('auth_permissions'), db.db.quote_name('package'),
-                app_label, db.db.quote_name('codename'), row[0])
-
-    # Check that there aren't any *extra* content types in the DB that the
-    # model doesn't know about.
-    cursor.execute(&quot;SELECT %s FROM %s WHERE %s = %%s&quot; % \
-        (db.db.quote_name('python_module_name'), db.db.quote_name('content_types'),
-        db.db.quote_name('package')), (app_label,))
-    for row in cursor.fetchall():
+def syncdb():
+    &quot;Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created.&quot;
+    from django.db import connection, transaction, models, get_creation_module
+    from django.db.models import signals
+    from django.conf import settings
+    from django.dispatch import dispatcher
+
+    disable_termcolors()
+
+    # First, try validating the models.
+    _check_for_validation_errors()
+
+    # Import the 'management' module within each installed app, to register
+    # dispatcher events.
+    for app_name in settings.INSTALLED_APPS:
         try:
-            contenttypes_seen[row[0]]
-        except KeyError:
-#             sys.stderr.write(&quot;A content type called '%s.%s' was found in the database but not in the model.\n&quot; % (app_label, row[0]))
-            print &quot;DELETE FROM %s WHERE %s='%s' AND %s = '%s';&quot; % \
-                (db.db.quote_name('content_types'), db.db.quote_name('package'),
-                app_label, db.db.quote_name('python_module_name'), row[0])
-database_check.help_doc = &quot;Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed.&quot;
-database_check.args = APP_ARGS
-
-def get_admin_index(mod):
-    &quot;Returns admin-index template snippet (in list form) for the given module.&quot;
+            __import__(app_name + '.management', '', '', [''])
+        except ImportError:
+            pass
+
+    data_types = get_creation_module().DATA_TYPES
+
+    cursor = connection.cursor()
+
+    # Get a list of all existing database tables,
+    # so we know what needs to be added.
+    table_list = _get_table_list()
+
+    # Get a list of already installed *models* so that references work right.
+    seen_models = _get_installed_models(table_list)
+    created_models = set()
+    pending_references = {}
+
+    for app in models.get_apps():
+        model_list = models.get_models(app)
+        for model in model_list:
+            # Create the model's database table, if it doesn't already exist.
+            if model._meta.db_table in table_list:
+                continue
+            sql, references = _get_sql_model_create(model, seen_models)
+            seen_models.add(model)
+            created_models.add(model)
+            pending_references.update(references)
+            sql.extend(_get_sql_for_pending_references(model, pending_references))
+            print &quot;Creating table %s&quot; % model._meta.db_table
+            for statement in sql:
+                cursor.execute(statement)
+
+        for model in model_list:
+            if model in created_models:
+                sql = _get_many_to_many_sql_for_model(model)
+                if sql:
+                    print &quot;Creating many-to-many tables for %s model&quot; % model.__name__
+                    for statement in sql:
+                        cursor.execute(statement)
+
+        transaction.commit_unless_managed()
+
+    # Send the post_syncdb signal, so individual apps can do whatever they need
+    # to do at this point.
+    for app in models.get_apps():
+        dispatcher.send(signal=signals.post_syncdb, sender=app,
+            app=app, created_models=created_models)
+
+        # Install initial data for the app (but only if this is a model we've
+        # just created)
+        for model in models.get_models(app):
+            if model in created_models:
+                initial_sql = get_sql_initial_data_for_model(model)
+                if initial_sql:
+                    print &quot;Installing initial data for %s model&quot; % model._meta.object_name
+                    try:
+                        for sql in initial_sql:
+                            cursor.execute(sql)
+                    except Exception, e:
+                        sys.stderr.write(&quot;Failed to install initial SQL data for %s model: %s&quot; % \
+                                            (model._meta.object_name, e))
+                        transaction.rollback_unless_managed()
+                    else:
+                        transaction.commit_unless_managed()
+
+syncdb.args = ''
+
+def get_admin_index(app):
+    &quot;Returns admin-index template snippet (in list form) for the given app.&quot;
     from django.utils.text import capfirst
+    from django.db.models import get_models
     output = []
-    app_label = mod._MODELS[0]._meta.app_label
+    app_models = get_models(app)
+    app_label = app_models[0]._meta.app_label
     output.append('{%% if perms.%s %%}' % app_label)
     output.append('&lt;div class=&quot;module&quot;&gt;&lt;h2&gt;%s&lt;/h2&gt;&lt;table&gt;' % app_label.title())
-    for klass in mod._MODELS:
+    for klass in app_models:
         if klass._meta.admin:
             output.append(MODULE_TEMPLATE % {
                 'app': app_label,
@@ -376,97 +511,114 @@ def get_admin_index(mod):
     output.append('&lt;/table&gt;&lt;/div&gt;')
     output.append('{% endif %}')
     return output
-get_admin_index.help_doc = &quot;Prints the admin-index template snippet for the given model module name(s).&quot;
+get_admin_index.help_doc = &quot;Prints the admin-index template snippet for the given app name(s).&quot;
 get_admin_index.args = APP_ARGS
 
-def init():
-    &quot;Initializes the database with auth and core.&quot;
-    try:
-        from django.core import db, meta
-        auth = meta.get_app('auth')
-        core = meta.get_app('core')
-        cursor = db.db.cursor()
-        for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth):
-            cursor.execute(sql)
-        cursor.execute(&quot;INSERT INTO %s (%s, %s) VALUES ('example.com', 'Example site')&quot; % \
-            (db.db.quote_name(core.Site._meta.db_table), db.db.quote_name('domain'),
-            db.db.quote_name('name')))
-    except Exception, e:
-        sys.stderr.write(&quot;Error: The database couldn't be initialized.\n%s\n&quot; % e)
-        try:
-            db.db.rollback()
-        except UnboundLocalError:
-            pass
-        sys.exit(1)
-    else:
-        db.db.commit()
-init.args = ''
+def _module_to_dict(module, omittable=lambda k: k.startswith('_')):
+    &quot;Converts a module namespace to a Python dictionary. Used by get_settings_diff.&quot;
+    return dict([(k, repr(v)) for k, v in module.__dict__.items() if not omittable(k)])
+
+def diffsettings():
+    &quot;&quot;&quot;
+    Displays differences between the current settings.py and Django's
+    default settings. Settings that don't appear in the defaults are
+    followed by &quot;###&quot;.
+    &quot;&quot;&quot;
+    # Inspired by Postfix's &quot;postconf -n&quot;.
+    from django.conf import settings, global_settings
+
+    user_settings = _module_to_dict(settings)
+    default_settings = _module_to_dict(global_settings)
 
-def install(mod):
+    output = []
+    keys = user_settings.keys()
+    keys.sort()
+    for key in keys:
+        if key not in default_settings:
+            output.append(&quot;%s = %s  ###&quot; % (key, user_settings[key]))
+        elif user_settings[key] != default_settings[key]:
+            output.append(&quot;%s = %s&quot; % (key, user_settings[key]))
+    print '\n'.join(output)
+diffsettings.args = &quot;&quot;
+
+def install(app):
     &quot;Executes the equivalent of 'get_sql_all' in the current database.&quot;
-    from django.core import db
-    from cStringIO import StringIO
-    mod_name = mod.__name__[mod.__name__.rindex('.')+1:]
+    from django.db import connection, transaction
+
+    app_name = app.__name__.split('.')[-2]
+
+    disable_termcolors()
 
     # First, try validating the models.
-    s = StringIO()
-    num_errors = get_validation_errors(s)
-    if num_errors:
-        sys.stderr.write(&quot;Error: %s couldn't be installed, because there were errors in your model:\n&quot; % mod_name)
-        s.seek(0)
-        sys.stderr.write(s.read())
-        sys.exit(1)
-    sql_list = get_sql_all(mod)
+    _check_for_validation_errors(app)
+
+    sql_list = get_sql_all(app)
 
     try:
-        cursor = db.db.cursor()
+        cursor = connection.cursor()
         for sql in sql_list:
             cursor.execute(sql)
     except Exception, e:
-        sys.stderr.write(&quot;&quot;&quot;Error: %s couldn't be installed. Possible reasons:
+        sys.stderr.write(style.ERROR(&quot;&quot;&quot;Error: %s couldn't be installed. Possible reasons:
   * The database isn't running or isn't configured correctly.
   * At least one of the database tables already exists.
   * The SQL was invalid.
 Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run.
-The full error: %s\n&quot;&quot;&quot; % \
-            (mod_name, mod_name, e))
-        db.db.rollback()
+The full error: &quot;&quot;&quot; % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
+        transaction.rollback_unless_managed()
         sys.exit(1)
-    db.db.commit()
-install.help_doc = &quot;Executes ``sqlall`` for the given model module name(s) in the current database.&quot;
+    transaction.commit_unless_managed()
+install.help_doc = &quot;Executes ``sqlall`` for the given app(s) in the current database.&quot;
 install.args = APP_ARGS
 
-def installperms(mod):
-    &quot;Installs any permissions for the given model, if needed.&quot;
-    from django.models.auth import permissions
-    from django.models.core import packages
-    num_added = 0
-    package = packages.get_object(pk=mod._MODELS[0]._meta.app_label)
-    for klass in mod._MODELS:
-        opts = klass._meta
-        for codename, name in _get_all_permissions(opts):
-            try:
-                permissions.get_object(name__exact=name, codename__exact=codename, package__label__exact=package.label)
-            except permissions.PermissionDoesNotExist:
-                p = permissions.Permission(name=name, package=package, codename=codename)
-                p.save()
-                print &quot;Added permission '%r'.&quot; % p
-                num_added += 1
-    if not num_added:
-        print &quot;No permissions were added, because all necessary permissions were already installed.&quot;
-installperms.help_doc = &quot;Installs any permissions for the given model module name(s), if needed.&quot;
-installperms.args = APP_ARGS
+def reset(app):
+    &quot;Executes the equivalent of 'get_sql_reset' in the current database.&quot;
+    from django.db import connection, transaction
+    from cStringIO import StringIO
+    app_name = app.__name__.split('.')[-2]
+
+    disable_termcolors()
+
+    # First, try validating the models.
+    _check_for_validation_errors(app)
+    sql_list = get_sql_reset(app)
+
+    confirm = raw_input(&quot;&quot;&quot;
+You have requested a database reset.
+This will IRREVERSIBLY DESTROY any data in your database.
+Are you sure you want to do this?
+
+Type 'yes' to continue, or 'no' to cancel: &quot;&quot;&quot;)
+    if confirm == 'yes':
+        try:
+            cursor = connection.cursor()
+            for sql in sql_list:
+                cursor.execute(sql)
+        except Exception, e:
+            sys.stderr.write(style.ERROR(&quot;&quot;&quot;Error: %s couldn't be installed. Possible reasons:
+  * The database isn't running or isn't configured correctly.
+  * At least one of the database tables already exists.
+  * The SQL was invalid.
+Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
+The full error: &quot;&quot;&quot; % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
+            transaction.rollback_unless_managed()
+            sys.exit(1)
+        transaction.commit_unless_managed()
+    else:
+        print &quot;Reset cancelled.&quot;
+reset.help_doc = &quot;Executes ``sqlreset`` for the given app(s) in the current database.&quot;
+reset.args = APP_ARGS
 
 def _start_helper(app_or_project, name, directory, other_name=''):
     other = {'project': 'app', 'app': 'project'}[app_or_project]
     if not _is_valid_dir_name(name):
-        sys.stderr.write(&quot;Error: %r is not a valid %s name. Please use only numbers, letters and underscores.\n&quot; % (name, app_or_project))
+        sys.stderr.write(style.ERROR(&quot;Error: %r is not a valid %s name. Please use only numbers, letters and underscores.\n&quot; % (name, app_or_project)))
         sys.exit(1)
     top_dir = os.path.join(directory, name)
     try:
         os.mkdir(top_dir)
     except OSError, e:
-        sys.stderr.write(&quot;Error: %s\n&quot; % e)
+        sys.stderr.write(style.ERROR(&quot;Error: %s\n&quot; % e))
         sys.exit(1)
     template_dir = PROJECT_TEMPLATE_DIR % app_or_project
     for d, subdirs, files in os.walk(template_dir):
@@ -479,17 +631,20 @@ def _start_helper(app_or_project, name, directory, other_name=''):
         for f in files:
             if f.endswith('.pyc'):
                 continue
-            fp_old = open(os.path.join(d, f), 'r')
-            fp_new = open(os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name)), 'w')
+            path_old = os.path.join(d, f)
+            path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
+            fp_old = open(path_old, 'r')
+            fp_new = open(path_new, 'w')
             fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
             fp_old.close()
             fp_new.close()
+            shutil.copymode(path_old, path_new)
 
 def startproject(project_name, directory):
     &quot;Creates a Django project for the given project_name in the given directory.&quot;
     from random import choice
     if project_name in INVALID_PROJECT_NAMES:
-        sys.stderr.write(&quot;Error: %r isn't a valid project name. Please try another.\n&quot; % project_name)
+        sys.stderr.write(style.ERROR(&quot;Error: %r isn't a valid project name. Please try another.\n&quot; % project_name))
         sys.exit(1)
     _start_helper('project', project_name, directory)
     # Create a random SECRET_KEY hash, and put it in the main settings.
@@ -513,71 +668,19 @@ def startapp(app_name, directory):
 startapp.help_doc = &quot;Creates a Django app directory structure for the given app name in the current directory.&quot;
 startapp.args = &quot;[appname]&quot;
 
-def createsuperuser(username=None, email=None, password=None):
-    &quot;Creates a superuser account.&quot;
-    from django.core import validators
-    from django.models.auth import users
-    import getpass
-    try:
-        while 1:
-            if not username:
-                username = raw_input('Username (only letters, digits and underscores): ')
-            if not username.isalnum():
-                sys.stderr.write(&quot;Error: That username is invalid.\n&quot;)
-                username = None
-            try:
-                users.get_object(username__exact=username)
-            except users.UserDoesNotExist:
-                break
-            else:
-                sys.stderr.write(&quot;Error: That username is already taken.\n&quot;)
-                username = None
-        while 1:
-            if not email:
-                email = raw_input('E-mail address: ')
-            try:
-                validators.isValidEmail(email, None)
-            except validators.ValidationError:
-                sys.stderr.write(&quot;Error: That e-mail address is invalid.\n&quot;)
-                email = None
-            else:
-                break
-        while 1:
-            if not password:
-                password = getpass.getpass()
-                password2 = getpass.getpass('Password (again): ')
-                if password != password2:
-                    sys.stderr.write(&quot;Error: Your passwords didn't match.\n&quot;)
-                    password = None
-                    continue
-            if password.strip() == '':
-                sys.stderr.write(&quot;Error: Blank passwords aren't allowed.\n&quot;)
-                password = None
-                continue
-            break
-    except KeyboardInterrupt:
-        sys.stderr.write(&quot;\nOperation cancelled.\n&quot;)
-        sys.exit(1)
-    u = users.create_user(username, email, password)
-    u.is_staff = True
-    u.is_active = True
-    u.is_superuser = True
-    u.save()
-    print &quot;User created successfully.&quot;
-createsuperuser.args = '[username] [email] [password] (Either all or none)'
-
-def inspectdb(db_name):
+def inspectdb():
     &quot;Generator that introspects the tables in the given database name and returns a Django model, one line at a time.&quot;
-    from django.core import db
+    from django.db import connection, get_introspection_module
     from django.conf import settings
     import keyword
 
+    introspection_module = get_introspection_module()
+
     def table2model(table_name):
         object_name = table_name.title().replace('_', '')
         return object_name.endswith('s') and object_name[:-1] or object_name
 
-    settings.DATABASE_NAME = db_name
-    cursor = db.db.cursor()
+    cursor = connection.cursor()
     yield &quot;# This is an auto-generated Django model module.&quot;
     yield &quot;# You'll have to do the following manually to clean this up:&quot;
     yield &quot;#     * Rearrange models' order&quot;
@@ -587,19 +690,19 @@ def inspectdb(db_name):
     yield &quot;# Also note: You'll have to insert the output of 'django-admin.py sqlinitialdata [appname]'&quot;
     yield &quot;# into your database.&quot;
     yield ''
-    yield 'from django.core import meta'
+    yield 'from django.db import models'
     yield ''
-    for table_name in db.get_table_list(cursor):
-        yield 'class %s(meta.Model):' % table2model(table_name)
+    for table_name in introspection_module.get_table_list(cursor):
+        yield 'class %s(models.Model):' % table2model(table_name)
         try:
-            relations = db.get_relations(cursor, table_name)
+            relations = introspection_module.get_relations(cursor, table_name)
         except NotImplementedError:
             relations = {}
         try:
-            indexes = db.get_indexes(cursor, table_name)
+            indexes = introspection_module.get_indexes(cursor, table_name)
         except NotImplementedError:
             indexes = {}
-        for i, row in enumerate(db.get_table_description(cursor, table_name)):
+        for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
             att_name = row[0]
             comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
             extra_params = {}  # Holds Field parameters such as 'db_column'.
@@ -618,7 +721,7 @@ def inspectdb(db_name):
                     extra_params['db_column'] = att_name
             else:
                 try:
-                    field_type = db.DATA_TYPES_REVERSE[row[1]]
+                    field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]
                 except KeyError:
                     field_type = 'TextField'
                     comment_notes.append('This field type is a guess.')
@@ -652,7 +755,14 @@ def inspectdb(db_name):
             if att_name == 'id' and field_type == 'AutoField(' and extra_params == {'primary_key': True}:
                 continue
 
-            field_desc = '%s = meta.%s' % (att_name, field_type)
+            # Add 'null' and 'blank', if the 'null_ok' flag was present in the
+            # table description.
+            if row[6]: # If it's NULL...
+                extra_params['blank'] = True
+                if not field_type in ('TextField', 'CharField'):
+                    extra_params['null'] = True
+
+            field_desc = '%s = models.%s' % (att_name, field_type)
             if extra_params:
                 if not field_desc.endswith('('):
                     field_desc += ', '
@@ -661,11 +771,11 @@ def inspectdb(db_name):
             if comment_notes:
                 field_desc += ' # ' + ' '.join(comment_notes)
             yield '    %s' % field_desc
-        yield '    class META:'
+        yield '    class Meta:'
         yield '        db_table = %r' % table_name
         yield ''
 inspectdb.help_doc = &quot;Introspects the database tables in the given database and outputs a Django model module.&quot;
-inspectdb.args = &quot;[dbname]&quot;
+inspectdb.args = &quot;&quot;
 
 class ModelErrorCollection:
     def __init__(self, outfile=sys.stdout):
@@ -674,123 +784,182 @@ class ModelErrorCollection:
 
     def add(self, opts, error):
         self.errors.append((opts, error))
-        self.outfile.write(&quot;%s.%s: %s\n&quot; % (opts.app_label, opts.module_name, error))
+        self.outfile.write(style.ERROR(&quot;%s.%s: %s\n&quot; % (opts.app_label, opts.module_name, error)))
+
+def get_validation_errors(outfile, app=None):
+    &quot;&quot;&quot;
+    Validates all models that are part of the specified app. If no app name is provided,
+    validates all models of all installed apps. Writes errors, if any, to outfile.
+    Returns number of errors.
+    &quot;&quot;&quot;
+    from django.db import models
+    from django.db.models.fields.related import RelatedObject
 
-def get_validation_errors(outfile):
-    &quot;Validates all installed models. Writes errors, if any, to outfile. Returns number of errors.&quot;
-    import django.models
-    from django.core import meta
     e = ModelErrorCollection(outfile)
-    module_list = meta.get_installed_model_modules()
-    for module in module_list:
-        for mod in module._MODELS:
-            opts = mod._meta
+    for cls in models.get_models(app):
+        opts = cls._meta
 
-            # Do field-specific validation.
-            for f in opts.fields:
-                if isinstance(f, meta.CharField) and f.maxlength in (None, 0):
-                    e.add(opts, '&quot;%s&quot; field: CharFields require a &quot;maxlength&quot; attribute.' % f.name)
-                if isinstance(f, meta.FloatField):
-                    if f.decimal_places is None:
-                        e.add(opts, '&quot;%s&quot; field: FloatFields require a &quot;decimal_places&quot; attribute.' % f.name)
-                    if f.max_digits is None:
-                        e.add(opts, '&quot;%s&quot; field: FloatFields require a &quot;max_digits&quot; attribute.' % f.name)
-                if isinstance(f, meta.FileField) and not f.upload_to:
-                    e.add(opts, '&quot;%s&quot; field: FileFields require an &quot;upload_to&quot; attribute.' % f.name)
-                if isinstance(f, meta.ImageField):
-                    try:
-                        from PIL import Image
-                    except ImportError:
-                        e.add(opts, '&quot;%s&quot; field: To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
-                if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
-                    e.add(opts, '&quot;%s&quot; field: prepopulate_from should be a list or tuple.' % f.name)
-                if f.choices:
-                    if not type(f.choices) in (tuple, list):
-                        e.add(opts, '&quot;%s&quot; field: &quot;choices&quot; should be either a tuple or list.' % f.name)
-                    else:
-                        for c in f.choices:
-                            if not type(c) in (tuple, list) or len(c) != 2:
-                                e.add(opts, '&quot;%s&quot; field: &quot;choices&quot; should be a sequence of two-tuples.' % f.name)
-                if f.db_index not in (None, True, False):
-                    e.add(opts, '&quot;%s&quot; field: &quot;db_index&quot; should be either None, True or False.' % f.name)
-
-            # Check for multiple ManyToManyFields to the same object, and
-            # verify &quot;singular&quot; is set in that case.
-            for i, f in enumerate(opts.many_to_many):
-                for previous_f in opts.many_to_many[:i]:
-                    if f.rel.to == previous_f.rel.to and f.rel.singular == previous_f.rel.singular:
-                        e.add(opts, 'The &quot;%s&quot; field requires a &quot;singular&quot; parameter, because the %s model has more than one ManyToManyField to the same model (%s).' % (f.name, opts.object_name, previous_f.rel.to.object_name))
-
-            # Check admin attribute.
-            if opts.admin is not None:
-                if not isinstance(opts.admin, meta.Admin):
-                    e.add(opts, '&quot;admin&quot; attribute, if given, must be set to a meta.Admin() instance.')
+        # Do field-specific validation.
+        for f in opts.fields:
+            # Check for deprecated args
+            dep_args = getattr(f, 'deprecated_args', None)
+            if dep_args:
+                e.add(opts, &quot;'%s' Initialized with deprecated args:%s&quot; % (f.name, &quot;,&quot;.join(dep_args)))
+            if isinstance(f, models.CharField) and f.maxlength in (None, 0):
+                e.add(opts, '&quot;%s&quot;: CharFields require a &quot;maxlength&quot; attribute.' % f.name)
+            if isinstance(f, models.FloatField):
+                if f.decimal_places is None:
+                    e.add(opts, '&quot;%s&quot;: FloatFields require a &quot;decimal_places&quot; attribute.' % f.name)
+                if f.max_digits is None:
+                    e.add(opts, '&quot;%s&quot;: FloatFields require a &quot;max_digits&quot; attribute.' % f.name)
+            if isinstance(f, models.FileField) and not f.upload_to:
+                e.add(opts, '&quot;%s&quot;: FileFields require an &quot;upload_to&quot; attribute.' % f.name)
+            if isinstance(f, models.ImageField):
+                try:
+                    from PIL import Image
+                except ImportError:
+                    e.add(opts, '&quot;%s&quot;: To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
+            if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
+                e.add(opts, '&quot;%s&quot;: prepopulate_from should be a list or tuple.' % f.name)
+            if f.choices:
+                if not type(f.choices) in (tuple, list):
+                    e.add(opts, '&quot;%s&quot;: &quot;choices&quot; should be either a tuple or list.' % f.name)
                 else:
-                    # list_display
-                    if not isinstance(opts.admin.list_display, (list, tuple)):
-                        e.add(opts, '&quot;admin.list_display&quot;, if given, must be set to a list or tuple.')
-                    else:
-                        for fn in opts.admin.list_display:
-                            try:
-                                f = opts.get_field(fn)
-                            except meta.FieldDoesNotExist:
-                                klass = opts.get_model_module().Klass
-                                if not hasattr(klass, fn) or not callable(getattr(klass, fn)):
-                                    e.add(opts, '&quot;admin.list_display&quot; refers to %r, which isn\'t a field or method.' % fn)
-                            else:
-                                if isinstance(f, meta.ManyToManyField):
-                                    e.add(opts, '&quot;admin.list_display&quot; doesn\'t support ManyToManyFields (%r).' % fn)
-                    # list_filter
-                    if not isinstance(opts.admin.list_filter, (list, tuple)):
-                        e.add(opts, '&quot;admin.list_filter&quot;, if given, must be set to a list or tuple.')
-                    else:
-                        for fn in opts.admin.list_filter:
-                            try:
-                                f = opts.get_field(fn)
-                            except meta.FieldDoesNotExist:
-                                e.add(opts, '&quot;admin.list_filter&quot; refers to %r, which isn\'t a field.' % fn)
-
-            # Check ordering attribute.
-            if opts.ordering:
-                for field_name in opts.ordering:
-                    if field_name == '?': continue
-                    if field_name.startswith('-'):
-                        field_name = field_name[1:]
-                    if opts.order_with_respect_to and field_name == '_order':
-                        continue
-                    try:
-                        opts.get_field(field_name, many_to_many=False)
-                    except meta.FieldDoesNotExist:
-                        e.add(opts, '&quot;ordering&quot; refers to &quot;%s&quot;, a field that doesn\'t exist.' % field_name)
+                    for c in f.choices:
+                        if not type(c) in (tuple, list) or len(c) != 2:
+                            e.add(opts, '&quot;%s&quot;: &quot;choices&quot; should be a sequence of two-tuples.' % f.name)
+            if f.db_index not in (None, True, False):
+                e.add(opts, '&quot;%s&quot;: &quot;db_index&quot; should be either None, True or False.' % f.name)
+
+            # Check to see if the related field will clash with any
+            # existing fields, m2m fields, m2m related objects or related objects
+            if f.rel:
+                rel_opts = f.rel.to._meta
+                if f.rel.to not in models.get_models():
+                    e.add(opts, &quot;'%s' has relation with uninstalled model %s&quot; % (f.name, rel_opts.object_name))
+
+                rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
+                for r in rel_opts.fields:
+                    if r.name == rel_name:
+                        e.add(opts, &quot;'%s' accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.name, f.name))
+                for r in rel_opts.many_to_many:
+                    if r.name == rel_name:
+                        e.add(opts, &quot;'%s' accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.name, f.name))
+                for r in rel_opts.get_all_related_many_to_many_objects():
+                    if r.get_accessor_name() == rel_name:
+                        e.add(opts, &quot;'%s' accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+                for r in rel_opts.get_all_related_objects():
+                    if r.get_accessor_name() == rel_name and r.field is not f:
+                        e.add(opts, &quot;'%s' accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+
+        for i, f in enumerate(opts.many_to_many):
+            # Check to see if the related m2m field will clash with any
+            # existing fields, m2m fields, m2m related objects or related objects
+            rel_opts = f.rel.to._meta
+            if f.rel.to not in models.get_models():
+                e.add(opts, &quot;'%s' has m2m relation with uninstalled model %s&quot; % (f.name, rel_opts.object_name))
+
+            rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
+            for r in rel_opts.fields:
+                if r.name == rel_name:
+                    e.add(opts, &quot;'%s' m2m accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.name, f.name))
+            for r in rel_opts.many_to_many:
+                if r.name == rel_name:
+                    e.add(opts, &quot;'%s' m2m accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.name, f.name))
+            for r in rel_opts.get_all_related_many_to_many_objects():
+                if r.get_accessor_name() == rel_name and r.field is not f:
+                    e.add(opts, &quot;'%s' m2m accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+            for r in rel_opts.get_all_related_objects():
+                if r.get_accessor_name() == rel_name:
+                    e.add(opts, &quot;'%s' m2m accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'.&quot; % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+
+        # Check admin attribute.
+        if opts.admin is not None:
+            if not isinstance(opts.admin, models.AdminOptions):
+                e.add(opts, '&quot;admin&quot; attribute, if given, must be set to a models.AdminOptions() instance.')
+            else:
+                # list_display
+                if not isinstance(opts.admin.list_display, (list, tuple)):
+                    e.add(opts, '&quot;admin.list_display&quot;, if given, must be set to a list or tuple.')
+                else:
+                    for fn in opts.admin.list_display:
+                        try:
+                            f = opts.get_field(fn)
+                        except models.FieldDoesNotExist:
+                            if not hasattr(cls, fn):
+                                e.add(opts, '&quot;admin.list_display&quot; refers to %r, which isn\'t an attribute, method or property.' % fn)
+                        else:
+                            if isinstance(f, models.ManyToManyField):
+                                e.add(opts, '&quot;admin.list_display&quot; doesn\'t support ManyToManyFields (%r).' % fn)
+                # list_filter
+                if not isinstance(opts.admin.list_filter, (list, tuple)):
+                    e.add(opts, '&quot;admin.list_filter&quot;, if given, must be set to a list or tuple.')
+                else:
+                    for fn in opts.admin.list_filter:
+                        try:
+                            f = opts.get_field(fn)
+                        except models.FieldDoesNotExist:
+                            e.add(opts, '&quot;admin.list_filter&quot; refers to %r, which isn\'t a field.' % fn)
+
+        # Check ordering attribute.
+        if opts.ordering:
+            for field_name in opts.ordering:
+                if field_name == '?': continue
+                if field_name.startswith('-'):
+                    field_name = field_name[1:]
+                if opts.order_with_respect_to and field_name == '_order':
+                    continue
+                try:
+                    opts.get_field(field_name, many_to_many=False)
+                except models.FieldDoesNotExist:
+                    e.add(opts, '&quot;ordering&quot; refers to &quot;%s&quot;, a field that doesn\'t exist.' % field_name)
 
-            # Check core=True, if needed.
-            for related in opts.get_followed_related_objects():
+        # Check core=True, if needed.
+        for related in opts.get_followed_related_objects():
+            try:
+                for f in related.opts.fields:
+                    if f.core:
+                        raise StopIteration
+                e.add(related.opts, &quot;At least one field in %s should have core=True, because it's being edited inline by %s.%s.&quot; % (related.opts.object_name, opts.module_name, opts.object_name))
+            except StopIteration:
+                pass
+
+        # Check unique_together.
+        for ut in opts.unique_together:
+            for field_name in ut:
                 try:
-                    for f in related.opts.fields:
-                        if f.core:
-                            raise StopIteration
-                    e.add(related.opts, &quot;At least one field in %s should have core=True, because it's being edited inline by %s.%s.&quot; % (related.opts.object_name, opts.module_name, opts.object_name))
-                except StopIteration:
-                    pass
-
-            # Check unique_together.
-            for ut in opts.unique_together:
-                for field_name in ut:
-                    try:
-                        f = opts.get_field(field_name, many_to_many=True)
-                    except meta.FieldDoesNotExist:
-                        e.add(opts, '&quot;unique_together&quot; refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
-                    else:
-                        if isinstance(f.rel, meta.ManyToManyRel):
-                            e.add(opts, '&quot;unique_together&quot; refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
+                    f = opts.get_field(field_name, many_to_many=True)
+                except models.FieldDoesNotExist:
+                    e.add(opts, '&quot;unique_together&quot; refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
+                else:
+                    if isinstance(f.rel, models.ManyToManyRel):
+                        e.add(opts, '&quot;unique_together&quot; refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
+
     return len(e.errors)
 
 def validate(outfile=sys.stdout):
     &quot;Validates all installed models.&quot;
-    num_errors = get_validation_errors(outfile)
-    outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
+    try:
+        num_errors = get_validation_errors(outfile)
+        outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
+    except ImproperlyConfigured:
+        outfile.write(&quot;Skipping validation because things aren't configured properly.&quot;)
 validate.args = ''
 
+def _check_for_validation_errors(app=None):
+    &quot;&quot;&quot;Check that an app has no validation errors, and exit with errors if it does.&quot;&quot;&quot;
+    try:
+        from cStringIO import StringIO
+    except ImportError:
+        from StringIO import StringIO
+    s = StringIO()
+    num_errors = get_validation_errors(s, app)
+    if num_errors:
+        sys.stderr.write(style.ERROR(&quot;Error: %s couldn't be installed, because there were errors in your model:\n&quot; % app))
+        s.seek(0)
+        sys.stderr.write(s.read())
+        sys.exit(1)
+
 def runserver(addr, port):
     &quot;Starts a lightweight Web server for development.&quot;
     from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
@@ -798,13 +967,13 @@ def runserver(addr, port):
     if not addr:
         addr = '127.0.0.1'
     if not port.isdigit():
-        sys.stderr.write(&quot;Error: %r is not a valid port number.\n&quot; % port)
+        sys.stderr.write(style.ERROR(&quot;Error: %r is not a valid port number.\n&quot; % port))
         sys.exit(1)
     def inner_run():
-        from django.conf.settings import SETTINGS_MODULE
+        from django.conf import settings
         print &quot;Validating models...&quot;
         validate()
-        print &quot;\nDjango version %s, using settings %r&quot; % (get_version(), SETTINGS_MODULE)
+        print &quot;\nDjango version %s, using settings %r&quot; % (get_version(), settings.SETTINGS_MODULE)
         print &quot;Development server is running at http://%s:%s/&quot; % (addr, port)
         print &quot;Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).&quot;
         try:
@@ -820,7 +989,7 @@ def runserver(addr, port):
                 error_text = ERRORS[e.args[0].args[0]]
             except (AttributeError, KeyError):
                 error_text = str(e)
-            sys.stderr.write(&quot;Error: %s\n&quot; % error_text)
+            sys.stderr.write(style.ERROR(&quot;Error: %s&quot; % error_text) + '\n')
             sys.exit(1)
         except KeyboardInterrupt:
             sys.exit(0)
@@ -830,17 +999,18 @@ runserver.args = '[optional port number, or ipaddr:port]'
 
 def createcachetable(tablename):
     &quot;Creates the table needed to use the SQL cache backend&quot;
-    from django.core import db, meta
+    from django.db import backend, connection, transaction, get_creation_module, models
+    data_types = get_creation_module().DATA_TYPES
     fields = (
         # &quot;key&quot; is a reserved word in MySQL, so use &quot;cache_key&quot; instead.
-        meta.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True),
-        meta.TextField(name='value'),
-        meta.DateTimeField(name='expires', db_index=True),
+        models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True),
+        models.TextField(name='value'),
+        models.DateTimeField(name='expires', db_index=True),
     )
     table_output = []
     index_output = []
     for f in fields:
-        field_output = [db.db.quote_name(f.column), db.DATA_TYPES[f.get_internal_type()] % f.__dict__]
+        field_output = [backend.quote_name(f.name), data_types[f.get_internal_type()] % f.__dict__]
         field_output.append(&quot;%sNULL&quot; % (not f.null and &quot;NOT &quot; or &quot;&quot;))
         if f.unique:
             field_output.append(&quot;UNIQUE&quot;)
@@ -849,18 +1019,18 @@ def createcachetable(tablename):
         if f.db_index:
             unique = f.unique and &quot;UNIQUE &quot; or &quot;&quot;
             index_output.append(&quot;CREATE %sINDEX %s_%s ON %s (%s);&quot; % \
-                (unique, tablename, f.column, db.db.quote_name(tablename),
-                db.db.quote_name(f.column)))
+                (unique, tablename, f.name, backend.quote_name(tablename),
+                backend.quote_name(f.name)))
         table_output.append(&quot; &quot;.join(field_output))
-    full_statement = [&quot;CREATE TABLE %s (&quot; % db.db.quote_name(tablename)]
+    full_statement = [&quot;CREATE TABLE %s (&quot; % backend.quote_name(tablename)]
     for i, line in enumerate(table_output):
         full_statement.append('    %s%s' % (line, i &lt; len(table_output)-1 and ',' or ''))
     full_statement.append(');')
-    curs = db.db.cursor()
+    curs = connection.cursor()
     curs.execute(&quot;\n&quot;.join(full_statement))
     for statement in index_output:
         curs.execute(statement)
-    db.db.commit()
+    transaction.commit_unless_managed()
 createcachetable.args = &quot;[tablename]&quot;
 
 def run_shell(use_plain=False):
@@ -877,17 +1047,22 @@ def run_shell(use_plain=False):
         code.interact()
 run_shell.args = '[--plain]'
 
+def dbshell():
+    &quot;Runs the command-line client for the current DATABASE_ENGINE.&quot;
+    from django.db import runshell
+    runshell()
+dbshell.args = &quot;&quot;
+
 # Utilities for command-line script
 
 DEFAULT_ACTION_MAPPING = {
     'adminindex': get_admin_index,
-    'createsuperuser': createsuperuser,
     'createcachetable' : createcachetable,
-#     'dbcheck': database_check,
-    'init': init,
+    'dbshell': dbshell,
+    'diffsettings': diffsettings,
     'inspectdb': inspectdb,
     'install': install,
-    'installperms': installperms,
+    'reset': reset,
     'runserver': runserver,
     'shell': run_shell,
     'sql': get_sql_create,
@@ -899,10 +1074,20 @@ DEFAULT_ACTION_MAPPING = {
     'sqlsequencereset': get_sql_sequence_reset,
     'startapp': startapp,
     'startproject': startproject,
+    'syncdb': syncdb,
     'validate': validate,
 }
 
-NO_SQL_TRANSACTION = ('adminindex', 'createcachetable', 'dbcheck', 'install', 'installperms', 'sqlindexes')
+NO_SQL_TRANSACTION = (
+    'adminindex',
+    'createcachetable',
+    'dbshell',
+    'diffsettings',
+    'install',
+    'reset',
+    'sqlindexes',
+    'syncdb',
+)
 
 class DjangoOptionParser(OptionParser):
     def print_usage_and_exit(self):
@@ -914,18 +1099,18 @@ def get_usage(action_mapping):
     Returns a usage string. Doesn't do the options stuff, because optparse
     takes care of that.
     &quot;&quot;&quot;
-    usage = [&quot;usage: %prog action [options]\nactions:&quot;]
+    usage = [&quot;%prog action [options]\nactions:&quot;]
     available_actions = action_mapping.keys()
     available_actions.sort()
     for a in available_actions:
         func = action_mapping[a]
         usage.append(&quot;  %s %s&quot; % (a, func.args))
-        usage.extend(textwrap.wrap(getattr(func, 'help_doc', func.__doc__), initial_indent='    ', subsequent_indent='    '))
+        usage.extend(textwrap.wrap(getattr(func, 'help_doc', textwrap.dedent(func.__doc__.strip())), initial_indent='    ', subsequent_indent='    '))
         usage.append(&quot;&quot;)
     return '\n'.join(usage[:-1]) # Cut off last list element, an empty space.
 
 def print_error(msg, cmd):
-    sys.stderr.write('Error: %s\nRun &quot;%s --help&quot; for help.\n' % (msg, cmd))
+    sys.stderr.write(style.ERROR('Error: %s' % msg) + '\nRun &quot;%s --help&quot; for help.\n' % cmd)
     sys.exit(1)
 
 def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
@@ -961,31 +1146,16 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
         from django.utils import translation
         translation.activate('en-us')
 
-    if action == 'createsuperuser':
-        try:
-            username, email, password = args[1], args[2], args[3]
-        except IndexError:
-            if len(args) == 1: # We got no arguments, just the action.
-                action_mapping[action]()
-            else:
-                sys.stderr.write(&quot;Error: %r requires arguments of 'username email password' or no argument at all.\n&quot;)
-                sys.exit(1)
-        else:
-            action_mapping[action](username, email, password)
-    elif action == 'shell':
+    if action == 'shell':
         action_mapping[action](options.plain is True)
-    elif action in ('init', 'validate'):
+    elif action in ('syncdb', 'validate', 'diffsettings', 'dbshell'):
         action_mapping[action]()
     elif action == 'inspectdb':
         try:
-            param = args[1]
-        except IndexError:
-            parser.print_usage_and_exit()
-        try:
-            for line in action_mapping[action](param):
+            for line in action_mapping[action]():
                 print line
         except NotImplementedError:
-            sys.stderr.write(&quot;Error: %r isn't supported for the currently selected database backend.\n&quot; % action)
+            sys.stderr.write(style.ERROR(&quot;Error: %r isn't supported for the currently selected database backend.\n&quot; % action))
             sys.exit(1)
     elif action == 'createcachetable':
         try:
@@ -1009,25 +1179,22 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
                 addr, port = '', args[1]
         action_mapping[action](addr, port)
     else:
-        from django.core import meta
-        if action == 'dbcheck':
-            mod_list = meta.get_all_installed_modules()
-        else:
-            try:
-                mod_list = [meta.get_app(app_label) for app_label in args[1:]]
-            except ImportError, e:
-                sys.stderr.write(&quot;Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n&quot; % e)
-                sys.exit(1)
-            if not mod_list:
-                parser.print_usage_and_exit()
+        from django.db import models
+        try:
+            mod_list = [models.get_app(app_label) for app_label in args[1:]]
+        except ImportError, e:
+            sys.stderr.write(style.ERROR(&quot;Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n&quot; % e))
+            sys.exit(1)
+        if not mod_list:
+            parser.print_usage_and_exit()
         if action not in NO_SQL_TRANSACTION:
-            print &quot;BEGIN;&quot;
+            print style.SQL_KEYWORD(&quot;BEGIN;&quot;)
         for mod in mod_list:
             output = action_mapping[action](mod)
             if output:
                 print '\n'.join(output)
         if action not in NO_SQL_TRANSACTION:
-            print &quot;COMMIT;&quot;
+            print style.SQL_KEYWORD(&quot;COMMIT;&quot;)
 
 def execute_manager(settings_mod):
     # Add this project to sys.path so that it's importable in the conventional
@@ -1042,10 +1209,18 @@ def execute_manager(settings_mod):
     # Set DJANGO_SETTINGS_MODULE appropriately.
     os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
 
+    action_mapping = DEFAULT_ACTION_MAPPING.copy()
+
     # Remove the &quot;startproject&quot; command from the action_mapping, because that's
     # a django-admin.py command, not a manage.py command.
-    action_mapping = DEFAULT_ACTION_MAPPING.copy()
     del action_mapping['startproject']
 
+    # Override the startapp handler so that it always uses the
+    # project_directory, not the current working directory (which is default).
+    action_mapping['startapp'] = lambda app_name, directory: startapp(app_name, project_directory)
+    action_mapping['startapp'].__doc__ = startapp.__doc__
+    action_mapping['startapp'].help_doc = startapp.help_doc
+    action_mapping['startapp'].args = startapp.args
+
     # Run the django-admin.py command.
     execute_from_command_line(action_mapping)</diff>
      <filename>django/core/management.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,20 +6,17 @@ class InvalidPage(Exception):
 
 class ObjectPaginator:
     &quot;&quot;&quot;
-    This class makes pagination easy. Feed it a module (an object with
-    get_count() and get_list() methods) and a dictionary of arguments
-    to be passed to those methods, plus the number of objects you want
-    on each page. Then read the hits and pages properties to see how
-    many pages it involves. Call get_page with a page number (starting
+    This class makes pagination easy. Feed it a QuerySet, plus the number of
+    objects you want on each page. Then read the hits and pages properties to
+    see how many pages it involves. Call get_page with a page number (starting
     at 0) to get back a list of objects for that page.
 
     Finally, check if a page number has a next/prev page using
     has_next_page(page_number) and has_previous_page(page_number).
     &quot;&quot;&quot;
-    def __init__(self, module, args, num_per_page, count_method='get_count', list_method='get_list'):
-        self.module, self.args = module, args
+    def __init__(self, query_set, num_per_page):
+        self.query_set = query_set
         self.num_per_page = num_per_page
-        self.count_method, self.list_method = count_method, list_method
         self._hits, self._pages = None, None
         self._has_next = {} # Caches page_number -&gt; has_next_boolean
 
@@ -30,14 +27,17 @@ class ObjectPaginator:
             raise InvalidPage
         if page_number &lt; 0:
             raise InvalidPage
-        args = copy(self.args)
-        args['offset'] = page_number * self.num_per_page
+
         # Retrieve one extra record, and check for the existence of that extra
         # record to determine whether there's a next page.
-        args['limit'] = self.num_per_page + 1
-        object_list = getattr(self.module, self.list_method)(**args)
+        limit = self.num_per_page + 1
+        offset = page_number * self.num_per_page
+
+        object_list = list(self.query_set[offset:offset+limit])
+
         if not object_list:
             raise InvalidPage
+
         self._has_next[page_number] = (len(object_list) &gt; self.num_per_page)
         return object_list[:self.num_per_page]
 
@@ -45,11 +45,8 @@ class ObjectPaginator:
         &quot;Does page $page_number have a 'next' page?&quot;
         if not self._has_next.has_key(page_number):
             if self._pages is None:
-                args = copy(self.args)
-                args['offset'] = (page_number + 1) * self.num_per_page
-                args['limit'] = 1
-                object_list = getattr(self.module, self.list_method)(**args)
-                self._has_next[page_number] = (object_list != [])
+                offset = (page_number + 1) * self.num_per_page
+                self._has_next[page_number] = len(self.query_set[offset:offset+1]) &gt; 0
             else:
                 self._has_next[page_number] = page_number &lt; (self.pages - 1)
         return self._has_next[page_number]
@@ -59,12 +56,7 @@ class ObjectPaginator:
 
     def _get_hits(self):
         if self._hits is None:
-            order_args = copy(self.args)
-            if order_args.has_key('order_by'):
-                del order_args['order_by']
-            if order_args.has_key('select_related'):
-                del order_args['select_related']
-            self._hits = getattr(self.module, self.count_method)(**order_args)
+            self._hits = self.query_set.count()
         return self._hits
 
     def _get_pages(self):</diff>
      <filename>django/core/paginator.py</filename>
    </modified>
    <modified>
      <diff>@@ -242,7 +242,7 @@ class ServerHandler:
 
     # Error handling (also per-subclass or per-instance)
     traceback_limit = None  # Print entire traceback to self.get_stderr()
-    error_status = &quot;500 Dude, this is whack!&quot;
+    error_status = &quot;500 INTERNAL SERVER ERROR&quot;
     error_headers = [('Content-Type','text/plain')]
 
     # State variables (don't mess with these)
@@ -383,7 +383,7 @@ class ServerHandler:
         assert type(data) is StringType,&quot;write() argument must be string&quot;
 
         if not self.status:
-             raise AssertionError(&quot;write() before start_response()&quot;)
+            raise AssertionError(&quot;write() before start_response()&quot;)
 
         elif not self.headers_sent:
             # Before the first output, send the stored headers
@@ -532,8 +532,8 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
     server_version = &quot;WSGIServer/&quot; + __version__
 
     def __init__(self, *args, **kwargs):
-        from django.conf.settings import ADMIN_MEDIA_PREFIX
-        self.admin_media_prefix = ADMIN_MEDIA_PREFIX
+        from django.conf import settings
+        self.admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
         BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
 
     def get_environ(self):</diff>
      <filename>django/core/servers/basehttp.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 # This module is DEPRECATED!
 #
-# You should no longer be using django.core.template_loader.
+# You should no longer be using django.template_loader.
 #
-# Use django.core.template.loader instead.
+# Use django.template.loader instead.
 
-from django.core.template.loader import *
+from django.template.loader import *</diff>
      <filename>django/core/template_loader.py</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,8 @@ a string) and returns a tuple in this format:
     (view_function, function_args, function_kwargs)
 &quot;&quot;&quot;
 
-from django.core.exceptions import Http404, ImproperlyConfigured, ViewDoesNotExist
+from django.http import Http404
+from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
 import re
 
 class Resolver404(Http404):</diff>
      <filename>django/core/urlresolvers.py</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,9 @@ validator will *always* be run, regardless of whether its associated
 form field is required.
 &quot;&quot;&quot;
 
+from django.conf import settings
+from django.utils.translation import gettext, gettext_lazy, ngettext
+from django.utils.functional import Promise, lazy
 import re
 
 _datere = r'(19|2\d)\d{2}-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[12][0-9])|(?:3[0-1]))'
@@ -24,10 +27,6 @@ phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNO
 slug_re = re.compile(r'^[-\w]+$')
 url_re = re.compile(r'^https?://\S+$')
 
-from django.conf.settings import JING_PATH
-from django.utils.translation import gettext_lazy, ngettext
-from django.utils.functional import Promise, lazy
-
 lazy_inter = lazy(lambda a,b: str(a) % b, str)
 
 class ValidationError(Exception):
@@ -58,11 +57,11 @@ class CriticalValidationError(Exception):
 
 def isAlphaNumeric(field_data, all_data):
     if not alnum_re.search(field_data):
-        raise ValidationError, _(&quot;This value must contain only letters, numbers and underscores.&quot;)
+        raise ValidationError, gettext(&quot;This value must contain only letters, numbers and underscores.&quot;)
 
 def isAlphaNumericURL(field_data, all_data):
     if not alnumurl_re.search(field_data):
-        raise ValidationError, _(&quot;This value must contain only letters, numbers, underscores, dashes or slashes.&quot;)
+        raise ValidationError, gettext(&quot;This value must contain only letters, numbers, underscores, dashes or slashes.&quot;)
 
 def isSlug(field_data, all_data):
     if not slug_re.search(field_data):
@@ -70,18 +69,18 @@ def isSlug(field_data, all_data):
 
 def isLowerCase(field_data, all_data):
     if field_data.lower() != field_data:
-        raise ValidationError, _(&quot;Uppercase letters are not allowed here.&quot;)
+        raise ValidationError, gettext(&quot;Uppercase letters are not allowed here.&quot;)
 
 def isUpperCase(field_data, all_data):
     if field_data.upper() != field_data:
-        raise ValidationError, _(&quot;Lowercase letters are not allowed here.&quot;)
+        raise ValidationError, gettext(&quot;Lowercase letters are not allowed here.&quot;)
 
 def isCommaSeparatedIntegerList(field_data, all_data):
     for supposed_int in field_data.split(','):
         try:
             int(supposed_int)
         except ValueError:
-            raise ValidationError, _(&quot;Enter only digits separated by commas.&quot;)
+            raise ValidationError, gettext(&quot;Enter only digits separated by commas.&quot;)
 
 def isCommaSeparatedEmailList(field_data, all_data):
     &quot;&quot;&quot;
@@ -93,48 +92,48 @@ def isCommaSeparatedEmailList(field_data, all_data):
         try:
             isValidEmail(supposed_email.strip(), '')
         except ValidationError:
-            raise ValidationError, _(&quot;Enter valid e-mail addresses separated by commas.&quot;)
+            raise ValidationError, gettext(&quot;Enter valid e-mail addresses separated by commas.&quot;)
 
 def isValidIPAddress4(field_data, all_data):
     if not ip4_re.search(field_data):
-        raise ValidationError, _(&quot;Please enter a valid IP address.&quot;)
+        raise ValidationError, gettext(&quot;Please enter a valid IP address.&quot;)
 
 def isNotEmpty(field_data, all_data):
     if field_data.strip() == '':
-        raise ValidationError, _(&quot;Empty values are not allowed here.&quot;)
+        raise ValidationError, gettext(&quot;Empty values are not allowed here.&quot;)
 
 def isOnlyDigits(field_data, all_data):
     if not field_data.isdigit():
-        raise ValidationError, _(&quot;Non-numeric characters aren't allowed here.&quot;)
+        raise ValidationError, gettext(&quot;Non-numeric characters aren't allowed here.&quot;)
 
 def isNotOnlyDigits(field_data, all_data):
     if field_data.isdigit():
-        raise ValidationError, _(&quot;This value can't be comprised solely of digits.&quot;)
+        raise ValidationError, gettext(&quot;This value can't be comprised solely of digits.&quot;)
 
 def isInteger(field_data, all_data):
     # This differs from isOnlyDigits because this accepts the negative sign
     if not integer_re.search(field_data):
-        raise ValidationError, _(&quot;Enter a whole number.&quot;)
+        raise ValidationError, gettext(&quot;Enter a whole number.&quot;)
 
 def isOnlyLetters(field_data, all_data):
     if not field_data.isalpha():
-        raise ValidationError, _(&quot;Only alphabetical characters are allowed here.&quot;)
+        raise ValidationError, gettext(&quot;Only alphabetical characters are allowed here.&quot;)
 
 def isValidANSIDate(field_data, all_data):
     if not ansi_date_re.search(field_data):
-        raise ValidationError, _('Enter a valid date in YYYY-MM-DD format.')
+        raise ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.')
 
 def isValidANSITime(field_data, all_data):
     if not ansi_time_re.search(field_data):
-        raise ValidationError, _('Enter a valid time in HH:MM format.')
+        raise ValidationError, gettext('Enter a valid time in HH:MM format.')
 
 def isValidANSIDatetime(field_data, all_data):
     if not ansi_datetime_re.search(field_data):
-        raise ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
+        raise ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
 
 def isValidEmail(field_data, all_data):
     if not email_re.search(field_data):
-        raise ValidationError, _('Enter a valid e-mail address.')
+        raise ValidationError, gettext('Enter a valid e-mail address.')
 
 def isValidImage(field_data, all_data):
     &quot;&quot;&quot;
@@ -146,18 +145,18 @@ def isValidImage(field_data, all_data):
     try:
         Image.open(StringIO(field_data['content']))
     except IOError: # Python Imaging Library doesn't recognize it as an image
-        raise ValidationError, _(&quot;Upload a valid image. The file you uploaded was either not an image or a corrupted image.&quot;)
+        raise ValidationError, gettext(&quot;Upload a valid image. The file you uploaded was either not an image or a corrupted image.&quot;)
 
 def isValidImageURL(field_data, all_data):
     uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png'))
     try:
         uc(field_data, all_data)
     except URLMimeTypeCheck.InvalidContentType:
-        raise ValidationError, _(&quot;The URL %s does not point to a valid image.&quot;) % field_data
+        raise ValidationError, gettext(&quot;The URL %s does not point to a valid image.&quot;) % field_data
 
 def isValidPhone(field_data, all_data):
     if not phone_re.search(field_data):
-        raise ValidationError, _('Phone numbers must be in XXX-XXX-XXXX format. &quot;%s&quot; is invalid.') % field_data
+        raise ValidationError, gettext('Phone numbers must be in XXX-XXX-XXXX format. &quot;%s&quot; is invalid.') % field_data
 
 def isValidQuicktimeVideoURL(field_data, all_data):
     &quot;Checks that the given URL is a video that can be played by QuickTime (qt, mpeg)&quot;
@@ -165,11 +164,11 @@ def isValidQuicktimeVideoURL(field_data, all_data):
     try:
         uc(field_data, all_data)
     except URLMimeTypeCheck.InvalidContentType:
-        raise ValidationError, _(&quot;The URL %s does not point to a valid QuickTime video.&quot;) % field_data
+        raise ValidationError, gettext(&quot;The URL %s does not point to a valid QuickTime video.&quot;) % field_data
 
 def isValidURL(field_data, all_data):
     if not url_re.search(field_data):
-        raise ValidationError, _(&quot;A valid URL is required.&quot;)
+        raise ValidationError, gettext(&quot;A valid URL is required.&quot;)
 
 def isValidHTML(field_data, all_data):
     import urllib, urllib2
@@ -183,14 +182,14 @@ def isValidHTML(field_data, all_data):
         return
     from xml.dom.minidom import parseString
     error_messages = [e.firstChild.wholeText for e in parseString(u.read()).getElementsByTagName('messages')[0].getElementsByTagName('msg')]
-    raise ValidationError, _(&quot;Valid HTML is required. Specific errors are:\n%s&quot;) % &quot;\n&quot;.join(error_messages)
+    raise ValidationError, gettext(&quot;Valid HTML is required. Specific errors are:\n%s&quot;) % &quot;\n&quot;.join(error_messages)
 
 def isWellFormedXml(field_data, all_data):
     from xml.dom.minidom import parseString
     try:
         parseString(field_data)
     except Exception, e: # Naked except because we're not sure what will be thrown
-        raise ValidationError, _(&quot;Badly formed XML: %s&quot;) % str(e)
+        raise ValidationError, gettext(&quot;Badly formed XML: %s&quot;) % str(e)
 
 def isWellFormedXmlFragment(field_data, all_data):
     isWellFormedXml('&lt;root&gt;%s&lt;/root&gt;' % field_data, all_data)
@@ -200,19 +199,19 @@ def isExistingURL(field_data, all_data):
     try:
         u = urllib2.urlopen(field_data)
     except ValueError:
-        raise ValidationError, _(&quot;Invalid URL: %s&quot;) % field_data
+        raise ValidationError, gettext(&quot;Invalid URL: %s&quot;) % field_data
     except urllib2.HTTPError, e:
         # 401s are valid; they just mean authorization is required.
         if e.code not in ('401',):
-            raise ValidationError, _(&quot;The URL %s is a broken link.&quot;) % field_data
+            raise ValidationError, gettext(&quot;The URL %s is a broken link.&quot;) % field_data
     except: # urllib2.URLError, httplib.InvalidURL, etc.
-        raise ValidationError, _(&quot;The URL %s is a broken link.&quot;) % field_data
+        raise ValidationError, gettext(&quot;The URL %s is a broken link.&quot;) % field_data
 
 def isValidUSState(field_data, all_data):
     &quot;Checks that the given string is a valid two-letter U.S. state abbreviation&quot;
     states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY']
     if field_data.upper() not in states:
-        raise ValidationError, _(&quot;Enter a valid U.S. state abbreviation.&quot;)
+        raise ValidationError, gettext(&quot;Enter a valid U.S. state abbreviation.&quot;)
 
 def hasNoProfanities(field_data, all_data):
     &quot;&quot;&quot;
@@ -334,7 +333,7 @@ class IsAPowerOf:
         from math import log
         val = log(int(field_data)) / log(self.power_of)
         if val != int(val):
-            raise ValidationError, _(&quot;This value must be a power of %s.&quot;) % self.power_of
+            raise ValidationError, gettext(&quot;This value must be a power of %s.&quot;) % self.power_of
 
 class IsValidFloat:
     def __init__(self, max_digits, decimal_places):
@@ -345,9 +344,9 @@ class IsValidFloat:
         try:
             float(data)
         except ValueError:
-            raise ValidationError, _(&quot;Please enter a valid decimal number.&quot;)
+            raise ValidationError, gettext(&quot;Please enter a valid decimal number.&quot;)
         if len(data) &gt; (self.max_digits + 1):
-            raise ValidationError, ngettext( &quot;Please enter a valid decimal number with at most %s total digit.&quot;,
+            raise ValidationError, ngettext(&quot;Please enter a valid decimal number with at most %s total digit.&quot;,
                 &quot;Please enter a valid decimal number with at most %s total digits.&quot;, self.max_digits) % self.max_digits
         if '.' in data and len(data.split('.')[1]) &gt; self.decimal_places:
             raise ValidationError, ngettext(&quot;Please enter a valid decimal number with at most %s decimal place.&quot;,
@@ -424,10 +423,10 @@ class URLMimeTypeCheck:
         try:
             info = urllib2.urlopen(field_data).info()
         except (urllib2.HTTPError, urllib2.URLError):
-            raise URLMimeTypeCheck.CouldNotRetrieve, _(&quot;Could not retrieve anything from %s.&quot;) % field_data
+            raise URLMimeTypeCheck.CouldNotRetrieve, gettext(&quot;Could not retrieve anything from %s.&quot;) % field_data
         content_type = info['content-type']
         if content_type not in self.mime_type_list:
-            raise URLMimeTypeCheck.InvalidContentType, _(&quot;The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.&quot;) % {
+            raise URLMimeTypeCheck.InvalidContentType, gettext(&quot;The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.&quot;) % {
                 'url': field_data, 'contenttype': content_type}
 
 class RelaxNGCompact:
@@ -447,9 +446,9 @@ class RelaxNGCompact:
         fp = open(filename, 'w')
         fp.write(field_data)
         fp.close()
-        if not os.path.exists(JING_PATH):
-            raise Exception, &quot;%s not found!&quot; % JING_PATH
-        p = os.popen('%s -c %s %s' % (JING_PATH, self.schema_path, filename))
+        if not os.path.exists(settings.JING_PATH):
+            raise Exception, &quot;%s not found!&quot; % settings.JING_PATH
+        p = os.popen('%s -c %s %s' % (settings.JING_PATH, self.schema_path, filename))
         errors = [line.strip() for line in p.readlines()]
         p.close()
         os.unlink(filename)</diff>
      <filename>django/core/validators.py</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,13 @@ that custom headers are prefxed with &quot;X-&quot;).
 Next time you're at slashdot.org, watch out for X-Fry and X-Bender. :)
 &quot;&quot;&quot;
 
-def populate_xheaders(request, response, package, python_module_name, object_id):
+def populate_xheaders(request, response, model, object_id):
     &quot;&quot;&quot;
     Adds the &quot;X-Object-Type&quot; and &quot;X-Object-Id&quot; headers to the given
-    HttpResponse according to the given package, python_module_name and
-    object_id -- but only if the given HttpRequest object has an IP address
-    within the INTERNAL_IPS setting.
+    HttpResponse according to the given model and object_id -- but only if the
+    given HttpRequest object has an IP address within the INTERNAL_IPS setting.
     &quot;&quot;&quot;
-    from django.conf.settings import INTERNAL_IPS
-    if request.META.get('REMOTE_ADDR') in INTERNAL_IPS:
-        response['X-Object-Type'] = &quot;%s.%s&quot; % (package, python_module_name)
+    from django.conf import settings
+    if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
+        response['X-Object-Type'] = &quot;%s.%s&quot; % (model._meta.app_label, model._meta.object_name.lower())
         response['X-Object-Id'] = str(object_id)</diff>
      <filename>django/core/xheaders.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 from django.conf import settings
 from django.core.cache import cache
 from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers
-from django.utils.httpwrappers import HttpResponseNotModified
+from django.http import HttpResponseNotModified
 
 class CacheMiddleware:
     &quot;&quot;&quot;</diff>
      <filename>django/middleware/cache.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 from django.conf import settings
-from django.utils import httpwrappers
+from django import http
 from django.core.mail import mail_managers
 import md5, os
 
@@ -27,10 +27,11 @@ class CommonMiddleware:
         if request.META.has_key('HTTP_USER_AGENT'):
             for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
                 if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
-                    return httpwrappers.HttpResponseForbidden('&lt;h1&gt;Forbidden&lt;/h1&gt;')
+                    return http.HttpResponseForbidden('&lt;h1&gt;Forbidden&lt;/h1&gt;')
 
         # Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW
-        old_url = [request.META.get('HTTP_HOST', ''), request.path]
+        host = http.get_host(request)
+        old_url = [host, request.path]
         new_url = old_url[:]
         if settings.PREPEND_WWW and old_url[0] and not old_url[0].startswith('www.'):
             new_url[0] = 'www.' + old_url[0]
@@ -46,7 +47,7 @@ class CommonMiddleware:
                 newurl = new_url[1]
             if request.GET:
                 newurl += '?' + request.GET.urlencode()
-            return httpwrappers.HttpResponsePermanentRedirect(newurl)
+            return http.HttpResponsePermanentRedirect(newurl)
 
         return None
 
@@ -56,7 +57,7 @@ class CommonMiddleware:
             if settings.SEND_BROKEN_LINK_EMAILS:
                 # If the referrer was from an internal link or a non-search-engine site,
                 # send a note to the managers.
-                domain = request.META['HTTP_HOST']
+                domain = http.get_host(request)
                 referer = request.META.get('HTTP_REFERER', None)
                 is_internal = referer and (domain in referer)
                 path = request.get_full_path()
@@ -69,7 +70,7 @@ class CommonMiddleware:
         if settings.USE_ETAGS:
             etag = md5.new(response.content).hexdigest()
             if request.META.get('HTTP_IF_NONE_MATCH') == etag:
-                response = httpwrappers.HttpResponseNotModified()
+                response = http.HttpResponseNotModified()
             else:
                 response['ETag'] = etag
 </diff>
      <filename>django/middleware/common.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 from django.conf import settings
-from django.utils import httpwrappers
+from django import http
 
 class XViewMiddleware:
     &quot;&quot;&quot;
@@ -12,6 +12,6 @@ class XViewMiddleware:
         documentation module to lookup the view function for an arbitrary page.
         &quot;&quot;&quot;
         if request.META['REQUEST_METHOD'] == 'HEAD' and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
-            response = httpwrappers.HttpResponse()
+            response = http.HttpResponse()
             response['X-View'] = &quot;%s.%s&quot; % (view_func.__module__, view_func.__name__)
             return response</diff>
      <filename>django/middleware/doc.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
-from django.conf.settings import INSTALLED_APPS
+from django.conf import settings
 
-for a in INSTALLED_APPS:
+for a in settings.INSTALLED_APPS:
     try:
         __path__.extend(__import__(a + '.templatetags', '', '', ['']).__path__)
     except ImportError:</diff>
      <filename>django/templatetags/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
-from django.core.template import Node, NodeList, Template, Context, resolve_variable
-from django.core.template import TemplateSyntaxError, TokenParser, Library
-from django.core.template import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR
+from django.template import Node, NodeList, Template, Context, resolve_variable
+from django.template import TemplateSyntaxError, TokenParser, Library
+from django.template import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR
 from django.utils import translation
 import re, sys
 
@@ -11,8 +11,8 @@ class GetAvailableLanguagesNode(Node):
         self.variable = variable
 
     def render(self, context):
-        from django.conf.settings import LANGUAGES
-        context[self.variable] = LANGUAGES
+        from django.conf import settings
+        context[self.variable] = settings.LANGUAGES
         return ''
 
 class GetCurrentLanguageNode(Node):</diff>
      <filename>django/templatetags/i18n.py</filename>
    </modified>
    <modified>
      <diff>@@ -80,8 +80,17 @@ def patch_response_headers(response, cache_timeout=None):
     if not response.has_header('Expires'):
         expires = now + datetime.timedelta(0, cache_timeout)
         response['Expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S GMT')
+    if cache_timeout &lt; 0:
+        cache_timeout = 0 # Can't have max-age negative
     patch_cache_control(response, max_age=cache_timeout)
 
+def add_never_cache_headers(response):
+    &quot;&quot;&quot;
+    Add headers to a response to indicate that 
+    a page should never be cached.
+    &quot;&quot;&quot;
+    patch_response_headers(response, cache_timeout=-1)
+
 def patch_vary_headers(response, newheaders):
     &quot;&quot;&quot;
     Adds (or updates) the &quot;Vary&quot; header in the given HttpResponse object.</diff>
      <filename>django/utils/cache.py</filename>
    </modified>
    <modified>
      <diff>@@ -40,6 +40,43 @@ class MergeDict:
                 return True
         return False
 
+class SortedDict(dict):
+    &quot;A dictionary that keeps its keys in the order in which they're inserted.&quot;
+    def __init__(self, data={}):
+        dict.__init__(self, data)
+        self.keyOrder = data.keys()
+
+    def __setitem__(self, key, value):
+        dict.__setitem__(self, key, value)
+        if key not in self.keyOrder:
+            self.keyOrder.append(key)
+
+    def __delitem__(self, key):
+        dict.__delitem__(self, key)
+        self.keyOrder.remove(key)
+
+    def __iter__(self):
+        for k in self.keyOrder:
+            yield k
+
+    def items(self):
+        return zip(self.keyOrder, self.values())
+
+    def keys(self):
+        return self.keyOrder[:]
+
+    def values(self):
+        return [dict.__getitem__(self,k) for k in self.keyOrder]
+
+    def update(self, dict):
+        for k, v in dict.items():
+            self.__setitem__(k, v)
+
+    def setdefault(self, key, default):
+        if key not in self.keyOrder:
+            self.keyOrder.append(key)
+        return dict.setdefault(self, key, default)
+
 class MultiValueDictKeyError(KeyError):
     pass
 
@@ -193,4 +230,4 @@ class DotExpandedDict(dict):
             try:
                 current[bits[-1]] = v
             except TypeError: # Special-case if current isn't a dict.
-                current = {bits[-1]: v}
+                current = {bits[-1] : v}</diff>
      <filename>django/utils/datastructures.py</filename>
    </modified>
    <modified>
      <diff>@@ -21,8 +21,6 @@ http://diveintomark.org/archives/2004/02/04/incompatible-rss
 from django.utils.xmlutils import SimplerXMLGenerator
 import datetime, re, time
 import email.Utils
-from xml.dom import minidom
-from xml.parsers.expat import ExpatError
 
 def rfc2822_date(date):
     return email.Utils.formatdate(time.mktime(date.timetuple()))
@@ -158,9 +156,11 @@ class Rss201rev2Feed(RssFeed):
                 handler.addQuickElement(u&quot;description&quot;, item['description'])
 
             # Author information.
-            if item['author_email'] is not None and item['author_name'] is not None:
-                handler.addQuickElement(u&quot;author&quot;, u&quot;%s (%s)&quot; % \
+            if item[&quot;author_name&quot;] and item[&quot;author_email&quot;]:
+                handler.addQuickElement(u&quot;author&quot;, &quot;%s (%s)&quot; % \
                     (item['author_email'], item['author_name']))
+            elif item[&quot;author_email&quot;]:
+                handler.addQuickElement(u&quot;author&quot;, item[&quot;author_email&quot;])
 
             if item['pubdate'] is not None:
                 handler.addQuickElement(u&quot;pubDate&quot;, rfc2822_date(item['pubdate']).decode('ascii'))</diff>
      <filename>django/utils/feedgenerator.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,14 +24,14 @@ def lazy(func, *resultclasses):
         # the evaluation and store the result. Afterwards, the result
         # is delivered directly. So the result is memoized.
         def __init__(self, args, kw):
-           self.__func = func
-           self.__args = args
-           self.__kw = kw
-           self.__dispatch = {}
-           for resultclass in resultclasses:
-               self.__dispatch[resultclass] = {}
-               for (k, v) in resultclass.__dict__.items():
-                   setattr(self, k, self.__promise__(resultclass, k, v))
+            self.__func = func
+            self.__args = args
+            self.__kw = kw
+            self.__dispatch = {}
+            for resultclass in resultclasses:
+                self.__dispatch[resultclass] = {}
+                for (k, v) in resultclass.__dict__.items():
+                    setattr(self, k, self.__promise__(resultclass, k, v))
 
         def __promise__(self, klass, funcname, func):
             # Builds a wrapper around some magic method and registers that magic</diff>
      <filename>django/utils/functional.py</filename>
    </modified>
    <modified>
      <diff>@@ -25,7 +25,7 @@ def escape(html):
     &quot;Returns the given HTML with ampersands, quotes and carets encoded&quot;
     if not isinstance(html, basestring):
         html = str(html)
-    return html.replace('&amp;', '&amp;amp;').replace('&lt;', '&amp;lt;').replace('&gt;', '&amp;gt;').replace('&quot;', '&amp;quot;')
+    return html.replace('&amp;', '&amp;amp;').replace('&lt;', '&amp;lt;').replace('&gt;', '&amp;gt;').replace('&quot;', '&amp;quot;').replace(&quot;'&quot;, '&amp;#39;')
 
 def linebreaks(value):
     &quot;Converts newlines into &lt;p&gt; and &lt;br /&gt;s&quot;</diff>
      <filename>django/utils/html.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 import re
 
-from django.conf.settings import DEFAULT_CHARSET
+from django.conf import settings
 
 # Capitalizes the first letter of a string.
 capfirst = lambda x: x and x[0].upper() + x[1:]
@@ -100,7 +100,7 @@ def javascript_quote(s):
         return r&quot;\u%04x&quot; % ord(match.group(1))
 
     if type(s) == str:
-        s = s.decode(DEFAULT_CHARSET)
+        s = s.decode(settings.DEFAULT_CHARSET)
     elif type(s) != unicode:
         raise TypeError, s
     s = s.replace('\\', '\\\\')</diff>
      <filename>django/utils/text.py</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,7 @@ def timesince(d, now=None):
     chunks = (
       (60 * 60 * 24 * 365, lambda n: ngettext('year', 'years', n)),
       (60 * 60 * 24 * 30, lambda n: ngettext('month', 'months', n)),
+      (60 * 60 * 24 * 7, lambda n : ngettext('week', 'weeks', n)),
       (60 * 60 * 24, lambda n : ngettext('day', 'days', n)),
       (60 * 60, lambda n: ngettext('hour', 'hours', n)),
       (60, lambda n: ngettext('minute', 'minutes', n))</diff>
      <filename>django/utils/timesince.py</filename>
    </modified>
    <modified>
      <diff>@@ -115,7 +115,7 @@ def translation(language):
     if sys.version_info &lt; (2, 4):
         klass = DjangoTranslation23
 
-    globalpath = os.path.join(os.path.dirname(settings.__file__), 'locale')
+    globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
 
     parts = settings.SETTINGS_MODULE.split('.')
     project = __import__(parts[0], {}, {}, [])
@@ -209,8 +209,8 @@ def get_language():
         except AttributeError:
             pass
     # If we don't have a real translation object, assume it's the default language.
-    from django.conf.settings import LANGUAGE_CODE
-    return LANGUAGE_CODE
+    from django.conf import settings
+    return settings.LANGUAGE_CODE
 
 def catalog():
     &quot;&quot;&quot;
@@ -275,7 +275,7 @@ def check_for_language(lang_code):
     only used for language codes from either the cookies or session.
     &quot;&quot;&quot;
     from django.conf import settings
-    globalpath = os.path.join(os.path.dirname(settings.__file__), 'locale')
+    globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
     if gettext_module.find('django', globalpath, [to_locale(lang_code)]) is not None:
         return True
     else:
@@ -289,7 +289,7 @@ def get_language_from_request(request):
     &quot;&quot;&quot;
     global _accepted
     from django.conf import settings
-    globalpath = os.path.join(os.path.dirname(settings.__file__), 'locale')
+    globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
     supported = dict(settings.LANGUAGES)
 
     if hasattr(request, 'session'):
@@ -346,16 +346,16 @@ def get_date_formats():
     technical message ID to store date and time formats. If it doesn't contain
     one, the formats provided in the settings will be used.
     &quot;&quot;&quot;
-    from django.conf.settings import DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT
+    from django.conf import settings
     date_format = _('DATE_FORMAT')
     datetime_format = _('DATETIME_FORMAT')
     time_format = _('TIME_FORMAT')
     if date_format == 'DATE_FORMAT':
-        date_format = DATE_FORMAT
+        date_format = settings.DATE_FORMAT
     if datetime_format == 'DATETIME_FORMAT':
-        datetime_format = DATETIME_FORMAT
+        datetime_format = settings.DATETIME_FORMAT
     if time_format == 'TIME_FORMAT':
-        time_format = TIME_FORMAT
+        time_format = settings.TIME_FORMAT
     return (date_format, datetime_format, time_format)
 
 def install():
@@ -384,7 +384,7 @@ def templatize(src):
     does so by translating the Django translation tags into standard gettext
     function invocations.
     &quot;&quot;&quot;
-    from django.core.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK
+    from django.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK
     out = StringIO()
     intrans = False
     inplural = False
@@ -457,3 +457,13 @@ def templatize(src):
             else:
                 out.write(blankout(t.contents, 'X'))
     return out.getvalue()
+
+def string_concat(*strings):
+    &quot;&quot;&quot;&quot;
+    lazy variant of string concatenation, needed for translations that are
+    constructed from multiple parts. Handles lazy strings and non-strings by
+    first turning all arguments to strings, before joining them.
+    &quot;&quot;&quot;
+    return ''.join([str(el) for el in strings])
+
+string_concat = lazy(string_concat, str)</diff>
      <filename>django/utils/translation.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 from django.conf import settings
-from django.core.template import Template, Context, TemplateDoesNotExist
+from django.template import Template, Context, TemplateDoesNotExist
 from django.utils.html import escape
-from django.utils.httpwrappers import HttpResponseServerError, HttpResponseNotFound
+from django.http import HttpResponseServerError, HttpResponseNotFound
 import os, re
 from itertools import count, izip
 from os.path import dirname, join as pathjoin
@@ -72,7 +72,7 @@ def technical_500_response(request, exc_type, exc_value, tb):
     template_does_not_exist = False
     loader_debug_info = None
     if issubclass(exc_type, TemplateDoesNotExist):
-        from django.core.template.loader import template_source_loaders
+        from django.template.loader import template_source_loaders
         template_does_not_exist = True
         loader_debug_info = []
         for loader in template_source_loaders:
@@ -641,8 +641,8 @@ EMPTY_URLCONF_TEMPLATE = &quot;&quot;&quot;
 &lt;div id=&quot;instructions&quot;&gt;
   &lt;p&gt;Of course, you haven't actually done any work yet. Here's what to do next:&lt;/p&gt;
   &lt;ul&gt;
-    &lt;li&gt;Edit the &lt;code&gt;DATABASE_*&lt;/code&gt; settings in &lt;code&gt;{{ project_name }}/settings.py&lt;/code&gt;.&lt;/li&gt;
-    &lt;li&gt;Start your first app by running &lt;code&gt;{{ project_name }}/manage.py startapp [appname]&lt;/code&gt;.&lt;/li&gt;
+    &lt;li&gt;If you plan to use a database, edit the &lt;code&gt;DATABASE_*&lt;/code&gt; settings in &lt;code&gt;{{ project_name }}/settings.py&lt;/code&gt;.&lt;/li&gt;
+    &lt;li&gt;Start your first app by running &lt;code&gt;python {{ project_name }}/manage.py startapp [appname]&lt;/code&gt;.&lt;/li&gt;
   &lt;/ul&gt;
 &lt;/div&gt;
 </diff>
      <filename>django/views/debug.py</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ account on caching -- just like the middleware does.
 import re
 
 from django.utils.decorators import decorator_from_middleware
-from django.utils.cache import patch_cache_control
+from django.utils.cache import patch_cache_control, add_never_cache_headers
 from django.middleware.cache import CacheMiddleware
 
 cache_page = decorator_from_middleware(CacheMiddleware)
@@ -31,3 +31,13 @@ def cache_control(**kwargs):
 
     return _cache_controller
 
+def never_cache(view_func):
+    &quot;&quot;&quot;
+    Decorator that adds headers to a response so that it will
+    never be cached.
+    &quot;&quot;&quot;
+    def _wrapped_view_func(request, *args, **kwargs):
+        response = view_func(request, *args, **kwargs)
+        add_never_cache_headers(response)
+        return response
+    return _wrapped_view_func</diff>
      <filename>django/views/decorators/cache.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ Decorators for views based on HTTP headers.
 
 from django.utils.decorators import decorator_from_middleware
 from django.middleware.http import ConditionalGetMiddleware
-from django.utils.httpwrappers import HttpResponseForbidden
+from django.http import HttpResponseForbidden
 
 conditional_page = decorator_from_middleware(ConditionalGetMiddleware)
 </diff>
      <filename>django/views/decorators/http.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,69 +1,89 @@
-from django.core.exceptions import Http404, ObjectDoesNotExist
-from django.core.template import Context, loader
-from django.models.core import sites, contenttypes
-from django.utils import httpwrappers
+from django.core.exceptions import ObjectDoesNotExist
+from django.template import Context, loader
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.sites.models import Site
+from django import http
 
 def shortcut(request, content_type_id, object_id):
     &quot;Redirect to an object's page based on a content-type ID and an object ID.&quot;
     # Look up the object, making sure it's got a get_absolute_url() function.
     try:
-        content_type = contenttypes.get_object(pk=content_type_id)
+        content_type = ContentType.objects.get(pk=content_type_id)
         obj = content_type.get_object_for_this_type(pk=object_id)
     except ObjectDoesNotExist:
-        raise Http404, &quot;Content type %s object %s doesn't exist&quot; % (content_type_id, object_id)
+        raise http.Http404, &quot;Content type %s object %s doesn't exist&quot; % (content_type_id, object_id)
     try:
         absurl = obj.get_absolute_url()
     except AttributeError:
-        raise Http404, &quot;%s objects don't have get_absolute_url() methods&quot; % content_type.name
+        raise http.Http404, &quot;%s objects don't have get_absolute_url() methods&quot; % content_type.name
 
     # Try to figure out the object's domain, so we can do a cross-site redirect
     # if necessary.
 
     # If the object actually defines a domain, we're done.
     if absurl.startswith('http://'):
-        return httpwrappers.HttpResponseRedirect(absurl)
+        return http.HttpResponseRedirect(absurl)
 
     object_domain = None
 
-    # Next, look for an many-to-many relationship to sites
-    if hasattr(obj, 'get_site_list'):
-        site_list = obj.get_site_list()
-        if site_list:
-            object_domain = site_list[0].domain
+    # Otherwise, we need to introspect the object's relationships for a
+    # relation to the Site object
+    opts = obj._meta
 
-    # Next, look for a many-to-one relationship to sites
-    elif hasattr(obj, 'get_site'):
+    # First, look for an many-to-many relationship to sites
+    for field in opts.many_to_many:
+        if field.rel.to is Site:
+            try:
+                object_domain = getattr(obj, field.name).all()[0].domain
+            except Site.DoesNotExist:
+                pass
+            if object_domain is not None:
+                break
+
+    # Next look for a many-to-one relationship to site
+    if object_domain is None:
+        for field in obj._meta.fields:
+            if field.rel and field.rel.to is Site:
+                try:
+                    object_domain = getattr(obj, field.name).domain
+                except Site.DoesNotExist:
+                    pass
+                if object_domain is not None:
+                    break
+
+    # Fall back to the current site (if possible)
+    if object_domain is None:
         try:
-            object_domain = obj.get_site().domain
-        except sites.SiteDoesNotExist:
+            object_domain = Site.objects.get_current().domain
+        except Site.DoesNotExist:
             pass
 
-    # Then, fall back to the current site (if possible)
+    # If all that malarkey found an object domain, use it; otherwise fall back
+    # to whatever get_absolute_url() returned.
+    if object_domain is not None:
+        return http.HttpResponseRedirect('http://%s%s' % (object_domain, absurl))
     else:
-        try:
-            object_domain = sites.get_current().domain
-        except sites.SiteDoesNotExist:
-            # Finally, give up and use a URL without the domain name
-            return httpwrappers.HttpResponseRedirect(obj.get_absolute_url())
-    return httpwrappers.HttpResponseRedirect('http://%s%s' % (object_domain, obj.get_absolute_url()))
+        return http.HttpResponseRedirect(absurl)
 
-def page_not_found(request, template_name='404'):
+def page_not_found(request, template_name='404.html'):
     &quot;&quot;&quot;
     Default 404 handler, which looks for the requested URL in the redirects
     table, redirects if found, and displays 404 page if not redirected.
 
-    Templates: `404`
-    Context: None
+    Templates: `404.html`
+    Context:
+        request_path
+            The path of the requested URL (e.g., '/app/pages/bad_page/')
     &quot;&quot;&quot;
     t = loader.get_template(template_name)
-    return httpwrappers.HttpResponseNotFound(t.render(Context()))
+    return http.HttpResponseNotFound(t.render(Context({'request_path': request.path})))
 
-def server_error(request, template_name='500'):
+def server_error(request, template_name='500.html'):
     &quot;&quot;&quot;
     500 error handler.
 
-    Templates: `500`
+    Templates: `500.html`
     Context: None
     &quot;&quot;&quot;
     t = loader.get_template(template_name)
-    return httpwrappers.HttpResponseServerError(t.render(Context()))
+    return http.HttpResponseServerError(t.render(Context()))</diff>
      <filename>django/views/defaults.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,20 @@
-from django import models
 from django.core.xheaders import populate_xheaders
-from django.core.template import loader
-from django.core import formfields, meta
-from django.views.auth.login import redirect_to_login
-from django.core.extensions import DjangoContext
+from django.template import loader
+from django import forms
+from django.db.models import FileField
+from django.contrib.auth.views import redirect_to_login
+from django.template import RequestContext
 from django.core.paginator import ObjectPaginator, InvalidPage
-from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
-from django.core.exceptions import Http404, ObjectDoesNotExist, ImproperlyConfigured
+from django.http import Http404, HttpResponse, HttpResponseRedirect
+from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
 
-def create_object(request, app_label, module_name, template_name=None,
+def create_object(request, model, template_name=None,
         template_loader=loader, extra_context={}, post_save_redirect=None,
         login_required=False, follow=None, context_processors=None):
     &quot;&quot;&quot;
     Generic object-creation function.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_form``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_form.html``
     Context:
         form
             the form wrapper for the object
@@ -22,13 +22,12 @@ def create_object(request, app_label, module_name, template_name=None,
     if login_required and request.user.is_anonymous():
         return redirect_to_login(request.path)
 
-    mod = models.get_module(app_label, module_name)
-    manipulator = mod.AddManipulator(follow=follow)
+    manipulator = model.AddManipulator(follow=follow)
     if request.POST:
         # If data was POSTed, we're trying to create a new object
         new_data = request.POST.copy()
 
-        if mod.Klass._meta.has_field_type(meta.FileField):
+        if model._meta.has_field_type(FileField):
             new_data.update(request.FILES)
 
         # Check for errors
@@ -40,7 +39,7 @@ def create_object(request, app_label, module_name, template_name=None,
             new_object = manipulator.save(new_data)
 
             if not request.user.is_anonymous():
-                request.user.add_message(&quot;The %s was created successfully.&quot; % mod.Klass._meta.verbose_name)
+                request.user.message_set.create(message=&quot;The %s was created successfully.&quot; % model._meta.verbose_name)
 
             # Redirect to the new object: first by trying post_save_redirect,
             # then by obj.get_absolute_url; fail if neither works.
@@ -56,11 +55,11 @@ def create_object(request, app_label, module_name, template_name=None,
         new_data = manipulator.flatten_data()
 
     # Create the FormWrapper, template, context, response
-    form = formfields.FormWrapper(manipulator, new_data, errors)
+    form = forms.FormWrapper(manipulator, new_data, errors)
     if not template_name:
-        template_name = &quot;%s/%s_form&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_form.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         'form': form,
     }, context_processors)
     for key, value in extra_context.items():
@@ -70,15 +69,15 @@ def create_object(request, app_label, module_name, template_name=None,
             c[key] = value
     return HttpResponse(t.render(c))
 
-def update_object(request, app_label, module_name, object_id=None, slug=None,
+def update_object(request, model, object_id=None, slug=None,
         slug_field=None, template_name=None, template_loader=loader,
-        extra_lookup_kwargs={}, extra_context={}, post_save_redirect=None,
+        extra_context={}, post_save_redirect=None,
         login_required=False, follow=None, context_processors=None,
         template_object_name='object'):
     &quot;&quot;&quot;
     Generic object-update function.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_form``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_form.html``
     Context:
         form
             the form wrapper for the object
@@ -88,23 +87,20 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
     if login_required and request.user.is_anonymous():
         return redirect_to_login(request.path)
 
-    mod = models.get_module(app_label, module_name)
-
     # Look up the object to be edited
     lookup_kwargs = {}
     if object_id:
-        lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id
+        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
     elif slug and slug_field:
         lookup_kwargs['%s__exact' % slug_field] = slug
     else:
         raise AttributeError(&quot;Generic edit view must be called with either an object_id or a slug/slug_field&quot;)
-    lookup_kwargs.update(extra_lookup_kwargs)
     try:
-        object = mod.get_object(**lookup_kwargs)
+        object = model.objects.get(**lookup_kwargs)
     except ObjectDoesNotExist:
-        raise Http404(&quot;%s.%s does not exist for %s&quot; % (app_label, module_name, lookup_kwargs))
+        raise Http404, &quot;No %s found for %s&quot; % (model._meta.verbose_name, lookup_kwargs)
 
-    manipulator = mod.ChangeManipulator(object.id, follow=follow)
+    manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.name), follow=follow)
 
     if request.POST:
         new_data = request.POST.copy()
@@ -114,7 +110,7 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
             manipulator.save(new_data)
 
             if not request.user.is_anonymous():
-                request.user.add_message(&quot;The %s was updated successfully.&quot; % mod.Klass._meta.verbose_name)
+                request.user.message_set.create(message=&quot;The %s was updated successfully.&quot; % model._meta.verbose_name)
 
             # Do a post-after-redirect so that reload works, etc.
             if post_save_redirect:
@@ -128,11 +124,11 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
         # This makes sure the form acurate represents the fields of the place.
         new_data = manipulator.flatten_data()
 
-    form = formfields.FormWrapper(manipulator, new_data, errors)
+    form = forms.FormWrapper(manipulator, new_data, errors)
     if not template_name:
-        template_name = &quot;%s/%s_form&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_form.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         'form': form,
         template_object_name: object,
     }, context_processors)
@@ -142,12 +138,12 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
         else:
             c[key] = value
     response = HttpResponse(t.render(c))
-    populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+    populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
     return response
 
-def delete_object(request, app_label, module_name, post_delete_redirect,
+def delete_object(request, model, post_delete_redirect,
         object_id=None, slug=None, slug_field=None, template_name=None,
-        template_loader=loader, extra_lookup_kwargs={}, extra_context={},
+        template_loader=loader, extra_context={},
         login_required=False, context_processors=None, template_object_name='object'):
     &quot;&quot;&quot;
     Generic object-delete function.
@@ -156,7 +152,7 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
     fetched using GET; for safty, deletion will only be performed if this
     view is POSTed.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_confirm_delete``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_confirm_delete.html``
     Context:
         object
             the original object being deleted
@@ -164,32 +160,29 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
     if login_required and request.user.is_anonymous():
         return redirect_to_login(request.path)
 
-    mod = models.get_module(app_label, module_name)
-
     # Look up the object to be edited
     lookup_kwargs = {}
     if object_id:
-        lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id
+        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
     elif slug and slug_field:
         lookup_kwargs['%s__exact' % slug_field] = slug
     else:
         raise AttributeError(&quot;Generic delete view must be called with either an object_id or a slug/slug_field&quot;)
-    lookup_kwargs.update(extra_lookup_kwargs)
     try:
-        object = mod.get_object(**lookup_kwargs)
+        object = model._default_manager.get(**lookup_kwargs)
     except ObjectDoesNotExist:
-        raise Http404(&quot;%s.%s does not exist for %s&quot; % (app_label, module_name, lookup_kwargs))
+        raise Http404, &quot;No %s found for %s&quot; % (model._meta.app_label, lookup_kwargs)
 
     if request.META['REQUEST_METHOD'] == 'POST':
         object.delete()
         if not request.user.is_anonymous():
-            request.user.add_message(&quot;The %s was deleted.&quot; % mod.Klass._meta.verbose_name)
+            request.user.message_set.create(message=&quot;The %s was deleted.&quot; % model._meta.verbose_name)
         return HttpResponseRedirect(post_delete_redirect)
     else:
         if not template_name:
-            template_name = &quot;%s/%s_confirm_delete&quot; % (app_label, module_name)
+            template_name = &quot;%s/%s_confirm_delete.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
         t = template_loader.get_template(template_name)
-        c = DjangoContext(request, {
+        c = RequestContext(request, {
             template_object_name: object,
         }, context_processors)
         for key, value in extra_context.items():
@@ -198,5 +191,5 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
             else:
                 c[key] = value
         response = HttpResponse(t.render(c))
-        populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+        populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
         return response</diff>
      <filename>django/views/generic/create_update.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,44 +1,37 @@
-from django.core.template import loader
-from django.core.exceptions import Http404, ObjectDoesNotExist
-from django.core.extensions import DjangoContext
+from django.template import loader, RequestContext
+from django.core.exceptions import ObjectDoesNotExist
 from django.core.xheaders import populate_xheaders
-from django.models import get_module
-from django.utils.httpwrappers import HttpResponse
+from django.http import Http404, HttpResponse
 import datetime, time
 
-def archive_index(request, app_label, module_name, date_field, num_latest=15,
-        template_name=None, template_loader=loader, extra_lookup_kwargs={},
+def archive_index(request, queryset, date_field, num_latest=15,
+        template_name=None, template_loader=loader,
         extra_context={}, allow_empty=False, context_processors=None):
     &quot;&quot;&quot;
     Generic top-level archive of date-based objects.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_archive``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_archive.html``
     Context:
         date_list
             List of years
         latest
             Latest N (defaults to 15) objects by date
     &quot;&quot;&quot;
-    mod = get_module(app_label, module_name)
-    lookup_kwargs = {'%s__lte' % date_field: datetime.datetime.now()}
-    lookup_kwargs.update(extra_lookup_kwargs)
-    date_list = getattr(mod, &quot;get_%s_list&quot; % date_field)('year', **lookup_kwargs)[::-1]
+    model = queryset.model
+    queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
+    date_list = queryset.dates(date_field, 'year')[::-1]
     if not date_list and not allow_empty:
-        raise Http404(&quot;No %s.%s available&quot; % (app_label, module_name))
+        raise Http404, &quot;No %s available&quot; % model._meta.verbose_name
 
     if date_list and num_latest:
-        lookup_kwargs.update({
-            'limit': num_latest,
-            'order_by': ('-' + date_field,),
-        })
-        latest = mod.get_list(**lookup_kwargs)
+        latest = queryset.order_by('-'+date_field)[:num_latest]
     else:
         latest = None
 
     if not template_name:
-        template_name = &quot;%s/%s_archive&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_archive.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         'date_list' : date_list,
         'latest' : latest,
     }, context_processors)
@@ -49,33 +42,34 @@ def archive_index(request, app_label, module_name, date_field, num_latest=15,
             c[key] = value
     return HttpResponse(t.render(c))
 
-def archive_year(request, year, app_label, module_name, date_field,
-        template_name=None, template_loader=loader, extra_lookup_kwargs={},
-        extra_context={}, allow_empty=False, context_processors=None):
+def archive_year(request, year, queryset, date_field, template_name=None,
+        template_loader=loader, extra_context={}, allow_empty=False,
+        context_processors=None):
     &quot;&quot;&quot;
     Generic yearly archive view.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_archive_year``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_archive_year.html``
     Context:
         date_list
             List of months in this year with objects
         year
             This year
     &quot;&quot;&quot;
-    mod = get_module(app_label, module_name)
+    model = queryset.model
     now = datetime.datetime.now()
+
     lookup_kwargs = {'%s__year' % date_field: year}
+
     # Only bother to check current date if the year isn't in the past.
     if int(year) &gt;= now.year:
         lookup_kwargs['%s__lte' % date_field] = now
-    lookup_kwargs.update(extra_lookup_kwargs)
-    date_list = getattr(mod, &quot;get_%s_list&quot; % date_field)('month', **lookup_kwargs)
+    date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
     if not date_list and not allow_empty:
         raise Http404
     if not template_name:
-        template_name = &quot;%s/%s_archive_year&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_archive_year.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         'date_list': date_list,
         'year': year,
     }, context_processors)
@@ -86,14 +80,14 @@ def archive_year(request, year, app_label, module_name, date_field,
             c[key] = value
     return HttpResponse(t.render(c))
 
-def archive_month(request, year, month, app_label, module_name, date_field,
+def archive_month(request, year, month, queryset, date_field,
         month_format='%b', template_name=None, template_loader=loader,
-        extra_lookup_kwargs={}, extra_context={}, allow_empty=False,
-        context_processors=None, template_object_name='object'):
+        extra_context={}, allow_empty=False, context_processors=None,
+        template_object_name='object'):
     &quot;&quot;&quot;
     Generic monthly archive view.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_archive_month``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_archive_month.html``
     Context:
         month:
             (date) this month
@@ -109,8 +103,9 @@ def archive_month(request, year, month, app_label, module_name, date_field,
     except ValueError:
         raise Http404
 
-    mod = get_module(app_label, module_name)
+    model = queryset.model
     now = datetime.datetime.now()
+
     # Calculate first and last day of month, for use in a date-range lookup.
     first_day = date.replace(day=1)
     if first_day.month == 12:
@@ -118,17 +113,17 @@ def archive_month(request, year, month, app_label, module_name, date_field,
     else:
         last_day = first_day.replace(month=first_day.month + 1)
     lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
+
     # Only bother to check current date if the month isn't in the past.
     if last_day &gt;= now.date():
         lookup_kwargs['%s__lte' % date_field] = now
-    lookup_kwargs.update(extra_lookup_kwargs)
-    object_list = mod.get_list(**lookup_kwargs)
+    object_list = queryset.filter(**lookup_kwargs)
     if not object_list and not allow_empty:
         raise Http404
     if not template_name:
-        template_name = &quot;%s/%s_archive_month&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_archive_month.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         '%s_list' % template_object_name: object_list,
         'month': date,
         'next_month': (last_day &lt; datetime.date.today()) and (last_day + datetime.timedelta(days=1)) or None,
@@ -141,14 +136,61 @@ def archive_month(request, year, month, app_label, module_name, date_field,
             c[key] = value
     return HttpResponse(t.render(c))
 
-def archive_day(request, year, month, day, app_label, module_name, date_field,
+def archive_week(request, year, week, queryset, date_field,
+        template_name=None, template_loader=loader,
+        extra_context={}, allow_empty=True, context_processors=None,
+        template_object_name='object'):
+    &quot;&quot;&quot;
+    Generic weekly archive view.
+
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_archive_week.html``
+    Context:
+        week:
+            (date) this week
+        object_list:
+            list of objects published in the given week
+    &quot;&quot;&quot;
+    try:
+        date = datetime.date(*time.strptime(year+'-0-'+week, '%Y-%w-%U')[:3])
+    except ValueError:
+        raise Http404
+
+    model = queryset.model
+    now = datetime.datetime.now()
+
+    # Calculate first and last day of week, for use in a date-range lookup.
+    first_day = date
+    last_day = date + datetime.timedelta(days=7)
+    lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
+
+    # Only bother to check current date if the week isn't in the past.
+    if last_day &gt;= now.date():
+        lookup_kwargs['%s__lte' % date_field] = now
+    object_list = queryset.filter(**lookup_kwargs)
+    if not object_list and not allow_empty:
+        raise Http404
+    if not template_name:
+        template_name = &quot;%s/%s_archive_week.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
+    t = template_loader.get_template(template_name)
+    c = RequestContext(request, {
+        '%s_list' % template_object_name: object_list,
+        'week': date,
+    })
+    for key, value in extra_context.items():
+        if callable(value):
+            c[key] = value()
+        else:
+            c[key] = value
+    return HttpResponse(t.render(c))
+
+def archive_day(request, year, month, day, queryset, date_field,
         month_format='%b', day_format='%d', template_name=None,
-        template_loader=loader, extra_lookup_kwargs={}, extra_context={},
-        allow_empty=False, context_processors=None, template_object_name='object'):
+        template_loader=loader, extra_context={}, allow_empty=False,
+        context_processors=None, template_object_name='object'):
     &quot;&quot;&quot;
     Generic daily archive view.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_archive_day``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_archive_day.html``
     Context:
         object_list:
             list of objects published that day
@@ -164,22 +206,23 @@ def archive_day(request, year, month, day, app_label, module_name, date_field,
     except ValueError:
         raise Http404
 
-    mod = get_module(app_label, module_name)
+    model = queryset.model
     now = datetime.datetime.now()
+
     lookup_kwargs = {
         '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
     }
+
     # Only bother to check current date if the date isn't in the past.
     if date &gt;= now.date():
         lookup_kwargs['%s__lte' % date_field] = now
-    lookup_kwargs.update(extra_lookup_kwargs)
-    object_list = mod.get_list(**lookup_kwargs)
+    object_list = queryset.filter(**lookup_kwargs)
     if not allow_empty and not object_list:
         raise Http404
     if not template_name:
-        template_name = &quot;%s/%s_archive_day&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_archive_day.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         '%s_list' % template_object_name: object_list,
         'day': date,
         'previous_day': date - datetime.timedelta(days=1),
@@ -204,15 +247,15 @@ def archive_today(request, **kwargs):
     })
     return archive_day(request, **kwargs)
 
-def object_detail(request, year, month, day, app_label, module_name, date_field,
+def object_detail(request, year, month, day, queryset, date_field,
         month_format='%b', day_format='%d', object_id=None, slug=None,
         slug_field=None, template_name=None, template_name_field=None,
-        template_loader=loader, extra_lookup_kwargs={}, extra_context={},
-        context_processors=None, template_object_name='object'):
+        template_loader=loader, extra_context={}, context_processors=None,
+        template_object_name='object'):
     &quot;&quot;&quot;
     Generic detail view from year/month/day/slug or year/month/day/id structure.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_detail``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_detail.html``
     Context:
         object:
             the object to be detailed
@@ -222,34 +265,35 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
     except ValueError:
         raise Http404
 
-    mod = get_module(app_label, module_name)
+    model = queryset.model
     now = datetime.datetime.now()
+
     lookup_kwargs = {
         '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
     }
+
     # Only bother to check current date if the date isn't in the past.
     if date &gt;= now.date():
         lookup_kwargs['%s__lte' % date_field] = now
     if object_id:
-        lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id
+        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
     elif slug and slug_field:
         lookup_kwargs['%s__exact' % slug_field] = slug
     else:
-        raise AttributeError(&quot;Generic detail view must be called with either an object_id or a slug/slugfield&quot;)
-    lookup_kwargs.update(extra_lookup_kwargs)
+        raise AttributeError, &quot;Generic detail view must be called with either an object_id or a slug/slugfield&quot;
     try:
-        object = mod.get_object(**lookup_kwargs)
+        obj = queryset.get(**lookup_kwargs)
     except ObjectDoesNotExist:
-        raise Http404(&quot;%s.%s does not exist for %s&quot; % (app_label, module_name, lookup_kwargs))
+        raise Http404, &quot;No %s found for&quot; % model._meta.verbose_name
     if not template_name:
-        template_name = &quot;%s/%s_detail&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_detail.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     if template_name_field:
-        template_name_list = [getattr(object, template_name_field), template_name]
+        template_name_list = [getattr(obj, template_name_field), template_name]
         t = template_loader.select_template(template_name_list)
     else:
         t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
-        template_object_name: object,
+    c = RequestContext(request, {
+        template_object_name: obj,
     }, context_processors)
     for key, value in extra_context.items():
         if callable(value):
@@ -257,5 +301,5 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
         else:
             c[key] = value
     response = HttpResponse(t.render(c))
-    populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
     return response</diff>
      <filename>django/views/generic/date_based.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,16 @@
-from django import models
-from django.core.template import loader
-from django.utils.httpwrappers import HttpResponse
+from django.template import loader, RequestContext
+from django.http import Http404, HttpResponse
 from django.core.xheaders import populate_xheaders
-from django.core.extensions import DjangoContext
 from django.core.paginator import ObjectPaginator, InvalidPage
-from django.core.exceptions import Http404, ObjectDoesNotExist
+from django.core.exceptions import ObjectDoesNotExist
 
-def object_list(request, app_label, module_name, paginate_by=None, allow_empty=False,
-        template_name=None, template_loader=loader, extra_lookup_kwargs={},
+def object_list(request, queryset, paginate_by=None, allow_empty=False,
+        template_name=None, template_loader=loader,
         extra_context={}, context_processors=None, template_object_name='object'):
     &quot;&quot;&quot;
     Generic list of objects.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_list``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_list.html``
     Context:
         object_list
             list of objects
@@ -35,10 +33,10 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
         hits
             number of objects, total
     &quot;&quot;&quot;
-    mod = models.get_module(app_label, module_name)
-    lookup_kwargs = extra_lookup_kwargs.copy()
+    queryset = queryset._clone()
+    model = queryset.model
     if paginate_by:
-        paginator = ObjectPaginator(mod, lookup_kwargs, paginate_by)
+        paginator = ObjectPaginator(queryset, paginate_by)
         page = request.GET.get('page', 1)
         try:
             page = int(page)
@@ -48,7 +46,7 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
                 object_list = []
             else:
                 raise Http404
-        c = DjangoContext(request, {
+        c = RequestContext(request, {
             '%s_list' % template_object_name: object_list,
             'is_paginated': paginator.pages &gt; 1,
             'results_per_page': paginate_by,
@@ -61,12 +59,11 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
             'hits' : paginator.hits,
         }, context_processors)
     else:
-        object_list = mod.get_list(**lookup_kwargs)
-        c = DjangoContext(request, {
-            '%s_list' % template_object_name: object_list,
+        c = RequestContext(request, {
+            '%s_list' % template_object_name: queryset,
             'is_paginated': False
         }, context_processors)
-        if len(object_list) == 0 and not allow_empty:
+        if not allow_empty and len(queryset) == 0:
             raise Http404
     for key, value in extra_context.items():
         if callable(value):
@@ -74,44 +71,42 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
         else:
             c[key] = value
     if not template_name:
-        template_name = &quot;%s/%s_list&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_list.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
     return HttpResponse(t.render(c))
 
-def object_detail(request, app_label, module_name, object_id=None, slug=None,
+def object_detail(request, queryset, object_id=None, slug=None,
         slug_field=None, template_name=None, template_name_field=None,
-        template_loader=loader, extra_lookup_kwargs={}, extra_context={},
+        template_loader=loader, extra_context={},
         context_processors=None, template_object_name='object'):
     &quot;&quot;&quot;
     Generic list of objects.
 
-    Templates: ``&lt;app_label&gt;/&lt;module_name&gt;_detail``
+    Templates: ``&lt;app_label&gt;/&lt;model_name&gt;_detail.html``
     Context:
         object
             the object
     &quot;&quot;&quot;
-    mod = models.get_module(app_label, module_name)
-    lookup_kwargs = {}
+    model = queryset.model
     if object_id:
-        lookup_kwargs['pk'] = object_id
+        queryset = queryset.filter(pk=object_id)
     elif slug and slug_field:
-        lookup_kwargs['%s__exact' % slug_field] = slug
+        queryset = queryset.filter(**{slug_field: slug})
     else:
-        raise AttributeError(&quot;Generic detail view must be called with either an object_id or a slug/slug_field&quot;)
-    lookup_kwargs.update(extra_lookup_kwargs)
+        raise AttributeError, &quot;Generic detail view must be called with either an object_id or a slug/slug_field.&quot;
     try:
-        object = mod.get_object(**lookup_kwargs)
+        obj = queryset.get()
     except ObjectDoesNotExist:
-        raise Http404(&quot;%s.%s does not exist for %s&quot; % (app_label, module_name, lookup_kwargs))
+        raise Http404, &quot;No %s found matching the query&quot; % (model._meta.verbose_name)
     if not template_name:
-        template_name = &quot;%s/%s_detail&quot; % (app_label, module_name)
+        template_name = &quot;%s/%s_detail.html&quot; % (model._meta.app_label, model._meta.object_name.lower())
     if template_name_field:
-        template_name_list = [getattr(object, template_name_field), template_name]
+        template_name_list = [getattr(obj, template_name_field), template_name]
         t = template_loader.select_template(template_name_list)
     else:
         t = template_loader.get_template(template_name)
-    c = DjangoContext(request, {
-        template_object_name: object,
+    c = RequestContext(request, {
+        template_object_name: obj,
     }, context_processors)
     for key, value in extra_context.items():
         if callable(value):
@@ -119,5 +114,5 @@ def object_detail(request, app_label, module_name, object_id=None, slug=None,
         else:
             c[key] = value
     response = HttpResponse(t.render(c))
-    populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
     return response</diff>
      <filename>django/views/generic/list_detail.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,13 @@
-from django.core.extensions import DjangoContext, render_to_response
-from django.utils.httpwrappers import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
 
 def direct_to_template(request, template, **kwargs):
     &quot;&quot;&quot;
     Render a given template with any extra URL parameters in the context as
     ``{{ params }}``.
     &quot;&quot;&quot;
-    return render_to_response(template, {'params' : kwargs}, context_instance=DjangoContext(request))
+    return render_to_response(template, {'params' : kwargs}, context_instance=RequestContext(request))
 
 def redirect_to(request, url, **kwargs):
     &quot;&quot;&quot;</diff>
      <filename>django/views/generic/simple.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-from django.utils import httpwrappers
+from django import http
 from django.utils.translation import check_for_language, activate, to_locale, get_language
 from django.utils.text import javascript_quote
 from django.conf import settings
@@ -17,7 +17,7 @@ def set_language(request):
         next = request.META.get('HTTP_REFERER', None)
     if not next:
         next = '/'
-    response = httpwrappers.HttpResponseRedirect(next)
+    response = http.HttpResponseRedirect(next)
     if check_for_language(lang_code):
         if hasattr(request, 'session'):
             request.session['django_language'] = lang_code
@@ -190,5 +190,5 @@ def javascript_catalog(request, domain='djangojs', packages=None):
     src.append(LibFoot)
     src.append(InterPolate)
     src = ''.join(src)
-    return httpwrappers.HttpResponse(src, 'text/javascript')
+    return http.HttpResponse(src, 'text/javascript')
 </diff>
      <filename>django/views/i18n.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,14 @@
+from django.template import loader
+from django.core.exceptions import ImproperlyConfigured
+from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
+from django.template import Template, Context, TemplateDoesNotExist
+import mimetypes
 import os
-import urllib
 import posixpath
-import mimetypes
 import re
 import rfc822
 import stat
-from django.core import template_loader
-from django.core.exceptions import Http404, ImproperlyConfigured
-from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect, \
-                                      HttpResponseNotModified
-from django.core.template import Template, Context, TemplateDoesNotExist
+import urllib
 
 def serve(request, path, document_root=None, show_indexes=False):
     &quot;&quot;&quot;
@@ -81,7 +80,7 @@ DEFAULT_DIRECTORY_INDEX_TEMPLATE = &quot;&quot;&quot;
 
 def directory_index(path, fullpath):
     try:
-        t = template_loader.get_template('static/directory_index')
+        t = loader.get_template('static/directory_index')
     except TemplateDoesNotExist:
         t = Template(DEFAULT_DIRECTORY_INDEX_TEMPLATE)
     files = []</diff>
      <filename>django/views/static.py</filename>
    </modified>
    <modified>
      <diff>@@ -12,9 +12,9 @@ admin
 =====
 
 The automatic Django administrative interface. For more information, see
-`Tutorial 3`_.
+`Tutorial 2`_.
 
-.. _Tutorial 3: http://www.djangoproject.com/documentation/tutorial2/
+.. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/
 
 comments
 ========</diff>
      <filename>docs/add_ons.txt</filename>
    </modified>
    <modified>
      <diff>@@ -28,11 +28,13 @@ Column Types
 
 .. admonition:: Note
 
-    In the Django development version, all admin pages (except the dashboard) are fluid-width. All fixed-width classes have been removed.
+    All admin pages (except the dashboard) are fluid-width. All fixed-width
+    classes from previous Django versions have been removed.
 
 The base template for each admin page has a block that defines the column
 structure for the page. This sets a class on the page content area
-(``div#content``) so everything on the page knows how wide it should be. There are three column types available.
+(``div#content``) so everything on the page knows how wide it should be. There
+are three column types available.
 
 colM
     This is the default column setting for all pages. The &quot;M&quot; stands for &quot;main&quot;.
@@ -46,39 +48,12 @@ colMS
 colSM
     Same as above, with the sidebar on the left. The source order of the columns
     doesn't matter.
-colM superwide (removed in Django development version)
-    This is for ridiculously wide pages. Doesn't really work very well for
-    anything but colM. With superwide, you've got 1000px to work with. Don't
-    waste them.
-flex (removed in Django development version)
-    This is for liquid-width pages, such as changelists. Currently only works
-    with single-column pages (does not combine with ``.colMS`` or ``.colSM``).
-    Form pages should never use ``.flex``.
 
-For instance, you could stick this in a template to make a two-column page with the sidebar on the right::
+For instance, you could stick this in a template to make a two-column page with
+the sidebar on the right::
 
     {% block coltype %}colMS{% endblock %}
 
-
-Widths
-======
-
-**Removed in Django development version (see note above).**
-
-There's a whole mess of classes in the stylesheet for custom pixel widths on
-objects. They come in handy for tables and table cells, if you want to avoid
-using the ``width`` attribute. Each class sets the width to the number of pixels
-in the class, except ``.xfull`` which will always be the width of the column
-it's in. (This helps with tables that you want to always fill the horizontal
-width, without using ``width=&quot;100%&quot;`` which makes IE 5's box model cry.)
-
-**Note:** Within a ``.flex`` page, the ``.xfull`` class will ``usually`` set
-to 100%, but there are exceptions and still some untested cases.
-
-Available width classes::
-
-    .x50 .x75 .x100 .x150 .x200 .x250 .x300 .x400 .x500 .xfull
-
 Text Styles
 ===========
 
@@ -107,17 +82,18 @@ There are also a few styles for styling text.
 .help
     This is a custom class for blocks of inline help text explaining the
     function of form elements. It makes text smaller and gray, and when applied
-    to ``p`` elements withing ``.form-row`` elements (see Form Styles below), it will
-    offset the text to align with the form field. Use this for help text,
-    instead of ``small quiet``. It works on other elements, but try to put the class
-    on a ``p`` whenever you can.
+    to ``p`` elements withing ``.form-row`` elements (see Form Styles below),
+    it will offset the text to align with the form field. Use this for help
+    text, instead of ``small quiet``. It works on other elements, but try to
+    put the class on a ``p`` whenever you can.
 .align-left
-    It aligns the text left. Only works on block elements containing inline elements.
+    It aligns the text left. Only works on block elements containing inline
+    elements.
 .align-right
     Are you paying attention?
 .nowrap
-    Keeps text and inline objects from wrapping. Comes in handy for table headers you want to stay
-    on one line.
+    Keeps text and inline objects from wrapping. Comes in handy for table
+    headers you want to stay on one line.
 
 Floats and Clears
 -----------------
@@ -173,9 +149,10 @@ Each fieldset can also take extra classes in addition to ``.module`` to apply
 appropriate formatting to the group of fields.
 
 .aligned
-    this will align the labels and inputs side by side on the same line.
+    This will align the labels and inputs side by side on the same line.
 .wide
-    used in combination with ``.aligned`` to widen the space available for the labels.
+    Used in combination with ``.aligned`` to widen the space available for the
+    labels.
 
 Form Rows
 ---------</diff>
      <filename>docs/admin_css.txt</filename>
    </modified>
    <modified>
      <diff>@@ -6,13 +6,8 @@ Django comes with a user authentication system. It handles user accounts,
 groups, permissions and cookie-based user sessions. This document explains how
 things work.
 
-The basics
-==========
-
-Django supports authentication out of the box. The ``django-admin.py init``
-command, used to initialize a database with Django's core database tables,
-creates the infrastructure for the auth system. You don't have to do anything
-else to use authentication.
+Overview
+========
 
 The auth system consists of:
 
@@ -23,13 +18,35 @@ The auth system consists of:
       user.
     * Messages: A simple way to queue messages for given users.
 
+Installation
+============
+
+Authentication support is bundled as a Django application in
+``django.contrib.auth``. To install it, do the following:
+
+    1. Put ``'django.contrib.auth'`` in your ``INSTALLED_APPS`` setting.
+    2. Run the command ``manage.py syncdb``.
+
+Note that the default ``settings.py`` file created by
+``django-admin.py startproject`` includes ``'django.contrib.auth'`` in
+``INSTALLED_APPS`` for convenience. If your ``INSTALLED_APPS`` already contains
+``'django.contrib.auth'``, feel free to run ``manage.py syncdb`` again; you
+can run that command as many times as you'd like, and each time it'll only
+install what's needed.
+
+The ``syncdb`` command creates the necessary database tables, creates
+permission objects for all installed apps that need 'em, and prompts you to
+create a superuser account.
+
+Once you've taken those steps, that's it.
+
 Users
 =====
 
 Users are represented by a standard Django model, which lives in
-`django/models/auth.py`_.
+`django/contrib/auth/models.py`_.
 
-.. _django/models/auth.py: http://code.djangoproject.com/browser/django/trunk/django/models/auth.py
+.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py
 
 API reference
 -------------
@@ -62,16 +79,20 @@ Methods
 ~~~~~~~
 
 ``User`` objects have two many-to-many fields: ``groups`` and
-``user_permissions``. Because of those relationships, ``User`` objects get
-data-access methods like any other `Django model`_:
-
-    * ``get_group_list(**kwargs)``
-    * ``set_groups(id_list)``
-    * ``get_permission_list(**kwargs)``
-    * ``set_user_permissions(id_list)``
+``user_permissions``. ``User`` objects can access their related
+objects in the same way as any other `Django model`_::
+
+    ``myuser.objects.groups = [group_list]``
+    ``myuser.objects.groups.add(group, group,...)``
+    ``myuser.objects.groups.remove(group, group,...)``
+    ``myuser.objects.groups.clear()``
+    ``myuser.objects.permissions = [permission_list]``
+    ``myuser.objects.permissions.add(permission, permission, ...)``
+    ``myuser.objects.permissions.remove(permission, permission, ...]``
+    ``myuser.objects.permissions.clear()``
 
 In addition to those automatic API methods, ``User`` objects have the following
-methods:
+custom methods:
 
     * ``is_anonymous()`` -- Always returns ``False``. This is a way of
       comparing ``User`` objects to anonymous users.
@@ -80,11 +101,12 @@ methods:
       with a space in between.
 
     * ``set_password(raw_password)`` -- Sets the user's password to the given
-      raw string, taking care of the MD5 hashing. Doesn't save the ``User``
-      object.
+      raw string, taking care of the password hashing. Doesn't save the
+      ``User`` object.
 
     * ``check_password(raw_password)`` -- Returns ``True`` if the given raw
-      string is the correct password for the user.
+      string is the correct password for the user. (This takes care of the
+      password hashing in making the comparison.)
 
     * ``get_group_permissions()`` -- Returns a list of permission strings that
       the user has, through his/her groups.
@@ -110,23 +132,25 @@ methods:
       `DEFAULT_FROM_EMAIL`_ setting.
 
     * ``get_profile()`` -- Returns a site-specific profile for this user.
-      Raises ``django.models.auth.SiteProfileNotAvailable`` if the current site
+      Raises ``django.contrib.auth.models.SiteProfileNotAvailable`` if the current site
       doesn't allow profiles.
 
 .. _Django model: http://www.djangoproject.com/documentation/model_api/
 .. _DEFAULT_FROM_EMAIL: http://www.djangoproject.com/documentation/settings/#default-from-email
 
-Module functions
-~~~~~~~~~~~~~~~~
+Manager functions
+~~~~~~~~~~~~~~~~~
 
-The ``django.models.auth.users`` module has the following helper functions:
+The ``User`` model has a custom manager that has the following helper functions:
 
     * ``create_user(username, email, password)`` -- Creates, saves and returns
       a ``User``. The ``username``, ``email`` and ``password`` are set as
       given, and the ``User`` gets ``is_active=True``.
 
+      See _`Creating users` for example usage.
+
     * ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')``
-      -- Returns a random password with the given length and given string of
+      Returns a random password with the given length and given string of
       allowed characters. (Note that the default value of ``allowed_chars``
       doesn't contain ``&quot;I&quot;`` or letters that look like it, to avoid user
       confusion.
@@ -140,11 +164,12 @@ Creating users
 The most basic way to create users is to use the ``create_user`` helper
 function that comes with Django::
 
-    &gt;&gt;&gt; from django.models.auth import users
-    &gt;&gt;&gt; user = users.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
+    &gt;&gt;&gt; from django.contrib.auth.models import User
+    &gt;&gt;&gt; user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
 
-    # Now, user is a User object already saved to the database.
-    # You can continue to change its attributes if you want to change other fields.
+    # At this point, user is a User object ready to be saved
+    # to the database. You can continue to change its attributes
+    # if you want to change other fields.
     &gt;&gt;&gt; user.is_staff = True
     &gt;&gt;&gt; user.save()
 
@@ -153,28 +178,26 @@ Changing passwords
 
 Change a password with ``set_password()``::
 
-    &gt;&gt;&gt; from django.models.auth import users
-    &gt;&gt;&gt; u = users.get_object(username__exact='john')
+    &gt;&gt;&gt; from django.contrib.auth.models import User
+    &gt;&gt;&gt; u = User.objects.get(username__exact='john')
     &gt;&gt;&gt; u.set_password('new password')
     &gt;&gt;&gt; u.save()
 
-Don't set the password field directly unless you know what you're doing. This
-is explained in the next section.
+Don't set the ``password`` attribute directly unless you know what you're
+doing. This is explained in the next section.
 
 Passwords
 ---------
 
-Previous versions, such as Django 0.90, used simple MD5 hashes without password
-salts.
-
-The ``password`` field of a ``User`` object is a string in this format::
+The ``password`` attribute of a ``User`` object is a string in this format::
 
     hashtype$salt$hash
 
 That's hashtype, salt and hash, separated by the dollar-sign character.
 
-Hashtype is either ``sha1`` (default) or ``md5``. Salt is a random string
-used to salt the raw password to create the hash.
+Hashtype is either ``sha1`` (default) or ``md5`` -- the algorithm used to
+perform a one-way hash of the password. Salt is a random string used to salt
+the raw password to create the hash.
 
 For example::
 
@@ -183,17 +206,22 @@ For example::
 The ``User.set_password()`` and ``User.check_password()`` functions handle
 the setting and checking of these values behind the scenes.
 
+Previous Django versions, such as 0.90, used simple MD5 hashes without password
+salts. For backwards compatibility, those are still supported; they'll be
+converted automatically to the new style the first time ``check_password()``
+works correctly for a given user.
+
 Anonymous users
 ---------------
 
-``django.parts.auth.anonymoususers.AnonymousUser`` is a class that implements
-the ``django.models.auth.users.User`` interface, with these differences:
+``django.contrib.auth.models.AnonymousUser`` is a class that implements
+the ``django.contirb.auth.models.User`` interface, with these differences:
 
     * ``id`` is always ``None``.
     * ``is_anonymous()`` returns ``True`` instead of ``False``.
     * ``has_perm()`` always returns ``False``.
-    * ``set_password()``, ``check_password()``, ``set_groups()`` and
-      ``set_permissions()`` raise ``NotImplementedError``.
+    * ``set_password()``, ``check_password()``, ``save()``, ``delete()``,
+      ``set_groups()`` and ``set_permissions()`` raise ``NotImplementedError``.
 
 In practice, you probably won't need to use ``AnonymousUser`` objects on your
 own, but they're used by Web requests, as explained in the next section.
@@ -202,10 +230,15 @@ Authentication in Web requests
 ==============================
 
 Until now, this document has dealt with the low-level APIs for manipulating
-authentication-related objects. On a higher level, Django hooks this
+authentication-related objects. On a higher level, Django can hook this
 authentication framework into its system of `request objects`_.
 
-In any Django view, ``request.user`` will give you a ``User`` object
+First, install the ``SessionMiddleware`` and ``AuthenticationMiddleware``
+middlewares by adding them to your ``MIDDLEWARE_CLASSES`` setting. See the
+`session documentation`_ for more information.
+
+Once you have those middlewares installed, you'll be able to access
+``request.user`` in views. ``request.user`` will give you a ``User`` object
 representing the currently logged-in user. If a user isn't currently logged in,
 ``request.user`` will be set to an instance of ``AnonymousUser`` (see the
 previous section). You can tell them apart with ``is_anonymous()``, like so::
@@ -215,10 +248,6 @@ previous section). You can tell them apart with ``is_anonymous()``, like so::
     else:
         # Do something for logged-in users.
 
-If you want to use ``request.user`` in your view code, make sure you have
-``SessionMiddleware`` enabled. See the `session documentation`_ for more
-information.
-
 .. _request objects: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
 .. _session documentation: http://www.djangoproject.com/documentation/sessions/
 
@@ -227,8 +256,8 @@ How to log a user in
 
 To log a user in, do the following within a view::
 
-    from django.models.auth import users
-    request.session[users.SESSION_KEY] = some_user.id
+    from django.contrib.auth.models import SESSION_KEY
+    request.session[SESSION_KEY] = some_user.id
 
 Because this uses sessions, you'll need to make sure you have
 ``SessionMiddleware`` enabled. See the `session documentation`_ for more
@@ -246,7 +275,7 @@ The raw way
 The simple, raw way to limit access to pages is to check
 ``request.user.is_anonymous()`` and either redirect to a login page::
 
-    from django.utils.httpwrappers import HttpResponseRedirect
+    from django.http import HttpResponseRedirect
 
     def my_view(request):
         if request.user.is_anonymous():
@@ -257,7 +286,7 @@ The simple, raw way to limit access to pages is to check
 
     def my_view(request):
         if request.user.is_anonymous():
-            return render_to_response('myapp/login_error')
+            return render_to_response('myapp/login_error.html')
         # ...
 
 The login_required decorator
@@ -265,15 +294,16 @@ The login_required decorator
 
 As a shortcut, you can use the convenient ``login_required`` decorator::
 
-    from django.views.decorators.auth import login_required
+    from django.contrib.auth.decorators import login_required
 
     def my_view(request):
         # ...
     my_view = login_required(my_view)
 
-Here's the same thing, using Python 2.4's decorator syntax::
+Here's an equivalent example, using the more compact decorator syntax
+introduced in Python 2.4::
 
-    from django.views.decorators.auth import login_required
+    from django.contrib.auth.decorators import login_required
 
     @login_required
     def my_view(request):
@@ -304,7 +334,7 @@ permission ``polls.can_vote``::
 
 As a shortcut, you can use the convenient ``user_passes_test`` decorator::
 
-    from django.views.decorators.auth import user_passes_test
+    from django.contrib.auth.decorators import user_passes_test
 
     def my_view(request):
         # ...
@@ -312,7 +342,7 @@ As a shortcut, you can use the convenient ``user_passes_test`` decorator::
 
 Here's the same thing, using Python 2.4's decorator syntax::
 
-    from django.views.decorators.auth import user_passes_test
+    from django.contrib.auth.decorators import user_passes_test
 
     @user_passes_test(lambda u: u.has_perm('polls.can_vote'))
     def my_view(request):
@@ -328,7 +358,7 @@ specify the URL for your login page (``/accounts/login/`` by default).
 
 Example in Python 2.3 syntax::
 
-    from django.views.decorators.auth import user_passes_test
+    from django.contrib.auth.decorators import user_passes_test
 
     def my_view(request):
         # ...
@@ -336,7 +366,7 @@ Example in Python 2.3 syntax::
 
 Example in Python 2.4 syntax::
 
-    from django.views.decorators.auth import user_passes_test
+    from django.contrib.auth.decorators import user_passes_test
 
     @user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')
     def my_view(request):
@@ -380,49 +410,52 @@ Permissions are set globally per type of object, not per specific object
 instance. For example, it's possible to say &quot;Mary may change news stories,&quot; but
 it's not currently possible to say &quot;Mary may change news stories, but only the
 ones she created herself&quot; or &quot;Mary may only change news stories that have a
-certain status or publication date.&quot; The latter functionality is something
+certain status, publication date or ID.&quot; The latter functionality is something
 Django developers are currently discussing.
 
 Default permissions
 -------------------
 
 Three basic permissions -- add, create and delete -- are automatically created
-for each Django model that has ``admin`` set. Behind the scenes, these
-permissions are added to the ``auth_permissions`` database table when you run
-``django-admin.py install [app]``. You can view the exact SQL ``INSERT``
-statements by running ``django-admin.py sqlinitialdata [app]``.
-
-Note that if your model doesn't have ``admin`` set when you run
-``django-admin.py install``, the permissions won't be created. If you
-initialize your database and add ``admin`` to models after the fact, you'll
-need to add the permissions to the database manually. Do this by running
-``django-admin.py installperms [app]``, which creates any missing permissions
-for the given app.
+for each Django model that has a ``class Admin`` set. Behind the scenes, these
+permissions are added to the ``auth_permission`` database table when you run
+``manage.py syncdb``.
+
+Note that if your model doesn't have ``class Admin`` set when you run
+``syncdb``, the permissions won't be created. If you initialize your database
+and add ``class Admin`` to models after the fact, you'll need to run
+``django-admin.py syncdb`` again. It will create any missing permissions for
+all of your installed apps.
 
 Custom permissions
 ------------------
 
 To create custom permissions for a given model object, use the ``permissions``
-`model META attribute`_.
+`model Meta attribute`_.
 
 This example model creates three custom permissions::
 
-    class USCitizen(meta.Model):
+    class USCitizen(models.Model):
         # ...
-        class META:
+        class Meta:
             permissions = (
                 (&quot;can_drive&quot;, &quot;Can drive&quot;),
                 (&quot;can_vote&quot;, &quot;Can vote in elections&quot;),
                 (&quot;can_drink&quot;, &quot;Can drink alcohol&quot;),
             )
 
-.. _model META attribute: http://www.djangoproject.com/documentation/model_api/#meta-options
+The only thing this does is create those extra permissions when you run
+``syncdb``.
+
+.. _model Meta attribute: http://www.djangoproject.com/documentation/model_api/#meta-options
 
 API reference
 -------------
 
 Just like users, permissions are implemented in a Django model that lives in
-`django/models/auth.py`_.
+`django/contrib/auth/models.py`_.
+
+.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py
 
 Fields
 ~~~~~~
@@ -430,8 +463,8 @@ Fields
 ``Permission`` objects have the following fields:
 
     * ``name`` -- Required. 50 characters or fewer. Example: ``'Can vote'``.
-    * ``package`` -- Required. A reference to the ``packages`` database table,
-      which contains a record for each installed Django application.
+    * ``content_type`` -- Required. A reference to the ``django_content_type``
+      database table, which contains a record for each installed Django model.
     * ``codename`` -- Required. 100 characters or fewer. Example: ``'can_vote'``.
 
 Methods
@@ -444,21 +477,21 @@ Authentication data in templates
 ================================
 
 The currently logged-in user and his/her permissions are made available in the
-`template context`_ when you use ``DjangoContext``.
+`template context`_ when you use ``RequestContext``.
 
 .. admonition:: Technicality
 
    Technically, these variables are only made available in the template context
-   if you use ``DjangoContext`` *and* your ``TEMPLATE_CONTEXT_PROCESSORS``
+   if you use ``RequestContext`` *and* your ``TEMPLATE_CONTEXT_PROCESSORS``
    setting contains ``&quot;django.core.context_processors.auth&quot;``, which is default.
-   For more, see the `DjangoContext docs`_.
+   For more, see the `RequestContext docs`_.
 
-   .. _DjangoContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
+   .. _RequestContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
 
 Users
 -----
 
-The currently logged-in user, either a ``User`` object or an``AnonymousUser``
+The currently logged-in user, either a ``User`` instance or an``AnonymousUser``
 instance, is stored in the template variable ``{{ user }}``::
 
     {% if user.is_anonymous %}
@@ -504,25 +537,25 @@ Thus, you can check permissions in template ``{% if %}`` statements::
 Groups
 ======
 
-Groups are a generic way of categorizing users to apply permissions, or some
-other label, to those users. A user can belong to any number of groups.
+Groups are a generic way of categorizing users so you can apply permissions, or
+some other label, to those users. A user can belong to any number of groups.
 
 A user in a group automatically has the permissions granted to that group. For
 example, if the group ``Site editors`` has the permission
 ``can_edit_home_page``, any user in that group will have that permission.
 
-Beyond permissions, groups are a convenient way to categorize users to apply
-some label, or extended functionality, to them. For example, you could create
-a group ``'Special users'``, and you could write code that would do special
-things to those users -- such as giving them access to a members-only portion
-of your site, or sending them members-only e-mail messages.
+Beyond permissions, groups are a convenient way to categorize users to give
+them some label, or extended functionality. For example, you could create a
+group ``'Special users'``, and you could write code that could, say, give them
+access to a members-only portion of your site, or send them members-only e-mail
+messages.
 
 Messages
 ========
 
 The message system is a lightweight way to queue messages for given users.
 
-A message is associated with a User. There's no concept of expiration or
+A message is associated with a ``User``. There's no concept of expiration or
 timestamps.
 
 Messages are used by the Django admin after successful actions. For example,
@@ -530,8 +563,9 @@ Messages are used by the Django admin after successful actions. For example,
 
 The API is simple::
 
-    * To add messages, use ``user.add_message(message_text)``.
-    * To retrieve/delete messages, use ``user.get_and_delete_messages()``,
+    * To create a new message, use
+      ``user_obj.message_set.create(message='message_text')``.
+    * To retrieve/delete messages, use ``user_obj.get_and_delete_messages()``,
       which returns a list of ``Message`` objects in the user's queue (if any)
       and deletes the messages from the queue.
 
@@ -541,10 +575,11 @@ a playlist::
     def create_playlist(request, songs):
         # Create the playlist with the given songs.
         # ...
-        request.user.add_message(&quot;Your playlist was added successfully.&quot;)
-        return render_to_response(&quot;playlists/create&quot;, context_instance=DjangoContext(request))
+        request.user.message_set.create(message=&quot;Your playlist was added successfully.&quot;)
+        return render_to_response(&quot;playlists/create.html&quot;,
+            context_instance=RequestContext(request))
 
-When you use ``DjangoContext``, the currently logged-in user and his/her
+When you use ``RequestContext``, the currently logged-in user and his/her
 messages are made available in the `template context`_ as the template variable
 ``{{ messages }}``. Here's an example of template code that displays messages::
 
@@ -556,7 +591,7 @@ messages are made available in the `template context`_ as the template variable
     &lt;/ul&gt;
     {% endif %}
 
-Note that ``DjangoContext`` calls ``get_and_delete_messages`` behind the
+Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the
 scenes, so any messages will be deleted even if you don't display them.
 
 Finally, note that this messages framework only works with users in the user</diff>
      <filename>docs/authentication.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,63 +2,180 @@
 Django's cache framework
 ========================
 
-So, you got slashdotted_. Now what?
-
-Django's cache framework gives you three methods of caching dynamic pages in
-memory or in a database. You can cache the output of specific views, you can
-cache only the pieces that are difficult to produce, or you can cache your
-entire site.
-
-.. _slashdotted: http://en.wikipedia.org/wiki/Slashdot_effect
+A fundamental tradeoff in dynamic Web sites is, well, they're dynamic. Each
+time a user requests a page, the Web server makes all sorts of calculations --
+from database queries to template rendering to business logic -- to create the
+page that your site's visitor sees. This is a lot more expensive, from a
+processing-overhead perspective, than your standard read-a-file-off-the-filesystem
+server arrangement.
+
+For most Web applications, this overhead isn't a big deal. Most Web
+applications aren't washingtonpost.com or slashdot.org; they're simply small-
+to medium-sized sites with so-so traffic. But for medium- to high-traffic
+sites, it's essential to cut as much overhead as possible.
+
+That's where caching comes in.
+
+To cache something is to save the result of an expensive calculation so that
+you don't have to perform the calculation next time. Here's some pseudocode
+explaining how this would work for a dynamically generated Web page:
+
+    given a URL, try finding that page in the cache
+    if the page is in the cache:
+        return the cached page
+    else:
+        generate the page
+        save the generated page in the cache (for next time)
+        return the generated page
+
+Django comes with a robust cache system that lets you save dynamic pages so
+they don't have to be calculated for each request. For convenience, Django
+offers different levels of cache granularity: You can cache the output of
+specific views, you can cache only the pieces that are difficult to produce, or
+you can cache your entire site.
+
+Django also works well with &quot;upstream&quot; caches, such as Squid
+(http://www.squid-cache.org/) and browser-based caches. These are the types of
+caches that you don't directly control but to which you can provide hints (via
+HTTP headers) about which parts of your site should be cached, and how.
 
 Setting up the cache
 ====================
 
-The cache framework allows for different &quot;backends&quot; -- different methods of
-caching data. There's a simple single-process memory cache (mostly useful as a
-fallback) and a memcached_ backend (the fastest option, by far, if you've got
-the RAM).
+The cache system requires a small amount of setup. Namely, you have to tell it
+where your cached data should live -- whether in a database, on the filesystem
+or directly in memory. This is an important decision that affects your cache's
+performance; yes, some cache types are faster than others.
+
+Your cache preference goes in the ``CACHE_BACKEND`` setting in your settings
+file. Here's an explanation of all available values for CACHE_BACKEND.
+
+Memcached
+---------
+
+By far the fastest, most efficient type of cache available to Django, Memcached
+is an entirely memory-based cache framework originally developed to handle high
+loads at LiveJournal.com and subsequently open-sourced by Danga Interactive.
+It's used by sites such as Slashdot and Wikipedia to reduce database access and
+dramatically increase site performance.
+
+Memcached is available for free at http://danga.com/memcached/ . It runs as a
+daemon and is allotted a specified amount of RAM. All it does is provide an
+interface -- a *super-lightning-fast* interface -- for adding, retrieving and
+deleting arbitrary data in the cache. All data is stored directly in memory,
+so there's no overhead of database or filesystem usage.
+
+After installing Memcached itself, you'll need to install the Memcached Python
+bindings. They're in a single Python module, memcache.py, available at
+ftp://ftp.tummy.com/pub/python-memcached/ . If that URL is no longer valid,
+just go to the Memcached Web site (http://www.danga.com/memcached/) and get the
+Python bindings from the &quot;Client APIs&quot; section.
+
+To use Memcached with Django, set ``CACHE_BACKEND`` to
+``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached
+daemon and ``port`` is the port on which Memcached is running.
+
+In this example, Memcached is running on localhost (127.0.0.1) port 11211::
+
+    CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
+
+One excellent feature of Memcached is its ability to share cache over multiple
+servers. To take advantage of this feature, include all server addresses in
+``CACHE_BACKEND``, separated by semicolons. In this example, the cache is
+shared over Memcached instances running on IP address 172.19.26.240 and
+172.19.26.242, both on port 11211::
+
+    CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
+
+Memory-based caching has one disadvantage: Because the cached data is stored in
+memory, the data will be lost if your server crashes. Clearly, memory isn't
+intended for permanent data storage, so don't rely on memory-based caching as
+your only data storage. Actually, none of the Django caching backends should be
+used for permanent storage -- they're all intended to be solutions for caching,
+not storage -- but we point this out here because memory-based caching is
+particularly temporary.
+
+Database caching
+----------------
+
+To use a database table as your cache backend, first create a cache table in
+your database by running this command::
+
+    python manage.py createcachetable [cache_table_name]
+
+...where ``[cache_table_name]`` is the name of the database table to create.
+(This name can be whatever you want, as long as it's a valid table name that's
+not already being used in your database.) This command creates a single table
+in your database that is in the proper format that Django's database-cache
+system expects.
+
+Once you've created that database table, set your ``CACHE_BACKEND`` setting to
+``&quot;db://tablename/&quot;``, where ``tablename`` is the name of the database table.
+In this example, the cache table's name is ``my_cache_table``:
+
+    CACHE_BACKEND = 'db://my_cache_table'
+
+Database caching works best if you've got a fast, well-indexed database server.
+
+Filesystem caching
+------------------
+
+To store cached items on a filesystem, use the ``&quot;file://&quot;`` cache type for
+``CACHE_BACKEND``. For example, to store cached data in ``/var/tmp/django_cache``,
+use this setting::
+
+    CACHE_BACKEND = 'file:///var/tmp/django_cache'
+
+Note that there are three forward slashes toward the beginning of that example.
+The first two are for ``file://``, and the third is the first character of the
+directory path, ``/var/tmp/django_cache``.
+
+The directory path should be absolute -- that is, it should start at the root
+of your filesystem. It doesn't matter whether you put a slash at the end of the
+setting.
 
-Before using the cache, you'll need to tell Django which cache backend you'd
-like to use. Do this by setting the ``CACHE_BACKEND`` in your settings file.
+Make sure the directory pointed-to by this setting exists and is readable and
+writable by the system user under which your Web server runs. Continuing the
+above example, if your server runs as the user ``apache``, make sure the
+directory ``/var/tmp/django_cache`` exists and is readable and writable by the
+user ``apache``.
 
-The ``CACHE_BACKEND`` setting is a &quot;fake&quot; URI (really an unregistered scheme).
-Examples:
+Local-memory caching
+--------------------
 
-    ==============================  ===========================================
-    CACHE_BACKEND                   Explanation
-    ==============================  ===========================================
-    memcached://127.0.0.1:11211/    A memcached backend; the server is running
-                                    on localhost port 11211.  You can use
-                                    multiple memcached servers by separating
-                                    them with semicolons.
+If you want the speed advantages of in-memory caching but don't have the
+capability of running Memcached, consider the local-memory cache backend. This
+cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to
+``&quot;locmem:///&quot;``. For example::
 
-                                    This backend requires the
-                                    `Python memcached bindings`_.
+    CACHE_BACKEND = 'locmem:///'
 
-    db://tablename/                 A database backend in a table named
-                                    &quot;tablename&quot;. This table should be created
-                                    with &quot;django-admin createcachetable&quot;.
+Simple caching (for development)
+--------------------------------
 
-    file:///var/tmp/django_cache/   A file-based cache stored in the directory
-                                    /var/tmp/django_cache/.
+A simple, single-process memory cache is available as ``&quot;simple:///&quot;``. This
+merely saves cached data in-process, which means it should only be used in
+development or testing environments. For example::
 
-    simple:///                      A simple single-process memory cache; you
-                                    probably don't want to use this except for
-                                    testing. Note that this cache backend is
-                                    NOT thread-safe!
+    CACHE_BACKEND = 'simple:///'
 
-    locmem:///                      A more sophisticated local memory cache;
-                                    this is multi-process- and thread-safe.
+Dummy caching (for development)
+-------------------------------
 
-    dummy:///                       Doesn't actually cache; just implements the
-                                    cache backend interface and doesn't do
-                                    anything. This is an easy way to turn off
-                                    caching for a test environment.
-    ==============================  ===========================================
+Finally, Django comes with a &quot;dummy&quot; cache that doesn't actually cache -- it
+just implements the cache interface without doing anything.
 
-All caches may take arguments -- they're given in query-string style.  Valid
-arguments are:
+This is useful if you have a production site that uses heavy-duty caching in
+various places but a development/test environment on which you don't want to
+cache. In that case, set ``CACHE_BACKEND`` to ``&quot;dummy:///&quot;`` in the settings
+file for your development environment. As a result, your development
+environment won't use caching and your production environment still will.
+
+CACHE_BACKEND arguments
+-----------------------
+
+All caches may take arguments. They're given in query-string style on the
+``CACHE_BACKEND`` setting. Valid arguments are:
 
     timeout
         Default timeout, in seconds, to use for the cache. Defaults to 5
@@ -66,7 +183,7 @@ arguments are:
 
     max_entries
         For the simple and database backends, the maximum number of entries
-        allowed in the cache before it is cleaned.  Defaults to 300.
+        allowed in the cache before it is cleaned. Defaults to 300.
 
     cull_percentage
         The percentage of entries that are culled when max_entries is reached.
@@ -77,20 +194,21 @@ arguments are:
         dumped when max_entries is reached. This makes culling *much* faster
         at the expense of more cache misses.
 
-For example::
+In this example, ``timeout`` is set to ``60``::
 
     CACHE_BACKEND = &quot;memcached://127.0.0.1:11211/?timeout=60&quot;
 
+In this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``::
+
+    CACHE_BACKEND = &quot;memcached://127.0.0.1:11211/?timeout=30&amp;max_entries=400&quot;
+
 Invalid arguments are silently ignored, as are invalid values of known
 arguments.
 
-.. _memcached: http://www.danga.com/memcached/
-.. _Python memcached bindings: ftp://ftp.tummy.com/pub/python-memcached/
-
 The per-site cache
 ==================
 
-Once the cache is set up, the simplest way to use the cache is to cache your
+Once the cache is set up, the simplest way to use caching is to cache your
 entire site. Just add ``django.middleware.cache.CacheMiddleware`` to your
 ``MIDDLEWARE_CLASSES`` setting, as in this example::
 
@@ -159,52 +277,100 @@ For example, you may find it's only necessary to cache the result of an
 intensive database query. In cases like this, you can use the low-level cache
 API to store objects in the cache with any level of granularity you like.
 
-The cache API is simple::
+The cache API is simple. The cache module, ``django.core.cache``, exports a
+``cache`` object that's automatically created from the ``CACHE_BACKEND``
+setting::
 
-    # The cache module exports a cache object that's automatically
-    # created from the CACHE_BACKEND setting.
     &gt;&gt;&gt; from django.core.cache import cache
 
-    # The basic interface is set(key, value, timeout_seconds) and get(key).
+The basic interface is ``set(key, value, timeout_seconds)`` and ``get(key)``::
+
     &gt;&gt;&gt; cache.set('my_key', 'hello, world!', 30)
     &gt;&gt;&gt; cache.get('my_key')
     'hello, world!'
 
-    # (Wait 30 seconds...)
+The ``timeout_seconds`` argument is optional and defaults to the ``timeout``
+argument in the ``CACHE_BACKEND`` setting (explained above).
+
+If the object doesn't exist in the cache, ``cache.get()`` returns ``None``::
+
+    &gt;&gt;&gt; cache.get('some_other_key')
+    None
+
+    # Wait 30 seconds for 'my_key' to expire...
+
     &gt;&gt;&gt; cache.get('my_key')
     None
 
-    # get() can take a default argument.
-    &gt;&gt;&gt; cache.get('my_key', 'has_expired')
-    'has_expired'
+get() can take a ``default`` argument::
+
+    &gt;&gt;&gt; cache.get('my_key', 'has expired')
+    'has expired'
+
+There's also a get_many() interface that only hits the cache once. get_many()
+returns a dictionary with all the keys you asked for that actually exist in the
+cache (and haven't expired)::
 
-    # There's also a get_many() interface that only hits the cache once.
-    # Also, note that the timeout argument is optional and defaults to what
-    # you've given in the settings file.
     &gt;&gt;&gt; cache.set('a', 1)
     &gt;&gt;&gt; cache.set('b', 2)
     &gt;&gt;&gt; cache.set('c', 3)
-
-    # get_many() returns a dictionary with all the keys you asked for that
-    # actually exist in the cache (and haven't expired).
     &gt;&gt;&gt; cache.get_many(['a', 'b', 'c'])
     {'a': 1, 'b': 2, 'c': 3}
 
-    # There's also a way to delete keys explicitly.
+Finally, you can delete keys explicitly with ``delete()``. This is an easy way
+of clearing the cache for a particular object::
+
     &gt;&gt;&gt; cache.delete('a')
 
 That's it. The cache has very few restrictions: You can cache any object that
 can be pickled safely, although keys must be strings.
 
-Controlling cache: Using Vary headers
-=====================================
+Upstream caches
+===============
+
+So far, this document has focused on caching your *own* data. But another type
+of caching is relevant to Web development, too: caching performed by &quot;upstream&quot;
+caches. These are systems that cache pages for users even before the request
+reaches your Web site.
+
+Here are a few examples of upstream caches:
+
+    * Your ISP may cache certain pages, so if you requested a page from
+      somedomain.com, your ISP would send you the page without having to access
+      somedomain.com directly.
+
+    * Your Django Web site may site behind a Squid Web proxy
+      (http://www.squid-cache.org/) that caches pages for performance. In this
+      case, each request first would be handled by Squid, and it'd only be
+      passed to your application if needed.
 
-The Django cache framework works with `HTTP Vary headers`_ to allow developers
-to instruct caching mechanisms to differ their cache contents depending on
-request HTTP headers.
+    * Your Web browser caches pages, too. If a Web page sends out the right
+      headers, your browser will use the local (cached) copy for subsequent
+      requests to that page.
 
-Essentially, the ``Vary`` response HTTP header defines which request headers a
-cache mechanism should take into account when building its cache key.
+Upstream caching is a nice efficiency boost, but there's a danger to it:
+Many Web pages' contents differ based on authentication and a host of other
+variables, and cache systems that blindly save pages based purely on URLs could
+expose incorrect or sensitive data to subsequent visitors to those pages.
+
+For example, say you operate a Web e-mail system, and the contents of the
+&quot;inbox&quot; page obviously depend on which user is logged in. If an ISP blindly
+cached your site, then the first user who logged in through that ISP would have
+his user-specific inbox page cached for subsequent visitors to the site. That's
+not cool.
+
+Fortunately, HTTP provides a solution to this problem: A set of HTTP headers
+exist to instruct caching mechanisms to differ their cache contents depending
+on designated variables, and to tell caching mechanisms not to cache particular
+pages.
+
+Using Vary headers
+==================
+
+One of these headers is ``Vary``. It defines which request headers a cache
+mechanism should take into account when building its cache key. For example, if
+the contents of a Web page depend on a user's language preference, the page is
+said to &quot;vary on language.&quot;
 
 By default, Django's cache system creates its cache keys using the requested
 path -- e.g., ``&quot;/stories/2005/jun/23/bank_robbed/&quot;``. This means every request
@@ -241,7 +407,7 @@ setting the ``Vary`` header (using something like
 ``response['Vary'] = 'user-agent'``) is that the decorator adds to the ``Vary``
 header (which may already exist) rather than setting it from scratch.
 
-Note that you can pass multiple headers to ``vary_on_headers()``::
+You can pass multiple headers to ``vary_on_headers()``::
 
     @vary_on_headers('User-Agent', 'Cookie')
     def my_view(request):
@@ -261,7 +427,8 @@ decorator. These two views are equivalent::
 Also note that the headers you pass to ``vary_on_headers`` are not case
 sensitive. ``&quot;User-Agent&quot;`` is the same thing as ``&quot;user-agent&quot;``.
 
-You can also use a helper function, ``patch_vary_headers()``, directly::
+You can also use a helper function, ``django.utils.cache.patch_vary_headers``,
+directly::
 
     from django.utils.cache import patch_vary_headers
     def my_view(request):
@@ -273,7 +440,9 @@ You can also use a helper function, ``patch_vary_headers()``, directly::
 ``patch_vary_headers`` takes an ``HttpResponse`` instance as its first argument
 and a list/tuple of header names as its second argument.
 
-.. _`HTTP Vary headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44
+For more on Vary headers, see the `official Vary spec`_.
+
+.. _`official Vary spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44
 
 Controlling cache: Using other headers
 ======================================
@@ -317,15 +486,19 @@ cache on every access and to store cached versions for, at most, 3600 seconds::
     def my_view(request):
         ...
 
-Any valid ``Cache-Control`` directive is valid in ``cache_control()``. For a
-full list, see the `Cache-Control spec`_. Just pass the directives as keyword
-arguments to ``cache_control()``, substituting underscores for hyphens. For
-directives that don't take an argument, set the argument to ``True``.
+Any valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``.
+Here's a full list:
 
-Examples:
+    * ``public=True``
+    * ``private=True``
+    * ``no_cache=True``
+    * ``no_transform=True``
+    * ``must_revalidate=True``
+    * ``proxy_revalidate=True``
+    * ``max_age=num_seconds``
+    * ``s_maxage=num_seconds``
 
-    * ``@cache_control(max_age=3600)`` turns into ``max-age=3600``.
-    * ``@cache_control(public=True)`` turns into ``public``.
+For explanation of Cache-Control HTTP directives, see the `Cache-Control spec`_.
 
 (Note that the caching middleware already sets the cache header's max-age with
 the value of the ``CACHE_MIDDLEWARE_SETTINGS`` setting. If you use a custom</diff>
      <filename>docs/cache.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,509 +2,1366 @@
 Database API reference
 ======================
 
-Once you've created your `data models`_, you'll need to retrieve data from the
-database. This document explains the database abstraction API derived from the
-models, and how to create, retrieve and update objects.
+Once you've created your `data models`_, Django automatically gives you a
+database-abstraction API that lets you create, retrieve, update and delete
+objects. This document explains that API.
 
 .. _`data models`: http://www.djangoproject.com/documentation/model_api/
 
-Throughout this reference, we'll refer to the following Poll application::
+Throughout this reference, we'll refer to the following models, which comprise
+a weblog application::
 
-    class Poll(meta.Model):
-        slug = meta.SlugField(unique_for_month='pub_date')
-        question = meta.CharField(maxlength=255)
-        pub_date = meta.DateTimeField()
-        expire_date = meta.DateTimeField()
+    class Blog(models.Model):
+        name = models.CharField(maxlength=100)
+        tagline = models.TextField()
 
-        def __repr__(self):
-            return self.question
+        def __str__(self):
+            return self.name
 
-    class Choice(meta.Model):
-        poll = meta.ForeignKey(Poll, edit_inline=meta.TABULAR,
-            num_in_admin=10, min_num_in_admin=5)
-        choice = meta.CharField(maxlength=255, core=True)
-        votes = meta.IntegerField(editable=False, default=0)
+    class Author(models.Model):
+        name = models.CharField(maxlength=50)
+        email = models.URLField()
 
-        def __repr__(self):
-            return self.choice
+        class __str__(self):
+            return self.name
 
-Basic lookup functions
-======================
+    class Entry(models.Model):
+        blog = models.ForeignKey(Blog)
+        headline = models.CharField(maxlength=255)
+        body_text = models.TextField()
+        pub_date = models.DateTimeField()
+        authors = models.ManyToManyField(Author)
 
-Each model exposes these module-level functions for lookups:
+        def __str__(self):
+            return self.headline
 
-get_object(\**kwargs)
----------------------
+Creating objects
+================
 
-Returns the object matching the given lookup parameters, which should be in
-the format described in &quot;Field lookups&quot; below. Raises a module-level
-``*DoesNotExist`` exception if an object wasn't found for the given parameters.
-Raises ``AssertionError`` if more than one object was found.
+To represent database-table data in Python objects, Django uses an intuitive
+system: A model class represents a database table, and an instance of that
+class represents a particular record in the database table.
 
-get_list(\**kwargs)
--------------------
+To create an object, instantiate it using keyword arguments to the model class,
+then call ``save()`` to save it to the database.
 
-Returns a list of objects matching the given lookup parameters, which should be
-in the format described in &quot;Field lookups&quot; below. If no objects match the given
-parameters, it returns an empty list. ``get_list()`` will always return a list.
+You import the model class from wherever it lives on the Python path, as you
+may expect. (We point this out here because previous Django versions required
+funky model importing.)
 
-get_iterator(\**kwargs)
------------------------
+Assuming models live in a file ``mysite/blog/models.py``, here's an example::
 
-Just like ``get_list()``, except it returns an iterator instead of a list. This
-is more efficient for large result sets. This example shows the difference::
+    from mysite.blog.models import Blog
+    b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
+    b.save()
 
-    # get_list() loads all objects into memory.
-    for obj in foos.get_list():
-        print repr(obj)
+This performs an ``INSERT`` SQL statement behind the scenes. Django doesn't hit
+the database until you explicitly call ``save()``.
 
-    # get_iterator() only loads a number of objects into memory at a time.
-    for obj in foos.get_iterator():
-        print repr(obj)
+The ``save()`` method has no return value.
 
-get_count(\**kwargs)
---------------------
+Auto-incrementing primary keys
+------------------------------
 
-Returns an integer representing the number of objects in the database matching
-the given lookup parameters, which should be in the format described in
-&quot;Field lookups&quot; below. ``get_count()`` never raises exceptions
+If a model has an ``AutoField`` -- an auto-incrementing primary key -- then
+that auto-incremented value will be calculated and saved as an attribute on
+your object the first time you call ``save()``.
 
-Depending on which database you're using (e.g. PostgreSQL vs. MySQL), this may
-return a long integer instead of a normal Python integer.
+Example::
 
-get_values(\**kwargs)
----------------------
+    b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
+    b2.id     # Returns None, because b doesn't have an ID yet.
+    b2.save()
+    b2.id     # Returns the ID of your new object.
 
-Just like ``get_list()``, except it returns a list of dictionaries instead of
-model-instance objects.
-
-It accepts an optional parameter, ``fields``, which should be a list or tuple
-of field names. If you don't specify ``fields``, each dictionary in the list
-returned by ``get_values()`` will have a key and value for each field in the
-database table. If you specify ``fields``, each dictionary will have only the
-field keys/values for the fields you specify. Here's an example, using the
-``Poll`` model defined above::
-
-    &gt;&gt;&gt; from datetime import datetime
-    &gt;&gt;&gt; p1 = polls.Poll(slug='whatsup', question=&quot;What's up?&quot;,
-    ...     pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20))
-    &gt;&gt;&gt; p1.save()
-    &gt;&gt;&gt; p2 = polls.Poll(slug='name', question=&quot;What's your name?&quot;,
-    ...     pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20))
-    &gt;&gt;&gt; p2.save()
-    &gt;&gt;&gt; polls.get_list()
-    [What's up?, What's your name?]
-    &gt;&gt;&gt; polls.get_values()
-    [{'id': 1, 'slug': 'whatsup', 'question': &quot;What's up?&quot;, 'pub_date': datetime.datetime(2005, 2, 20), 'expire_date': datetime.datetime(2005, 3, 20)},
-     {'id': 2, 'slug': 'name', 'question': &quot;What's your name?&quot;, 'pub_date': datetime.datetime(2005, 3, 20), 'expire_date': datetime.datetime(2005, 4, 20)}]
-    &gt;&gt;&gt; polls.get_values(fields=['id', 'slug'])
-    [{'id': 1, 'slug': 'whatsup'}, {'id': 2, 'slug': 'name'}]
-
-Use ``get_values()`` when you know you're only going to need a couple of field
-values and you won't need the functionality of a model instance object. It's
-more efficient to select only the fields you need to use.
-
-get_values_iterator(\**kwargs)
-------------------------------
+There's no way to tell what the value of an ID will be before you call
+``save()``, because that value is calculated by your database, not by Django.
 
-Just like ``get_values()``, except it returns an iterator instead of a list.
-See the section on ``get_iterator()`` above.
-
-get_in_bulk(id_list, \**kwargs)
--------------------------------
-
-Takes a list of IDs and returns a dictionary mapping each ID to an instance of
-the object with the given ID. Also takes optional keyword lookup arguments,
-which should be in the format described in &quot;Field lookups&quot; below. Here's an
-example, using the ``Poll`` model defined above::
-
-    &gt;&gt;&gt; from datetime import datetime
-    &gt;&gt;&gt; p1 = polls.Poll(slug='whatsup', question=&quot;What's up?&quot;,
-    ...     pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20))
-    &gt;&gt;&gt; p1.save()
-    &gt;&gt;&gt; p2 = polls.Poll(slug='name', question=&quot;What's your name?&quot;,
-    ...     pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20))
-    &gt;&gt;&gt; p2.save()
-    &gt;&gt;&gt; polls.get_list()
-    [What's up?, What's your name?]
-    &gt;&gt;&gt; polls.get_in_bulk([1])
-    {1: What's up?}
-    &gt;&gt;&gt; polls.get_in_bulk([1, 2])
-    {1: What's up?, 2: What's your name?}
+(For convenience, each model has an ``AutoField`` named ``id`` by default
+unless you explicitly specify ``primary_key=True`` on a field. See the
+`AutoField documentation`_.)
 
-Field lookups
-=============
+.. _AutoField documentation: TODO: Link
 
-Basic field lookups take the form ``field__lookuptype`` (that's a
-double-underscore). For example::
+Explicitly specifying auto-primary-key values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    polls.get_list(pub_date__lte=datetime.datetime.now())
+If a model has an ``AutoField`` but you want to define a new object's ID
+explicitly when saving, just define it explicitly before saving, rather than
+relying on the auto-assignment of the ID.
 
-translates (roughly) into the following SQL::
+Example::
 
-    SELECT * FROM polls_polls WHERE pub_date &lt;= NOW();
+    b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
+    b3.id     # Returns 3.
+    b3.save()
+    b3.id     # Returns 3.
 
-.. admonition:: How this is possible
+If you assign auto-primary-key values manually, make sure not to use an
+already-existing primary-key value! If you create a new object with an explicit
+primary-key value that already exists in the database, Django will assume
+you're changing the existing record rather than creating a new one.
 
-   Python has the ability to define functions that accept arbitrary name-value
-   arguments whose names and values are evaluated at run time. For more
-   information, see `Keyword Arguments`_ in the official Python tutorial.
+Given the above ``'Cheddar Talk'`` blog example, this example would override
+the previous record in the database::
 
-The DB API supports the following lookup types:
-
-    ===========  ==============================================================
-    Type         Description
-    ===========  ==============================================================
-    exact        Exact match: ``polls.get_object(id__exact=14)``.
-    iexact       Case-insensitive exact match:
-                 ``polls.get_list(slug__iexact=&quot;foo&quot;)`` matches a slug of
-                 ``foo``, ``FOO``, ``fOo``, etc.
-    contains     Case-sensitive containment test:
-                 ``polls.get_list(question__contains=&quot;spam&quot;)`` returns all polls
-                 that contain &quot;spam&quot; in the question. (PostgreSQL and MySQL
-                 only. SQLite doesn't support case-sensitive LIKE statements;
-                 ``contains`` will act like ``icontains`` for SQLite.)
-    icontains    Case-insensitive containment test.
-    gt           Greater than: ``polls.get_list(id__gt=4)``.
-    gte          Greater than or equal to.
-    lt           Less than.
-    lte          Less than or equal to.
-    ne           Not equal to.
-    in           In a given list: ``polls.get_list(id__in=[1, 3, 4])`` returns
-                 a list of polls whose IDs are either 1, 3 or 4.
-    startswith   Case-sensitive starts-with:
-                 ``polls.get_list(question__startswith=&quot;Would&quot;)``. (PostgreSQL
-                 and MySQL only. SQLite doesn't support case-sensitive LIKE
-                 statements; ``startswith`` will act like ``istartswith`` for
-                 SQLite.)
-    endswith     Case-sensitive ends-with. (PostgreSQL and MySQL only.)
-    istartswith  Case-insensitive starts-with.
-    iendswith    Case-insensitive ends-with.
-    range        Range test:
-                 ``polls.get_list(pub_date__range=(start_date, end_date))``
-                 returns all polls with a pub_date between ``start_date``
-                 and ``end_date`` (inclusive).
-    year         For date/datetime fields, exact year match:
-                 ``polls.get_count(pub_date__year=2005)``.
-    month        For date/datetime fields, exact month match.
-    day          For date/datetime fields, exact day match.
-    isnull       True/False; does is IF NULL/IF NOT NULL lookup:
-                 ``polls.get_list(expire_date__isnull=True)``.
-    ===========  ==============================================================
-
-Multiple lookups are allowed, of course, and are translated as &quot;AND&quot;s::
-
-    polls.get_list(
-        pub_date__year=2005,
-        pub_date__month=1,
-        question__startswith=&quot;Would&quot;,
-    )
+    b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
+    b4.save()  # Overrides the previous blog with ID=3!
 
-...retrieves all polls published in January 2005 that have a question starting with &quot;Would.&quot;
+See _`How Django knows to UPDATE vs. INSERT`, below, for the reason this
+happens.
 
-For convenience, there's a ``pk`` lookup type, which translates into
-``(primary_key)__exact``. In the polls example, these two statements are
-equivalent::
+Explicitly specifying auto-primary-key values is mostly useful for bulk-saving
+objects, when you're confident you won't have primary-key collision.
 
-    polls.get_object(id__exact=3)
-    polls.get_object(pk=3)
+Saving changes to objects
+=========================
 
-``pk`` lookups also work across joins. In the polls example, these two
-statements are equivalent::
+To save changes to an object that's already in the database, use ``save()``.
 
-    choices.get_list(poll__id__exact=3)
-    choices.get_list(poll__pk=3)
+Given a ``Blog`` instance ``b5`` that has already been saved to the database,
+this example changes its name and updates its record in the database::
 
-If you pass an invalid keyword argument, the function will raise ``TypeError``.
+    b5.name = 'New name'
+    b5.save()
 
-.. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000
+This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit
+the database until you explicitly call ``save()``.
 
-OR lookups
-----------
+The ``save()`` method has no return value.
 
-By default, multiple lookups are &quot;AND&quot;ed together. If you'd like to use ``OR``
-statements in your queries, use the ``complex`` lookup type.
+How Django knows to UPDATE vs. INSERT
+-------------------------------------
 
-``complex`` takes an expression of clauses, each of which is an instance of
-``django.core.meta.Q``. ``Q`` takes an arbitrary number of keyword arguments in
-the standard Django lookup format. And you can use Python's &quot;and&quot; (``&amp;``) and
-&quot;or&quot; (``|``) operators to combine ``Q`` instances. For example::
+You may have noticed Django database objects use the same ``save()`` method
+for creating and changing objects. Django abstracts the need to use ``INSERT``
+or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django
+follows this algorithm:
+
+    * If the object's primary key attribute is set to a value that evaluates to
+      ``False`` (such as ``None`` or the empty string), Django executes a
+      ``SELECT`` query to determine whether a record with the given primary key
+      already exists.
+    * If the record with the given primary key does already exist, Django
+      executes an ``UPDATE`` query.
+    * If the object's primary key attribute is *not* set, or if it's set but a
+      record doesn't exist, Django executes an ``INSERT``.
+
+The one gotcha here is that you should be careful not to specify a primary-key
+value explicitly when saving new objects, if you cannot guarantee the
+primary-key value is unused. For more on this nuance, see
+&quot;Explicitly specifying auto-primary-key values&quot; above.
+
+Retrieving objects
+==================
+
+To retrieve objects from your database, you construct a ``QuerySet`` via a
+``Manager`` on your model class.
+
+A ``QuerySet`` represents a collection of objects from your database. It can
+have zero, one or many *filters* -- criteria that narrow down the collection
+based on given parameters. In SQL terms, a ``QuerySet`` equates to a ``SELECT``
+statement, and a filter is a limiting clause such as ``WHERE`` or ``LIMIT``.
+
+You get a ``QuerySet`` by using your model's ``Manager``. Each model has at
+least one ``Manager``, and it's called ``objects`` by default. Access it
+directly via the model class, like so::
+
+    Blog.objects  # &lt;django.db.models.manager.Manager object at ...&gt;
+    b = Blog(name='Foo', tagline='Bar')
+    b.objects     # AttributeError: &quot;Manager isn't accessible via Blog instances.&quot;
+
+(``Managers`` are accessible only via model classes, rather than from model
+instances, to enforce a separation between &quot;table-level&quot; operations and
+&quot;record-level&quot; operations.)
+
+The ``Manager`` is the main source of ``QuerySets`` for a model. It acts as a
+&quot;root&quot; ``QuerySet`` that describes all objects in the model's database table.
+For example, ``Blog.objects`` is the initial ``QuerySet`` that contains all
+``Blog`` objects in the database.
+
+Retrieving all objects
+----------------------
 
-    from django.core.meta import Q
-    polls.get_object(complex=(Q(question__startswith='Who') | Q(question__startswith='What')))
+The simplest way to retrieve objects from a table is to get all of them.
+To do this, use the ``all()`` method on a ``Manager``.
 
-The ``|`` symbol signifies an &quot;OR&quot;, so this (roughly) translates into::
+Example::
+
+    all_entries = Entry.objects.all()
+
+The ``all()`` method returns a ``QuerySet`` of all the objects in the database.
+
+(If ``Entry.objects`` is a ``QuerySet``, why can't we just do ``Entry.objects``?
+That's because ``Entry.objects``, the root ``QuerySet``, is a special case
+that cannot be evaluated. The ``all()`` method returns a ``QuerySet`` that
+*can* be evaluated.)
+
+Filtering objects
+-----------------
 
-    SELECT * FROM polls
-    WHERE question LIKE 'Who%' OR question LIKE 'What%';
+The root ``QuerySet`` provided by the ``Manager`` describes all objects in the
+database table. Usually, though, you'll need to select only a subset of the
+complete set of objects.
+
+To create such a subset, you refine the initial ``QuerySet``, adding filter
+conditions. The two most common ways to refine a ``QuerySet`` are:
+
+``filter(**kwargs)``
+    Returns a new ``QuerySet`` containing objects that match the given lookup
+    parameters.
+
+``exclude(**kwargs)``
+    Returns a new ``QuerySet`` containing objects that do *not* match the given
+    lookup parameters.
+
+The lookup parameters (``**kwargs`` in the above function definitions) should
+be in the format described in _`Field lookups` below.
+
+For example, to get a ``QuerySet`` of blog entries from the year 2006, use
+``filter()`` like so::
+
+    Entry.objects.filter(pub_date__year=2006)
+
+(Note we don't have to add an ``all()`` -- ``Entry.objects.all().filter(...)``.
+That would still work, but you only need ``all()`` when you want all objects
+from the root ``QuerySet``.)
+
+Chaining filters
+~~~~~~~~~~~~~~~~
+
+The result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's
+possible to chain refinements together. For example::
+
+    Entry.objects.filter(
+        headline__startswith='What').exclude(
+            pub_date__gte=datetime.now()).filter(
+                pub_date__gte=datetime(2005, 1, 1))
+
+...takes the initial ``QuerySet`` of all entries in the database, adds a
+filter, then an exclusion, then another filter. The final result is a
+``QuerySet`` containing all entries with a headline that starts with &quot;What&quot;,
+that were published between January 1, 2005, and the current day.
+
+Filtered QuerySets are unique
+-----------------------------
+
+Each time you refine a ``QuerySet``, you get a brand-new ``QuerySet`` that is
+in no way bound to the previous ``QuerySet``. Each refinement creates a
+separate and distinct ``QuerySet`` that can be stored, used and reused.
 
-You can use ``&amp;`` and ``|`` operators together, and use parenthetical grouping.
 Example::
 
-    polls.get_object(complex=(Q(question__startswith='Who') &amp; (Q(pub_date__exact=date(2005, 5, 2)) | Q(pub_date__exact=date(2005, 5, 6))))
+    q1 = Entry.objects.filter(headline__startswith=&quot;What&quot;)
+    q2 = q1.exclude(pub_date__gte=datetime.now())
+    q3 = q1.filter(pub_date__gte=datetime.now())
 
-This roughly translates into::
+These three ``QuerySets`` are separate. The first is a base ``QuerySet``
+containing all entries that contain a headline starting with &quot;What&quot;. The second
+is a subset of the first, with an additional criteria that excludes records
+whose ``pub_date`` is greater than now. The third is a subset of the first,
+with an additional criteria that selects only the records whose ``pub_date`` is
+greater than now. The initial ``QuerySet`` (``q1``) is unaffected by the
+refinement process.
 
-    SELECT * FROM polls
-    WHERE question LIKE 'Who%'
-        AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06');
+QuerySets are lazy
+------------------
 
-See the `OR lookups examples page`_ for more examples.
+``QuerySets`` are lazy -- the act of creating a ``QuerySet`` doesn't involve
+any database activity. You can stack filters together all day long, and Django
+won't actually run the query until the ``QuerySet`` is *evaluated*.
 
-.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/
+When QuerySets are evaluated
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Ordering
-========
+You can evaluate a ``QuerySet`` in the following ways:
 
-The results are automatically ordered by the ordering tuple given by the
-``ordering`` key in the model, but the ordering may be explicitly
-provided by the ``order_by`` argument to a lookup::
+    * **Iteration.** A ``QuerySet`` is iterable, and it executes its database
+      query the first time you iterate over it. For example, this will print
+      the headline of all entries in the database::
 
-    polls.get_list(
-        pub_date__year=2005,
-        pub_date__month=1,
-        order_by=('-pub_date', 'question'),
-    )
+          for e in Entry.objects.all():
+              print e.headline
+
+    * **Slicing.** A ``QuerySet`` can be sliced, using Python's array-slicing
+      syntax, and it executes its database query the first time you slice it.
+      Examples::
+
+          fifth_entry = Entry.objects.all()[4]
+          all_entries_but_the_first_two = Entry.objects.all()[2:]
+          every_second_entry = Entry.objects.all()[::2]
+
+    * **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it.
+      This is for convenience in the Python interactive interpreter, so you can
+      immediately see your results when using the API interactively.
+
+    * **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it.
+      This, as you might expect, returns the length of the result list.
+
+      Note: *Don't* use ``len()`` on ``QuerySet``s if all you want to do is
+      determine the number of records in the set. It's much more efficient to
+      handle a count at the database level, using SQL's ``SELECT COUNT(*)``,
+      and Django provides a ``count()`` method for precisely this reason. See
+      ``count()`` below.
+
+    * **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on
+      it. For example::
+
+          entry_list = list(Entry.objects.all())
 
-The result set above will be ordered by ``pub_date`` descending, then
-by ``question`` ascending. The negative sign in front of &quot;-pub_date&quot; indicates
-descending order. Ascending order is implied. To order randomly, use &quot;?&quot;, like
-so::
+      Be warned, though, that this could have a large memory overhead, because
+      Django will load each element of the list into memory. In contrast,
+      iterating over a ``QuerySet`` will take advantage of your database to
+      load data and instantiate objects only as you need them.
 
-    polls.get_list(order_by=['?'])
+QuerySet methods that return new QuerySets
+------------------------------------------
+
+Django provides a range of ``QuerySet`` refinement methods that modify either
+the types of results returned by the ``QuerySet`` or the way its SQL query is
+executed.
+
+filter(**kwargs)
+~~~~~~~~~~~~~~~~
+
+Returns a new ``QuerySet`` containing objects that match the given lookup
+parameters.
+
+The lookup parameters (``**kwargs``) should be in the format described in
+_`Field lookups` below. Multiple parameters are joined via ``AND`` in the
+underlying SQL statement.
+
+exclude(**kwargs)
+~~~~~~~~~~~~~~~~~
+
+Returns a new ``QuerySet`` containing objects that do *not* match the given
+lookup parameters.
+
+The lookup parameters (``**kwargs``) should be in the format described in
+_`Field lookups` below. Multiple parameters are joined via ``AND`` in the
+underlying SQL statement, and the whole thing is enclosed in a ``NOT()``.
+
+This example excludes all entries whose ``pub_date`` is the current date/time
+AND whose ``headline`` is &quot;Hello&quot;::
+
+    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
+
+In SQL terms, that evaluates to::
+
+    SELECT ...
+    WHERE NOT (pub_date &gt; '2005-1-3' AND headline = 'Hello')
+
+This example excludes all entries whose ``pub_date`` is the current date/time
+OR whose ``headline`` is &quot;Hello&quot;::
+
+    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
+
+In SQL terms, that evaluates to::
+
+    SELECT ...
+    WHERE NOT pub_date &gt; '2005-1-3'
+    AND NOT headline = 'Hello'
+
+Note the second example is more restrictive.
+
+order_by(*fields)
+~~~~~~~~~~~~~~~~~
+
+By default, results returned by a ``QuerySet`` are ordered by the ordering
+tuple given by the ``ordering`` option in the model's ``Meta``. You can
+override this on a per-``QuerySet`` basis by using the ``order_by`` method.
+
+Example::
+
+    Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
+
+The result above will be ordered by ``pub_date`` descending, then by
+``headline`` ascending. The negative sign in front of ``&quot;-pub_date&quot;`` indicates
+*descending* order. Ascending order is implied. To order randomly, use ``&quot;?&quot;``,
+like so::
+
+    Entry.objects.order_by('?')
 
 To order by a field in a different table, add the other table's name and a dot,
 like so::
 
-    choices.get_list(order_by=('polls.pub_date', 'choice'))
+    Entry.objects.order_by('blogs_blog.name', 'headline')
 
 There's no way to specify whether ordering should be case sensitive. With
 respect to case-sensitivity, Django will order results however your database
 backend normally orders them.
 
-Relationships (joins)
-=====================
+distinct()
+~~~~~~~~~~
 
-Joins may implicitly be performed by following relationships:
-``choices.get_list(poll__slug__exact=&quot;eggs&quot;)`` fetches a list of ``Choice``
-objects where the associated ``Poll`` has a slug of ``eggs``.  Multiple levels
-of joins are allowed.
+Returns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This
+eliminates duplicate rows from the query results.
 
-Given an instance of an object, related objects can be looked-up directly using
-convenience functions. For example, if ``p`` is a ``Poll`` instance,
-``p.get_choice_list()`` will return a list of all associated choices. Astute
-readers will note that this is the same as
-``choices.get_list(poll__id__exact=p.id)``, except clearer.
+By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this
+is rarely a problem, because simple queries such as ``Blog.objects.all()``
+don't introduce the possibility of duplicate result rows.
 
-Each type of relationship creates a set of methods on each object in the
-relationship. These methods are created in both directions, so objects that are
-&quot;related-to&quot; need not explicitly define reverse relationships; that happens
-automatically.
+However, if your query spans multiple tables, it's possible to get duplicate
+results when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``.
 
-One-to-one relations
---------------------
+values(*fields)
+~~~~~~~~~~~~~~~
 
-Each object in a one-to-one relationship will have a ``get_relatedobjectname()``
-method. For example::
+Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of
+dictionaries instead of model-instance objects.
 
-    class Place(meta.Model):
-        # ...
+Each of those dictionaries represents an object, with the keys corresponding to
+the attribute names of model objects.
 
-    class Restaurant(meta.Model):
-        # ...
-        the_place = meta.OneToOneField(places.Place)
+This example compares the dictionaries of ``values()`` with the normal model
+objects::
 
-In the above example, each ``Place`` will have a ``get_restaurant()`` method,
-and each ``Restaurant`` will have a ``get_the_place()`` method.
+    # This list contains a Blog object.
+    &gt;&gt;&gt; Blog.objects.filter(name__startswith='Beatles')
+    [Beatles Blog]
 
-Many-to-one relations
----------------------
+    # This list contains a dictionary.
+    &gt;&gt;&gt; Blog.objects.filter(name__startswith='Beatles').values()
+    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]
 
-In each many-to-one relationship, the related object will have a
-``get_relatedobject()`` method, and the related-to object will have
-``get_relatedobject()``, ``get_relatedobject_list()``, and
-``get_relatedobject_count()`` methods (the same as the module-level
-``get_object()``, ``get_list()``, and ``get_count()`` methods).
+``values()`` takes optional positional arguments, ``*fields``, which specify
+field names to which the ``SELECT`` should be limited. If you specify the
+fields, each dictionary will contain only the field keys/values for the fields
+you specify. If you don't specify the fields, each dictionary will contain a
+key and value for every field in the database table.
 
-In the poll example above, here are the available choice methods on a ``Poll`` object ``p``::
+Example::
 
-    p.get_choice()
-    p.get_choice_list()
-    p.get_choice_count()
+    &gt;&gt;&gt; Blog.objects.values()
+    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
+    &gt;&gt;&gt; Blog.objects.values('id', 'name')
+    [{'id': 1, 'name': 'Beatles Blog'}]
 
-And a ``Choice`` object ``c`` has the following method::
+A ``ValuesQuerySet`` is useful when you know you're only going to need values
+from a small number of the available fields and you won't need the
+functionality of a model instance object. It's more efficient to select only
+the fields you need to use.
 
-    c.get_poll()
+Finally, note a ``ValuesQuerySet`` is a subclass of ``QuerySet``, so it has all
+methods of ``QuerySet``. You can call ``filter()`` on it, or ``order_by()``, or
+whatever. Yes, that means these two calls are identical::
 
-Many-to-many relations
-----------------------
+    Blog.objects.values().order_by('id')
+    Blog.objects.order_by('id').values()
 
-Many-to-many relations result in the same set of methods as `Many-to-one relations`_,
-except that the ``get_relatedobject_list()`` function on the related object will
-return a list of instances instead of a single instance.  So, if the relationship
-between ``Poll`` and ``Choice`` was many-to-many, ``choice.get_poll_list()`` would
-return a list.
+The people who made Django prefer to put all the SQL-affecting methods first,
+followed (optionally) by any output-affecting methods (such as ``values()``),
+but it doesn't really matter. This is your chance to really flaunt your
+individualism.
 
-Relationships across applications
----------------------------------
+dates(field, kind, order='ASC')
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If a relation spans applications -- if ``Place`` was had a ManyToOne relation to
-a ``geo.City`` object, for example -- the name of the other application will be
-added to the method, i.e. ``place.get_geo_city()`` and
-``city.get_places_place_list()``.
+Returns a ``DateQuerySet`` -- a ``QuerySet`` that evaluates to a list of
+``datetime.datetime`` objects representing all available dates of a particular
+kind within the contents of the ``QuerySet``.
 
-Selecting related objects
--------------------------
+``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your
+model.
 
-Relations are the bread and butter of databases, so there's an option to &quot;follow&quot;
-all relationships and pre-fill them in a simple cache so that later calls to
-objects with a one-to-many relationship don't have to hit the database. Do this by
-passing ``select_related=True`` to a lookup. This results in (sometimes much) larger
-queries, but it means that later use of relationships is much faster.
+``kind`` should be either ``&quot;year&quot;``, ``&quot;month&quot;`` or ``&quot;day&quot;``. Each
+``datetime.datetime`` object in the result list is &quot;truncated&quot; to the given
+``type``.
 
-For example, using the Poll and Choice models from above, if you do the following::
+    * ``&quot;year&quot;`` returns a list of all distinct year values for the field.
+    * ``&quot;month&quot;`` returns a list of all distinct year/month values for the field.
+    * ``&quot;day&quot;`` returns a list of all distinct year/month/day values for the field.
+
+``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or
+``'DESC'``. This specifies how to order the results.
 
-    c = choices.get_object(id__exact=5, select_related=True)
+Examples::
 
-Then subsequent calls to ``c.get_poll()`` won't hit the database.
+    &gt;&gt;&gt; Entry.objects.dates('pub_date', 'year')
+    [datetime.datetime(2005, 1, 1)]
+    &gt;&gt;&gt; Entry.objects.dates('pub_date', 'month')
+    [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]
+    &gt;&gt;&gt; Entry.objects.dates('pub_date', 'day')
+    [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]
+    &gt;&gt;&gt; Entry.objects.dates('pub_date', 'day', order='DESC')
+    [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]
+    &gt;&gt;&gt; Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
+    [datetime.datetime(2005, 3, 20)]
 
-Note that ``select_related`` follows foreign keys as far as possible. If you have the
+select_related()
+~~~~~~~~~~~~~~~~
+
+Returns a ``QuerySet`` that will automatically &quot;follow&quot; foreign-key
+relationships, selecting that additional related-object data when it executes
+its query. This is a performance booster which results in (sometimes much)
+larger queries but means later use of foreign-key relationships won't require
+database queries.
+
+The following examples illustrate the difference between plain lookups and
+``select_related()`` lookups. Here's standard lookup::
+
+    # Hits the database.
+    e = Entry.objects.get(id=5)
+
+    # Hits the database again to get the related Blog object.
+    b = e.blog
+
+And here's ``select_related`` lookup::
+
+    # Hits the database.
+    e = Entry.objects.select_related().get(id=5)
+
+    # Doesn't hit the database, because e.blog has been prepopulated
+    # in the previous query.
+    b = e.blog
+
+``select_related()`` follows foreign keys as far as possible. If you have the
 following models::
 
-    class Poll(meta.Model):
+    class City(models.Model):
         # ...
 
-    class Choice(meta.Model):
+    class Person(models.Model):
         # ...
-        poll = meta.ForeignKey(Poll)
+        hometown = models.ForeignKey(City)
 
-    class SingleVote(meta.Model):
+    class Book(meta.Model):
         # ...
-        choice = meta.ForeignKey(Choice)
+        author = models.ForeignKey(Person)
 
-then a call to ``singlevotes.get_object(id__exact=4, select_related=True)`` will
-cache the related choice *and* the related poll::
+...then a call to ``Book.objects.select_related().get(id=4)`` will cache the
+related ``Person`` *and* the related ``City``::
 
-    &gt;&gt;&gt; sv = singlevotes.get_object(id__exact=4, select_related=True)
-    &gt;&gt;&gt; c = sv.get_choice()        # Doesn't hit the database.
-    &gt;&gt;&gt; p = c.get_poll()           # Doesn't hit the database.
+    b = Book.objects.select_related().get(id=4)
+    p = b.author         # Doesn't hit the database.
+    c = p.hometown       # Doesn't hit the database.
 
-    &gt;&gt;&gt; sv = singlevotes.get_object(id__exact=4) # Note no &quot;select_related&quot;.
-    &gt;&gt;&gt; c = sv.get_choice()        # Hits the database.
-    &gt;&gt;&gt; p = c.get_poll()           # Hits the database.
+    sv = Book.objects.get(id=4) # No select_related() in this example.
+    p = b.author         # Hits the database.
+    c = p.hometown       # Hits the database.
 
-Limiting selected rows
-======================
+extra(select=None, where=None, params=None, tables=None)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The ``limit``, ``offset``, and ``distinct`` keywords can be used to control
-which rows are returned.  Both ``limit`` and ``offset`` should be integers which
-will be directly passed to the SQL ``LIMIT``/``OFFSET`` commands.
+Sometimes, the Django query syntax by itself can't easily express a complex
+``WHERE`` clause. For these edge cases, Django provides the ``extra()``
+``QuerySet`` modifier -- a hook for injecting specific clauses into the SQL
+generated by a ``QuerySet``.
 
-If ``distinct`` is True, only distinct rows will be returned. This is equivalent
-to a ``SELECT DISTINCT`` SQL clause. You can use this with ``get_values()`` to
-get distinct values. For example, this returns the distinct first_names::
+By definition, these extra lookups may not be portable to different database
+engines (because you're explicitly writing SQL code) and violate the DRY
+principle, so you should avoid them if possible.
+
+Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None
+of the arguments is required, but you should use at least one of them.
+
+``select``
+    The ``select`` argument lets you put extra fields in the ``SELECT`` clause.
+    It should be a dictionary mapping attribute names to SQL clauses to use to
+    calculate that attribute.
 
-    &gt;&gt;&gt; people.get_values(fields=['first_name'], distinct=True)
-    [{'first_name': 'Adrian'}, {'first_name': 'Jacob'}, {'first_name': 'Simon'}]
+    Example::
 
-Other lookup options
-====================
+        Entry.objects.extra(select={'is_recent': &quot;pub_date &gt; '2006-01-01'&quot;})
 
-There are a few other ways of more directly controlling the generated SQL
-for the lookup.  Note that by definition these extra lookups may not be
-portable to different database engines (because you're explicitly writing
-SQL code) and should be avoided if possible.:
+    As a result, each ``Entry`` object will have an extra attribute,
+    ``is_recent``, a boolean representing whether the entry's ``pub_date`` is
+    greater than Jan. 1, 2006.
+
+    Django inserts the given SQL snippet directly into the ``SELECT``
+    statement, so the resulting SQL of the above example would be::
+
+        SELECT blog_entry.*, (pub_date &gt; '2006-01-01')
+        FROM blog_entry;
+
+
+    The next example is more advanced; it does a subquery to give each
+    resulting ``Blog`` object an ``entry_count`` attribute, an integer count
+    of associated ``Entry`` objects.
+
+        Blog.objects.extra(
+            select={
+                'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
+            },
+        )
+
+    (In this particular case, we're exploiting the fact that the query will
+    already contain the ``blog_blog`` table in its ``FROM`` clause.)
+
+    The resulting SQL of the above example would be::
+
+        SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id)
+        FROM blog_blog;
+
+    Note that the parenthesis required by most database engines around
+    subqueries are not required in Django's ``select`` clauses. Also note that
+    some database backends, such as some MySQL versions, don't support
+    subqueries.
+
+``where`` / ``tables``
+    You can define explicit SQL ``WHERE`` clauses -- perhaps to perform
+    non-explicit joins -- by using ``where``. You can manually add tables to
+    the SQL ``FROM`` clause by using ``tables``.
+
+    ``where`` and ``tables`` both take a list of strings. All ``where``
+    parameters are &quot;AND&quot;ed to any other search criteria.
+
+    Example::
+
+        Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
+
+    ...translates (roughly) into the following SQL::
+
+        SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
 
 ``params``
-----------
+    The ``select`` and ``where`` parameters described above may use standard
+    Python database string placeholders -- ``'%s'`` to indicate parameters the
+    database engine should automatically quote. The ``params`` argument is a
+    list of any extra parameters to be substituted.
 
-All the extra-SQL params described below may use standard Python string
-formatting codes to indicate parameters that the database engine will
-automatically quote.  The ``params`` argument can contain any extra
-parameters to be substituted.
+    Example::
 
-``select``
-----------
+        Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
+
+    Always use ``params`` instead of embedding values directly into ``select``
+    or ``where`` because ``params`` will ensure values are quoted correctly
+    according to your particular backend. (For example, quotes will be escaped
+    correctly.)
+
+    Bad::
+
+        Entry.objects.extra(where=[&quot;headline='Lennon'&quot;])
+
+    Good::
+
+        Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
+
+QuerySet methods that do not return QuerySets
+---------------------------------------------
+
+The following ``QuerySet`` methods evaluate the ``QuerySet`` and return
+something *other than* a ``QuerySet``.
+
+These methods do not use a cache (see _`Caching and QuerySets` below). Rather,
+they query the database each time they're called.
+
+get(**kwargs)
+~~~~~~~~~~~~~
+
+Returns the object matching the given lookup parameters, which should be in
+the format described in _`Field lookups`.
+
+``get()`` raises ``AssertionError`` if more than one object was found.
+
+``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for the
+given parameters. The ``DoesNotExist`` exception is an attribute of the model
+class. Example::
+
+    Entry.objects.get(id='foo') # raises Entry.DoesNotExist
+
+The ``DoesNotExist`` exception inherits from
+``django.core.exceptions.ObjectDoesNotExist``, so you can target multiple
+``DoesNotExist`` exceptions. Example::
+
+    from django.core.exceptions import ObjectDoesNotExist
+    try:
+        e = Entry.objects.get(id=3)
+        b = Blog.objects.get(id=1)
+    except ObjectDoesNotExist:
+        print &quot;Either the entry or blog doesn't exist.&quot;
+
+count()
+~~~~~~~
+
+Returns an integer representing the number of objects in the database matching
+the ``QuerySet``. ``count()`` never raises exceptions.
+
+Example::
+
+    # Returns the total number of entries in the database.
+    Entry.objects.count()
+
+    # Returns the number of entries whose headline contains 'Lennon'
+    Entry.objects.filter(headline__contains='Lennon').count()
+
+``count()`` performs a ``SELECT COUNT(*)`` behind the scenes, so you should
+always use ``count()`` rather than loading all of the record into Python
+objects and calling ``len()`` on the result.
+
+Depending on which database you're using (e.g. PostgreSQL vs. MySQL),
+``count()`` may return a long integer instead of a normal Python integer. This
+is an underlying implementation quirk that shouldn't pose any real-world
+problems.
+
+in_bulk(id_list)
+~~~~~~~~~~~~~~~~
+
+Takes a list of primary-key values and returns a dictionary mapping each
+primary-key value to an instance of the object with the given ID.
+
+Example::
+
+    &gt;&gt;&gt; Blog.objects.in_bulk([1])
+    {1: Beatles Blog}
+    &gt;&gt;&gt; Blog.objects.in_bulk([1, 2])
+    {1: Beatles Blog, 2: Cheddar Talk}
+    &gt;&gt;&gt; Blog.objects.in_bulk([])
+    {}
+
+If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary.
+
+latest(field_name=None)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Returns the latest object in the table, by date, using the ``field_name``
+provided as the date field.
+
+This example returns the latest ``Entry`` in the table, according to the
+``pub_date`` field::
+
+    Entry.objects.latest('pub_date')
+
+If your model's ``Meta`` specifies ``get_latest_by``, you can leave off the
+``field_name`` argument to ``latest()``. Django will use the field specified in
+``get_latest_by`` by default.
+
+Like ``get()``, ``latest()`` raises ``DoesNotExist`` if an object doesn't
+exist with the given parameters.
+
+Note ``latest()`` exists purely for convenience and readability.
+
+Field lookups
+-------------
+
+Field lookups are how you specify the meat of an SQL ``WHERE`` clause. They're
+specified as keyword arguments to the ``QuerySet`` methods ``filter()``,
+``exclude()`` and ``get()``.
+
+Basic lookups keyword arguments take the form ``field__lookuptype=value``.
+(That's a double-underscore). For example::
+
+    Entry.objects.filter(pub_date__lte='2006-01-01')
+
+translates (roughly) into the following SQL::
+
+    SELECT * FROM blog_entry WHERE pub_date &lt;= '2006-01-01';
+
+.. admonition:: How this is possible
+
+   Python has the ability to define functions that accept arbitrary name-value
+   arguments whose names and values are evaluated at runtime. For more
+   information, see `Keyword Arguments`_ in the official Python tutorial.
+
+   .. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000
+
+If you pass an invalid keyword argument, a lookup function will raise
+``TypeError``.
+
+The database API supports the following lookup types:
+
+exact
+~~~~~
+
+Exact match.
+
+Example::
+
+    Entry.objects.get(id__exact=14)
+
+SQL equivalent::
+
+    SELECT ... WHERE id = 14;
+
+iexact
+~~~~~~
+
+Case-insensitive exact match.
+
+Example::
+
+    Blog.objects.get(name__iexact='beatles blog')
+
+SQL equivalent::
+
+    SELECT ... WHERE name ILIKE 'beatles blog';
+
+Note this will match ``'Beatles Blog'``, ``'beatles blog'``,
+``'BeAtLes BLoG'``, etc.
+
+contains
+~~~~~~~~
+
+Case-sensitive containment test.
+
+Example::
+
+    Entry.objects.get(headline__contains='Lennon')
+
+SQL equivalent::
+
+    SELECT ... WHERE headline LIKE '%Lennon%';
+
+Note this will match the headline ``'Today Lennon honored'`` but not
+``'today lennon honored'``.
+
+SQLite doesn't support case-sensitive ``LIKE`` statements; ``contains`` acts
+like ``icontains`` for SQLite.
+
+icontains
+~~~~~~~~~
+
+Case-insensitive containment test.
+
+Example::
+
+    Entry.objects.get(headline__icontains='Lennon')
 
-The ``select`` keyword allows you to select extra fields.  This should be a
-dictionary mapping attribute names to a SQL clause to use to calculate that
-attribute. For example::
+SQL equivalent::
 
-    polls.get_list(
-        select={
-            'choice_count': 'SELECT COUNT(*) FROM choices WHERE poll_id = polls.id'
-        }
+    SELECT ... WHERE headline ILIKE '%Lennon%';
+
+gt
+~~
+
+Greater than.
+
+Example::
+
+    Entry.objects.filter(id__gt=4)
+
+SQL equivalent::
+
+    SELECT ... WHERE id &gt; 4;
+
+gte
+~~~
+
+Greater than or equal to.
+
+lt
+~~
+
+Less than.
+
+lte
+~~~
+
+Less than or equal to.
+
+in
+~~
+
+In a given list.
+
+Example::
+
+    Entry.objects.filter(id__in=[1, 3, 4])
+
+SQL equivalent::
+
+    SELECT ... WHERE id IN (1, 3, 4);
+
+startswith
+~~~~~~~~~~
+
+Case-sensitive starts-with.
+
+Example::
+
+    Entry.objects.filter(headline__startswith='Will')
+
+SQL equivalent::
+
+    SELECT ... WHERE headline LIKE 'Will%';
+
+SQLite doesn't support case-sensitive ``LIKE`` statements; ``startswith`` acts
+like ``istartswith`` for SQLite.
+
+istartswith
+~~~~~~~~~~~
+
+Case-insensitive starts-with.
+
+Example::
+
+    Entry.objects.filter(headline__istartswith='will')
+
+SQL equivalent::
+
+    SELECT ... WHERE headline ILIKE 'Will%';
+
+endswith
+~~~~~~~~
+
+Case-sensitive ends-with.
+
+Example::
+
+    Entry.objects.filter(headline__endswith='cats')
+
+SQL equivalent::
+
+    SELECT ... WHERE headline LIKE '%cats';
+
+SQLite doesn't support case-sensitive ``LIKE`` statements; ``endswith`` acts
+like ``iendswith`` for SQLite.
+
+iendswith
+~~~~~~~~~
+
+Case-insensitive ends-with.
+
+Example::
+
+    Entry.objects.filter(headline__iendswith='will')
+
+SQL equivalent::
+
+    SELECT ... WHERE headline ILIKE '%will'
+
+range
+~~~~~
+
+Range test (inclusive).
+
+Example::
+
+    start_date = datetime.date(2005, 1, 1)
+    end_date = datetime.date(2005, 3, 31)
+    Entry.objects.filter(pub_date__range=(start_date, end_date))
+
+SQL equivalent::
+
+    SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
+
+You can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates,
+numbers and even characters.
+
+year
+~~~~
+
+For date/datetime fields, exact year match. Takes a four-digit year.
+
+Example::
+
+    Entry.objects.filter(pub_date__year=2005)
+
+SQL equivalent::
+
+    SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005';
+
+(The exact SQL syntax varies for each database engine.)
+
+month
+~~~~~
+
+For date/datetime fields, exact month match. Takes an integer 1 (January)
+through 12 (December).
+
+Example::
+
+    Entry.objects.filter(pub_date__month=12)
+
+SQL equivalent::
+
+    SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
+
+(The exact SQL syntax varies for each database engine.)
+
+day
+~~~
+
+For date/datetime fields, exact day match.
+
+Example::
+
+    Entry.objects.filter(pub_date__day=3)
+
+SQL equivalent::
+
+    SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
+
+(The exact SQL syntax varies for each database engine.)
+
+Note this will match any record with a pub_date on the third day of the month,
+such as January 3, July 3, etc.
+
+isnull
+~~~~~~
+
+``NULL`` or ``IS NOT NULL`` match. Takes either ``True`` or ``False``, which
+correspond to ``IS NULL`` and ``IS NOT NULL``, respectively.
+
+Example::
+
+    Entry.objects.filter(pub_date__isnull=True)
+
+SQL equivalent::
+
+    SELECT ... WHERE pub_date IS NULL;
+
+Default lookups are exact
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you don't provide a lookup type -- that is, if your keyword argument doesn't
+contain a double underscore -- the lookup type is assumed to be ``exact``.
+
+For example, the following two statements are equivalent::
+
+    Blog.objects.get(id=14)
+    Blog.objects.get(id__exact=14)
+
+This is for convenience, because ``exact`` lookups are the common case.
+
+The pk lookup shortcut
+~~~~~~~~~~~~~~~~~~~~~~
+
+For convenience, Django provides a ``pk`` lookup type, which stands for
+&quot;primary_key&quot;. This is shorthand for &quot;an exact lookup on the primary-key.&quot;
+
+In the example ``Blog`` model, the primary key is the ``id`` field, so these
+two statements are equivalent::
+
+    Blog.objects.get(id__exact=14)
+    Blog.objects.get(pk=14)
+
+``pk`` lookups also work across joins. For example, these two statements are
+equivalent::
+
+    Entry.objects.filter(blog__id__exact=3)
+    Entry.objects.filter(blog__pk=3)
+
+Escaping parenthesis and underscores in LIKE statements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The field lookups that equate to ``LIKE`` SQL statements (``iexact``,
+``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith``
+and ``iendswith``) will automatically escape the two special characters used in
+``LIKE`` statements -- the percent sign and the underscore. (In a ``LIKE``
+statement, the percent sign signifies a multiple-character wildcard and the
+underscore signifies a single-character wildcard.)
+
+This means things should work intuitively, so the abstraction doesn't leak.
+For example, to retrieve all the entries that contain a percent sign, just use
+the percent sign as any other character::
+
+    Entry.objects.filter(headline__contains='%')
+
+Django takes care of the quoting for you; the resulting SQL will look something
+like this::
+
+    SELECT ... WHERE headline LIKE '%\%%';
+
+Same goes for underscores. Both percentage signs and underscores are handled
+for you transparently.
+
+Caching and QuerySets
+---------------------
+
+Each ``QuerySet`` contains a cache, to minimize database access. It's important
+to understand how it works, in order to write the most efficient code.
+
+In a newly created ``QuerySet``, the cache is empty. The first time a
+``QuerySet`` is evaluated -- and, hence, a database query happens -- Django
+saves the query results in the ``QuerySet``'s cache and returns the results
+that have been explicitly requested (e.g., the next element, if the
+``QuerySet`` is being iterated over). Subsequent evaluations of the
+``QuerySet`` reuse the cached results.
+
+Keep this caching behavior in mind, because it may bite you if you don't use
+your ``QuerySet``s correctly. For example, the following will create two
+``QuerySet``s, evaluate them, and throw them away::
+
+    print [e.headline for e in Entry.objects.all()]
+    print [e.pub_date for e in Entry.objects.all()]
+
+That means the same database query will be executed twice, effectively doubling
+your database load. Also, there's a possibility the two lists may not include
+the same database records, because an ``Entry`` may have been added or deleted
+in the split second between the two requests.
+
+To avoid this problem, simply save the ``QuerySet`` and reuse it::
+
+    queryset = Poll.objects.all()
+    print [p.headline for p in queryset] # Evaluate the query set.
+    print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.
+
+Comparing objects
+=================
+
+To compare two model instances, just use the standard Python comparison operator,
+the double equals sign: ``==``. Behind the scenes, that compares the primary
+key values of two models.
+
+Using the ``Entry`` example above, the following two statements are equivalent::
+
+    some_entry == other_entry
+    some_entry.id == other_entry.id
+
+If a model's primary key isn't called ``id``, no problem. Comparisons will
+always use the primary key, whatever it's called. For example, if a model's
+primary key field is called ``name``, these two statements are equivalent::
+
+    some_obj == other_obj
+    some_obj.name == other_obj.name
+
+
+
+
+========================================
+THE REST OF THIS HAS NOT YET BEEN EDITED
+========================================
+
+
+OR lookups
+==========
+
+Keyword argument queries are &quot;AND&quot;ed together. If you have more
+complex query requirements (for example, you need to include an ``OR``
+statement in your query), you need to use ``Q`` objects.
+
+A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a
+collection of keyword arguments. These keyword arguments are specified in
+the same way as keyword arguments to the basic lookup functions like get()
+and filter(). For example::
+
+    Q(question__startswith='What')
+
+is a ``Q`` object encapsulating a single ``LIKE`` query. ``Q`` objects can be
+combined using the ``&amp;`` and ``|`` operators. When an operator is used on two
+``Q`` objects, it yields a new ``Q`` object. For example the statement::
+
+    Q(question__startswith='Who') | Q(question__startswith='What')
+
+... yields a single ``Q`` object that represents the &quot;OR&quot; of two
+&quot;question__startswith&quot; queries, equivalent to the SQL WHERE clause::
+
+    ... WHERE question LIKE 'Who%' OR question LIKE 'What%'
+
+You can compose statements of arbitrary complexity by combining ``Q`` objects
+with the ``&amp;`` and ``|`` operators. Parenthetical grouping can also be used.
+
+One or more ``Q`` objects can then provided as arguments to the lookup
+functions. If multiple ``Q`` object arguments are provided to a lookup
+function, they will be &quot;AND&quot;ed together. For example::
+
+    Poll.objects.get(
+        Q(question__startswith='Who'),
+        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
     )
 
-Each of the resulting ``Poll`` objects will have an extra attribute, ``choice_count``,
-an integer count of associated ``Choice`` objects. Note that the parenthesis required by
-most database engines around sub-selects are not required in Django's ``select``
-clauses.
+... roughly translates into the SQL::
 
-``where`` / ``tables``
-----------------------
+    SELECT * from polls WHERE question LIKE 'Who%'
+        AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
+
+If necessary, lookup functions can mix the use of ``Q`` objects and keyword
+arguments. All arguments provided to a lookup function (be they keyword
+argument or ``Q`` object) are &quot;AND&quot;ed together. However, if a ``Q`` object is
+provided, it must precede the definition of any keyword arguments. For
+example::
+
+    Poll.objects.get(
+        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
+        question__startswith='Who')
+
+... would be a valid query, equivalent to the previous example; but::
+
+    # INVALID QUERY
+    Poll.objects.get(
+        question__startswith='Who',
+        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
 
-If you need to explicitly pass extra ``WHERE`` clauses -- perhaps to perform
-non-explicit joins -- use the ``where`` keyword. If you need to
-join other tables into your query, you can pass their names to ``tables``.
+... would not be valid.
 
-``where`` and ``tables`` both take a list of strings. All ``where`` parameters
-are &quot;AND&quot;ed to any other search criteria.
+A ``Q`` objects can also be provided to the ``complex`` keyword argument. For example::
 
+    Poll.objects.get(
+        complex=Q(question__startswith='Who') &amp;
+            (Q(pub_date=date(2005, 5, 2)) |
+             Q(pub_date=date(2005, 5, 6))
+        )
+    )
+
+See the `OR lookups examples page`_ for more examples.
+
+.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/
+
+
+Relationships (joins)
+=====================
+
+When you define a relationship in a model (i.e., a ForeignKey,
+OneToOneField, or ManyToManyField), Django uses the name of the
+relationship to add a descriptor_ on every instance of the model.
+This descriptor behaves just like a normal attribute, providing
+access to the related object or objects.  For example,
+``mychoice.poll`` will return the poll object associated with a specific
+instance of ``Choice``.
+
+.. _descriptor: http://users.rcn.com/python/download/Descriptor.htm
+
+Django also adds a descriptor for the 'other' side of the relationship -
+the link from the related model to the model that defines the relationship.
+Since the related model has no explicit reference to the source model,
+Django will automatically derive a name for this descriptor. The name that
+Django chooses depends on the type of relation that is represented. However,
+if the definition of the relation has a `related_name` parameter, Django
+will use this name in preference to deriving a name.
+
+There are two types of descriptor that can be employed: Single Object
+Descriptors and Object Set Descriptors. The following table describes
+when each descriptor type is employed. The local model is the model on
+which the relation is defined; the related model is the model referred
+to by the relation.
+
+    =============== ============= =============
+    Relation Type   Local Model   Related Model
+    =============== ============= =============
+    OneToOneField   Single Object Single Object
+
+    ForeignKey      Single Object Object Set
+
+    ManyToManyField Object Set    Object Set
+    =============== ============= =============
+
+Single object descriptor
+------------------------
+
+If the related object is a single object, the descriptor acts
+just as if the related object were an attribute::
+
+    # Obtain the existing poll
+    old_poll = mychoice.poll
+    # Set a new poll
+    mychoice.poll = new_poll
+    # Save the change
+    mychoice.save()
+
+Whenever a change is made to a Single Object Descriptor, save()
+must be called to commit the change to the database.
+
+If no `related_name` parameter is defined, Django will use the
+lower case version of the source model name as the name for the
+related descriptor. For example, if the ``Choice`` model had
+a field::
+
+    coordinator = models.OneToOneField(User)
+
+... instances of the model ``User`` would be able to call:
+
+    old_choice = myuser.choice
+    myuser.choice = new_choice
+
+By default, relations do not allow values of None; if you attempt
+to assign None to a Single Object Descriptor, an AttributeError
+will be thrown. However, if the relation has 'null=True' set
+(i.e., the database will allow NULLs for the relation), None can
+be assigned and returned by the descriptor to represent empty
+relations.
+
+Access to Single Object Descriptors is cached. The first time
+a descriptor on an instance is accessed, the database will be
+queried, and the result stored. Subsequent attempts to access
+the descriptor on the same instance will use the cached value.
+
+Object set descriptor
+---------------------
+
+An Object Set Descriptor acts just like the Manager - as an initial Query
+Set describing the set of objects related to an instance. As such, any
+query refining technique (filter, exclude, etc) can be used on the Object
+Set descriptor. This also means that Object Set Descriptor cannot be evaluated
+directly - the ``all()`` method must be used to produce a Query Set that
+can be evaluated.
+
+If no ``related_name`` parameter is defined, Django will use the lower case
+version of the source model name appended with `_set` as the name for the
+related descriptor. For example, every ``Poll`` object has a ``choice_set``
+descriptor.
+
+The Object Set Descriptor has utility methods to add objects to the
+related object set:
+
+``add(obj1, obj2, ...)``
+    Add the specified objects to the related object set.
+
+``create(\**kwargs)``
+    Create a new object, and put it in the related object set. See
+    _`Creating new objects`
+
+The Object Set Descriptor may also have utility methods to remove objects
+from the related object set:
+
+``remove(obj1, obj2, ...)``
+    Remove the specified objects from the related object set.
+
+``clear()``
+    Remove all objects from the related object set.
+
+These two removal methods will not exist on ForeignKeys where ``Null=False``
+(such as in the Poll example). This is to prevent database inconsistency - if
+the related field cannot be set to None, then an object cannot be removed
+from one relation without adding it to another.
+
+The members of a related object set can be assigned from any iterable object.
 For example::
 
-    polls.get_list(question__startswith='Who', where=['id IN (3, 4, 5, 20)'])
+    mypoll.choice_set = [choice1, choice2]
 
-...translates (roughly) into the following SQL:
+If the ``clear()`` method is available, any pre-existing objects will be removed
+from the Object Set before all objects in the iterable (in this case, a list)
+are added to the choice set. If the ``clear()`` method is not available, all
+objects in the iterable will be added without removing any existing elements.
 
-    SELECT * FROM polls_polls WHERE question LIKE 'Who%' AND id IN (3, 4, 5, 20);
+Each of these operations on the Object Set Descriptor has immediate effect
+on the database - every add, create and remove is immediately and
+automatically saved to the database.
 
-Changing objects
-================
+Relationships and queries
+=========================
 
-Once you've retrieved an object from the database using any of the above
-options, changing it is extremely easy.  Make changes directly to the
-objects fields, then call the object's ``save()`` method::
+When composing a ``filter`` or ``exclude`` refinement, it may be necessary to
+include conditions that span relationships. Relations can be followed as deep
+as required - just add descriptor names, separated by double underscores, to
+describe the full path to the query attribute. The query::
 
-    &gt;&gt;&gt; p = polls.get_object(id__exact=15)
-    &gt;&gt;&gt; p.slug = &quot;new_slug&quot;
-    &gt;&gt;&gt; p.pub_date = datetime.datetime.now()
-    &gt;&gt;&gt; p.save()
+    Foo.objects.filter(name1__name2__name3__attribute__lookup=value)
 
-Creating new objects
-====================
+... is interpreted as 'get every Foo that has a name1 that has a name2 that
+has a name3 that has an attribute with lookup matching value'. In the Poll
+example::
 
-Creating new objects (i.e. ``INSERT``) is done by creating new instances
-of objects then calling save() on them::
+    Choice.objects.filter(poll__slug__startswith=&quot;eggs&quot;)
 
-    &gt;&gt;&gt; p = polls.Poll(slug=&quot;eggs&quot;,
-    ...                question=&quot;How do you like your eggs?&quot;,
-    ...                pub_date=datetime.datetime.now(),
-    ...                expire_date=some_future_date)
-    &gt;&gt;&gt; p.save()
+... describes the set of choices for which the related poll has a slug
+attribute that starts with &quot;eggs&quot;. Django automatically composes the joins
+and conditions required for the SQL query.
 
-Calling ``save()`` on an object with a primary key whose value is ``None``
-signifies to Django that the object is new and should be inserted.
+Creating new related objects
+============================
 
-Related objects (e.g. ``Choices``) are created using convenience functions::
+Related objects are created using the ``create()`` convenience function on
+the descriptor Manager for relation::
 
-    &gt;&gt;&gt; p.add_choice(choice=&quot;Over easy&quot;, votes=0)
-    &gt;&gt;&gt; p.add_choice(choice=&quot;Scrambled&quot;, votes=0)
-    &gt;&gt;&gt; p.add_choice(choice=&quot;Fertilized&quot;, votes=0)
-    &gt;&gt;&gt; p.add_choice(choice=&quot;Poached&quot;, votes=0)
-    &gt;&gt;&gt; p.get_choice_count()
+    &gt;&gt;&gt; p.choice_set.create(choice=&quot;Over easy&quot;, votes=0)
+    &gt;&gt;&gt; p.choice_set.create(choice=&quot;Scrambled&quot;, votes=0)
+    &gt;&gt;&gt; p.choice_set.create(choice=&quot;Fertilized&quot;, votes=0)
+    &gt;&gt;&gt; p.choice_set.create(choice=&quot;Poached&quot;, votes=0)
+    &gt;&gt;&gt; p.choice_set.count()
     4
 
-Each of those ``add_choice`` methods is equivalent to (but much simpler than)::
+Each of those ``create()`` methods is equivalent to (but much simpler than)::
 
-    &gt;&gt;&gt; c = polls.Choice(poll_id=p.id, choice=&quot;Over easy&quot;, votes=0)
+    &gt;&gt;&gt; c = Choice(poll_id=p.id, choice=&quot;Over easy&quot;, votes=0)
     &gt;&gt;&gt; c.save()
 
-Note that when using the `add_foo()`` methods, you do not give any value
+Note that when using the `create()`` method, you do not give any value
 for the ``id`` field, nor do you give a value for the field that stores
 the relation (``poll_id`` in this case).
 
-The ``add_FOO()`` method always returns the newly created object.
+The ``create()`` method always returns the newly created object.
 
 Deleting objects
 ================
@@ -514,31 +1371,27 @@ deletes the object and has no return value. Example::
 
     &gt;&gt;&gt; c.delete()
 
-Comparing objects
-=================
+Objects can also be deleted in bulk. Every Query Set has a ``delete()`` method
+that will delete all members of the query set. For example::
 
-To compare two model objects, just use the standard Python comparison operator,
-the double equals sign: ``==``. Behind the scenes, that compares the primary
-key values of two models.
+    &gt;&gt;&gt; Polls.objects.filter(pub_date__year=2005).delete()
 
-Using the ``Poll`` example above, the following two statements are equivalent::
+would bulk delete all Polls with a year of 2005. Note that ``delete()`` is the
+only Query Set method that is not exposed on the Manager itself.
 
-    some_poll == other_poll
-    some_poll.id == other_poll.id
+This is a safety mechanism to prevent you from accidentally requesting
+``Polls.objects.delete()``, and deleting *all* the polls.
 
-If a model's primary key isn't called ID, no problem. Comparisons will always
-use the primary key, whatever it's called. For example, if a model's primary
-key field is called ``name``, these two statements are equivalent::
+If you *actually* want to delete all the objects, then you have to explicitly
+request a complete query set::
 
-    some_obj == other_obj
-    some_obj.name == other_obj.name
+    Polls.objects.all().delete()
 
 Extra instance methods
 ======================
 
-In addition to ``save()``, ``delete()`` and all of the ``add_*`` and ``get_*``
-related-object methods, a model object might get any or all of the following
-methods:
+In addition to ``save()``, ``delete()``, a model object might get any or all
+of the following methods:
 
 get_FOO_display()
 -----------------
@@ -572,10 +1425,10 @@ For every ``DateField`` and ``DateTimeField`` that does not have ``null=True``,
 the object will have ``get_next_by_FOO()`` and ``get_previous_by_FOO()``
 methods, where ``FOO`` is the name of the field. This returns the next and
 previous object with respect to the date field, raising the appropriate
-``*DoesNotExist`` exception when appropriate.
+``DoesNotExist`` exception when appropriate.
 
 Both methods accept optional keyword arguments, which should be in the format
-described in &quot;Field lookups&quot; above.
+described in _`Field lookups` above.
 
 Note that in the case of identical date values, these methods will use the ID
 as a fallback check. This guarantees that no records are skipped or duplicated.
@@ -604,14 +1457,14 @@ returns an empty string.
 get_FOO_size()
 --------------
 
-For every ``FileField``, the object will have a ``get_FOO_size()`` method,
+For every ``FileField``, the object will have a ``get_FOO_filename()`` method,
 where ``FOO`` is the name of the field. This returns the size of the file, in
 bytes. (Behind the scenes, it uses ``os.path.getsize``.)
 
 save_FOO_file(filename, raw_contents)
 -------------------------------------
 
-For every ``FileField``, the object will have a ``save_FOO_file()`` method,
+For every ``FileField``, the object will have a ``get_FOO_filename()`` method,
 where ``FOO`` is the name of the field. This saves the given file to the
 filesystem, using the given filename. If a file with the given filename already
 exists, Django adds an underscore to the end of the filename (but before the
@@ -623,48 +1476,3 @@ get_FOO_height() and get_FOO_width()
 For every ``ImageField``, the object will have ``get_FOO_height()`` and
 ``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This
 returns the height (or width) of the image, as an integer, in pixels.
-
-Extra module functions
-======================
-
-In addition to every function described in &quot;Basic lookup functions&quot; above, a
-model module might get any or all of the following methods:
-
-get_FOO_list(kind, \**kwargs)
------------------------------
-
-For every ``DateField`` and ``DateTimeField``, the model module will have a
-``get_FOO_list()`` function, where ``FOO`` is the name of the field. This
-returns a list of ``datetime.datetime`` objects representing all available
-dates of the given scope, as defined by the ``kind`` argument. ``kind`` should
-be either ``&quot;year&quot;``, ``&quot;month&quot;`` or ``&quot;day&quot;``. Each ``datetime.datetime``
-object in the result list is &quot;truncated&quot; to the given ``type``.
-
-    * ``&quot;year&quot;`` returns a list of all distinct year values for the field.
-    * ``&quot;month&quot;`` returns a list of all distinct year/month values for the field.
-    * ``&quot;day&quot;`` returns a list of all distinct year/month/day values for the field.
-
-Additional, optional keyword arguments, in the format described in
-&quot;Field lookups&quot; above, are also accepted.
-
-Here's an example, using the ``Poll`` model defined above::
-
-    &gt;&gt;&gt; from datetime import datetime
-    &gt;&gt;&gt; p1 = polls.Poll(slug='whatsup', question=&quot;What's up?&quot;,
-    ...     pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20))
-    &gt;&gt;&gt; p1.save()
-    &gt;&gt;&gt; p2 = polls.Poll(slug='name', question=&quot;What's your name?&quot;,
-    ...     pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20))
-    &gt;&gt;&gt; p2.save()
-    &gt;&gt;&gt; polls.get_pub_date_list('year')
-    [datetime.datetime(2005, 1, 1)]
-    &gt;&gt;&gt; polls.get_pub_date_list('month')
-    [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]
-    &gt;&gt;&gt; polls.get_pub_date_list('day')
-    [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]
-    &gt;&gt;&gt; polls.get_pub_date_list('day', question__contains='name')
-    [datetime.datetime(2005, 3, 20)]
-
-``get_FOO_list()`` also accepts an optional keyword argument ``order``, which
-should be either ``&quot;ASC&quot;`` or ``&quot;DESC&quot;``. This specifies how to order the
-results. Default is ``&quot;ASC&quot;``.</diff>
      <filename>docs/db-api.txt</filename>
    </modified>
    <modified>
      <diff>@@ -20,6 +20,9 @@ For example, the template system knows nothing about Web requests, the database
 layer knows nothing about data display and the view system doesn't care which
 template system a programmer uses.
 
+Although Django comes with a full stack for convenience, the pieces of the
+stack are independent of another wherever possible.
+
 .. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion
 
 Less code
@@ -49,7 +52,10 @@ Explicit is better than implicit
 --------------------------------
 
 This, a `core Python principle`_, means Django shouldn't do too much &quot;magic.&quot;
-Magic shouldn't happen unless there's a really good reason for it.
+Magic shouldn't happen unless there's a really good reason for it. Magic is
+worth using only if it creates a huge convenience unattainable in other ways,
+and it isn't implemented in a way that confuses developers who are trying to
+learn how to use the feature.
 
 .. _`core Python principle`: http://www.python.org/doc/Humor.html#zen
 
@@ -96,8 +102,9 @@ optimize statements internally.
 This is why developers need to call ``save()`` explicitly, rather than the
 framework saving things behind the scenes silently.
 
-This is also why the ``select_related`` argument exists. It's an optional
-performance booster for the common case of selecting &quot;every related object.&quot;
+This is also why the ``select_related()`` ``QuerySet`` method exists. It's an
+optional performance booster for the common case of selecting &quot;every related
+object.&quot;
 
 Terse, powerful syntax
 ----------------------
@@ -144,6 +151,8 @@ design pretty URLs than ugly ones.
 
 File extensions in Web-page URLs should be avoided.
 
+Vignette-style commas in URLs deserve severe punishment.
+
 Definitive URLs
 ---------------
 
@@ -186,6 +195,13 @@ The template system shouldn't be designed so that it only outputs HTML. It
 should be equally good at generating other text-based formats, or just plain
 text.
 
+XML should not be used for template languages
+---------------------------------------------
+
+Using an XML engine to parse templates introduces a whole new world of human
+error in editing templates -- and incurs an unacceptable level of overhead in
+template processing.
+
 Assume designer competence
 --------------------------
 </diff>
      <filename>docs/design_philosophies.txt</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,10 @@
-===========================
-The django-admin.py utility
-===========================
+=============================
+django-admin.py and manage.py
+=============================
 
 ``django-admin.py`` is Django's command-line utility for administrative tasks.
 This document outlines all it can do.
 
-The ``django-admin.py`` script should be on your system path if you installed
-Django via its ``setup.py`` utility. If it's not on your path, you can find it in
-``site-packages/django/bin`` within your Python installation. Consider
-symlinking to it from some place on your path, such as ``/usr/local/bin``.
-
 In addition, ``manage.py`` is automatically created in each Django project.
 ``manage.py`` is a thin wrapper around ``django-admin.py`` that takes care of
 two things for you before delegating to ``django-admin.py``:
@@ -19,6 +14,11 @@ two things for you before delegating to ``django-admin.py``:
     * It sets the ``DJANGO_SETTINGS_MODULE`` environment variable so that it
       points to your project's ``settings.py`` file.
 
+The ``django-admin.py`` script should be on your system path if you installed
+Django via its ``setup.py`` utility. If it's not on your path, you can find it in
+``site-packages/django/bin`` within your Python installation. Consider
+symlinking to it from some place on your path, such as ``/usr/local/bin``.
+
 Generally, when working on a single Django project, it's easier to use
 ``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the
 ``--settings`` command line option, if you need to switch between multiple
@@ -38,18 +38,17 @@ document.
 Run ``django-admin.py --help`` to display a help message that includes a terse
 list of all available actions and options.
 
-Most actions take a list of &quot;modelmodule&quot;s. A &quot;modelmodule,&quot; in this case, is
-the name of a file containing Django models. For example, if you have a model
-module called ``myproject/apps/polls/pollmodels.py``, the &quot;modelmodule&quot; in this
-case would be ``&quot;pollmodels&quot;``.
+Most actions take a list of ``appname``s. An ``appname`` is the basename of the
+package containing your models. For example, if your ``INSTALLED_APPS``
+contains the string ``'mysite.blog'``, the ``appname`` is ``blog``.
 
 Available actions
 =================
 
-adminindex [modelmodule modelmodule ...]
-----------------------------------------
+adminindex [appname appname ...]
+--------------------------------
 
-Prints the admin-index template snippet for the given model module(s).
+Prints the admin-index template snippet for the given appnames.
 
 Use admin-index template snippets if you want to customize the look and feel of
 your admin's index page. See `Tutorial 2`_ for more information.
@@ -64,29 +63,41 @@ backend.  See the `cache documentation`_ for more information.
 
 .. _cache documentation: http://www.djangoproject.com/documentation/cache/
 
-createsuperuser
----------------
+dbshell
+-------
 
-Creates a superuser account interactively. It asks you for a username, e-mail
-address and password.
+Runs the command-line client for the database engine specified in your
+``DATABASE_ENGINE`` setting, with the connection parameters specified in your
+``DATABASE_USER``, ``DATABASE_PASSWORD``, etc., settings.
 
-You can specify ``username email password`` on the command line, for convenient
-use in shell scripts. Example::
+    * For PostgreSQL, this runs the ``psql`` command-line client.
+    * For MySQL, this runs the ``mysql`` command-line client.
+    * For SQLite, this runs the ``sqlite3`` command-line client.
 
-    django-admin.py createsuperuser john john@example.com mypassword
+This command assumes the programs are on your ``PATH`` so that a simple call to
+the program name (``psql``, ``mysql``, ``sqlite3``) will find the program in
+the right place. There's no way to specify the location of the program
+manually.
 
-init
-----
+diffsettings
+------------
 
-Initializes the database with the tables and data Django needs by default.
-Specifically, these are the database tables from the ``auth`` and ``core``
-models.
+Displays differences between the current settings file and Django's default
+settings.
 
-inspectdb [dbname]
-------------------
+Settings that don't appear in the defaults are followed by ``&quot;###&quot;``. For
+example, the default settings don't define ``ROOT_URLCONF``, so
+``ROOT_URLCONF`` is followed by ``&quot;###&quot;`` in the output of ``diffsettings``.
 
-Introspects the database tables in the given database and outputs a Django
-model module to standard output.
+Note that Django's default settings live in ``django/conf/global_settings.py``,
+if you're ever curious to see the full list of defaults.
+
+inspectdb
+---------
+
+Introspects the database tables in the database pointed-to by the
+``DATABASE_NAME`` setting and outputs a Django model module (a ``models.py``
+file) to standard output.
 
 Use this if you have a legacy database with which you'd like to use Django.
 The script will inspect the database and create a model for each table within
@@ -101,12 +112,12 @@ output:
       ``'This field type is a guess.'`` next to the field in the generated
       model.
 
-    * **New in Django development version.** If the database column name is a
-      Python reserved word (such as ``'pass'``, ``'class'`` or ``'for'``),
-      ``inspectdb`` will append ``'_field'`` to the attribute name. For
-      example, if a table has a column ``'for'``, the generated model will have
-      a field ``'for_field'``, with the ``db_column`` attribute set to
-      ``'for'``. ``inspectdb`` will insert the Python comment
+    * If the database column name is a Python reserved word (such as
+      ``'pass'``, ``'class'`` or ``'for'``), ``inspectdb`` will append
+      ``'_field'`` to the attribute name. For example, if a table has a column
+      ``'for'``, the generated model will have a field ``'for_field'``, with
+      the ``db_column`` attribute set to ``'for'``. ``inspectdb`` will insert
+      the Python comment
       ``'Field renamed because it was a Python reserved word.'`` next to the
       field.
 
@@ -115,25 +126,16 @@ you run it, you'll want to look over the generated models yourself to make
 customizations. In particular, you'll need to rearrange models' order, so that
 models that refer to other models are ordered properly.
 
-If you're using Django 0.90 or 0.91, you'll need to add ``primary_key=True`` to
-one field in each model. In the Django development version, primary keys are
-automatically introspected for PostgreSQL and MySQL, and Django puts in the
-``primary_key=True`` where needed.
+Primary keys are automatically introspected for PostgreSQL and MySQL, in which
+case Django puts in the ``primary_key=True`` where needed.
 
 ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
-only works in PostgreSQL.
-
-install [modelmodule modelmodule ...]
--------------------------------------
-
-Executes the equivalent of ``sqlall`` for the given model module(s).
+only works in PostgreSQL and with certain types of MySQL tables.
 
-installperms [modelmodule modelmodule ...]
-------------------------------------------
+install [appname appname ...]
+-----------------------------
 
-Installs any admin permissions for the given model module(s) that aren't
-already installed in the database. Outputs a message telling how many
-permissions were added, if any.
+Executes the equivalent of ``sqlall`` for the given appnames.
 
 runserver [optional port number, or ipaddr:port]
 ------------------------------------------------
@@ -144,7 +146,7 @@ IP address and port number explicitly.
 
 If you run this script as a user with normal privileges (recommended), you
 might not have access to start a port on a low port number. Low port numbers
-are reserved for superusers (root).
+are reserved for the superuser (root).
 
 DO NOT USE THIS SERVER IN A PRODUCTION SETTING.
 
@@ -153,7 +155,7 @@ needed. You don't need to restart the server for code changes to take effect.
 
 When you start the server, and each time you change Python code while the
 server is running, the server will validate all of your installed models. (See
-the &quot;validate&quot; option below.) If the validator finds errors, it will print
+the ``validate`` command below.) If the validator finds errors, it will print
 them to standard output, but it won't stop the server.
 
 You can run as many servers as you want, as long as they're on separate ports.
@@ -180,49 +182,49 @@ shell
 
 Starts the Python interactive interpreter.
 
-**New in Django development version:** Uses IPython_, if it's installed. If you
-have IPython installed and want to force use of the &quot;plain&quot; Python interpreter,
-use the ``--plain`` option, like so::
+Django will use IPython_, if it's installed. If you have IPython installed and
+want to force use of the &quot;plain&quot; Python interpreter, use the ``--plain``
+option, like so::
 
     django-admin.py shell --plain
 
 .. _IPython: http://ipython.scipy.org/
 
-sql [modelmodule modelmodule ...]
----------------------------------
+sql [appname appname ...]
+-------------------------
 
-Prints the CREATE TABLE SQL statements for the given model module(s).
+Prints the CREATE TABLE SQL statements for the given appnames.
 
-sqlall [modelmodule modelmodule ...]
-------------------------------------
+sqlall [appname appname ...]
+----------------------------
 
-Prints the CREATE TABLE and initial-data SQL statements for the given model module(s).
+Prints the CREATE TABLE and initial-data SQL statements for the given appnames.
 
-sqlclear [modelmodule modelmodule ...]
+sqlclear [appname appname ...]
 --------------------------------------
 
-Prints the DROP TABLE SQL statements for the given model module(s).
+Prints the DROP TABLE SQL statements for the given appnames.
 
-sqlindexes [modelmodule modelmodule ...]
+sqlindexes [appname appname ...]
 ----------------------------------------
 
-Prints the CREATE INDEX SQL statements for the given model module(s).
+Prints the CREATE INDEX SQL statements for the given appnames.
 
-sqlinitialdata [modelmodule modelmodule ...]
+sqlinitialdata [appname appname ...]
 --------------------------------------------
 
-Prints the initial INSERT SQL statements for the given model module(s).
+Prints the initial INSERT SQL statements for the given appnames.
 
-sqlreset [modelmodule modelmodule ...]
+sqlreset [appname appname ...]
 --------------------------------------
 
-Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given model module(s).
+Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.
 
-sqlsequencereset [modelmodule modelmodule ...]
+sqlsequencereset [appname appname ...]
 ----------------------------------------------
 
 Prints the SQL statements for resetting PostgreSQL sequences for the given
-model module(s).
+appnames.
 
 See http://simon.incutio.com/archive/2004/04/21/postgres for more information.
 
@@ -252,11 +254,12 @@ Available options
 
 Example usage::
 
-    django-admin.py init --settings=myproject.settings
+    django-admin.py syncdb --settings=mysite.settings
 
 Explicitly specifies the settings module to use. The settings module should be
-in Python path syntax, e.g. &quot;myproject.settings&quot;. If this isn't provided,
-``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable.
+in Python package syntax, e.g. ``mysite.settings``. If this isn't provided,
+``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment
+variable.
 
 Note that this option is unnecessary in ``manage.py``, because it takes care of
 setting ``DJANGO_SETTINGS_MODULE`` for you.
@@ -266,7 +269,7 @@ setting ``DJANGO_SETTINGS_MODULE`` for you.
 
 Example usage::
 
-    django-admin.py init --pythonpath='/home/djangoprojects/myproject'
+    django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject'
 
 Adds the given filesystem path to the Python `import search path`_. If this
 isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment
@@ -282,3 +285,27 @@ setting the Python path for you.
 
 Displays a help message that includes a terse list of all available actions and
 options.
+
+Extra niceties
+==============
+
+Syntax coloring
+---------------
+
+The ``django-admin.py`` / ``manage.py`` commands that output SQL to standard
+output will use pretty color-coded output if your terminal supports
+ANSI-colored output. It won't use the color codes if you're piping the
+command's output to another program.
+
+Bash completion
+---------------
+
+If you use the Bash shell, consider installing the Django bash completion
+script, which lives in ``extras/django_bash_completion`` in the Django
+distribution. It enables tab-completion of ``django-admin.py`` and
+``manage.py`` commands, so you can, for instance...
+
+    * Type ``django-admin.py``.
+    * Press [TAB] to see all available options.
+    * Type ``sql``, then [TAB], to see all available options whose names start
+      with ``sql``.</diff>
      <filename>docs/django-admin.txt</filename>
    </modified>
    <modified>
      <diff>@@ -20,11 +20,11 @@ In two lines::
     send_mail('Subject here', 'Here is the message.', 'from@example.com',
         ['to@example.com'], fail_silently=False)
 
-The send_mail function
-======================
+send_mail()
+===========
 
 The simplest way to send e-mail is using the function
-``django.core.mail.send_mail``. Here's its definition::
+``django.core.mail.send_mail()``. Here's its definition::
 
     send_mail(subject, message, from_email, recipient_list,
         fail_silently=False, auth_user=EMAIL_HOST_USER,
@@ -42,20 +42,19 @@ are required.
     * ``fail_silently``: A boolean. If it's ``False``, ``send_mail`` will raise
       an ``smtplib.SMTPException``. See the `smtplib docs`_ for a list of
       possible exceptions, all of which are subclasses of ``SMTPException``.
-    * ``auth_user``: **New in Django development version.** The optional
-      username to use to authenticate to the SMTP server. If this isn't
-      provided, Django will use the value of the ``EMAIL_HOST_USER`` setting.
-    * ``auth_password``: **New in Django development version.** The optional
-      password to use to authenticate to the SMTP server. If this isn't
-      provided, Django will use the value of the ``EMAIL_HOST_PASSWORD``
-      setting.
+    * ``auth_user``: The optional username to use to authenticate to the SMTP
+      server. If this isn't provided, Django will use the value of the
+      ``EMAIL_HOST_USER`` setting.
+    * ``auth_password``: The optional password to use to authenticate to the
+      SMTP server. If this isn't provided, Django will use the value of the
+      ``EMAIL_HOST_PASSWORD`` setting.
 
 .. _smtplib docs: http://www.python.org/doc/current/lib/module-smtplib.html
 
-The send_mass_mail function
-===========================
+send_mass_mail()
+================
 
-``django.core.mail.send_mass_mail`` is intended to handle mass e-mailing.
+``django.core.mail.send_mass_mail()`` is intended to handle mass e-mailing.
 Here's the definition::
 
     send_mass_mail(datatuple, fail_silently=False,
@@ -66,25 +65,24 @@ Here's the definition::
     (subject, message, from_email, recipient_list)
 
 ``fail_silently``, ``auth_user`` and ``auth_password`` have the same functions
-as in ``send_mail()``. Note that ``auth_user`` and ``auth_password`` are only
-available in the Django development version.
+as in ``send_mail()``.
 
 Each separate element of ``datatuple`` results in a separate e-mail message.
 As in ``send_mail()``, recipients in the same ``recipient_list`` will all see
 the other addresses in the e-mail messages's &quot;To:&quot; field.
 
-send_mass_mail vs. send_mail
-----------------------------
+send_mass_mail() vs. send_mail()
+--------------------------------
 
 The main difference between ``send_mass_mail()`` and ``send_mail()`` is that
 ``send_mail()`` opens a connection to the mail server each time it's executed,
 while ``send_mass_mail()`` uses a single connection for all of its messages.
 This makes ``send_mass_mail()`` slightly more efficient.
 
-The mail_admins function
-========================
+mail_admins()
+=============
 
-``django.core.mail.mail_admins`` is a shortcut for sending an e-mail to the
+``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the
 site admins, as defined in the `ADMINS setting`_. Here's the definition::
 
     mail_admins(subject, message, fail_silently=False)
@@ -94,14 +92,16 @@ site admins, as defined in the `ADMINS setting`_. Here's the definition::
 
 The &quot;From:&quot; header of the e-mail will be the value of the `SERVER_EMAIL setting`_.
 
+This method exists for convenience and readability.
+
 .. _ADMINS setting: http://www.djangoproject.com/documentation/settings/#admins
 .. _EMAIL_SUBJECT_PREFIX setting: http://www.djangoproject.com/documentation/settings/#email-subject-prefix
 .. _SERVER_EMAIL setting: http://www.djangoproject.com/documentation/settings/#server-email
 
-The mail_managers function
-==========================
+mail_managers() function
+========================
 
-``django.core.mail.mail_managers`` is just like ``mail_admins``, except it
+``django.core.mail.mail_managers()`` is just like ``mail_admins()``, except it
 sends an e-mail to the site managers, as defined in the `MANAGERS setting`_.
 Here's the definition::
 </diff>
      <filename>docs/email.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,14 +8,20 @@ General questions
 Why does this project exist?
 ----------------------------
 
-Django grew from a very practical need: in our fast-paced newsroom, we often
-have only a matter of hours to take a complicated Web application from
-concept to public launch.  Django was designed to not only allow us to
-build Web applications quickly, but to allow us to build them right.
+Django grew from a very practical need: World Online, a newspaper Web
+operation, is responsible for building intensive Web applications on journalism
+deadlines. In the fast-paced newsroom, World Online often has only a matter of
+hours to take a complicated Web application from concept to public launch.
+
+At the same time, the World Online Web developers have consistently been
+perfectionists when it comes to following best practices of Web development.
+
+Thus, Django was designed not only to allow fast Web development, but
+*best-practice* Web development.
 
 Django would not be possible without a whole host of open-source projects --
-`Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're thrilled to be
-able to give something back to the open-source community.
+`Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're thrilled to
+be able to give something back to the open-source community.
 
 .. _Apache: http://httpd.apache.org/
 .. _Python: http://www.python.org/
@@ -29,25 +35,28 @@ to early 1950s. To this day, he's considered one of the best guitarists of all t
 
 Listen to his music. You'll like it.
 
-According to Wikipedia_, &quot;Django is pronounced **zhane**-go (with a long 'a').&quot;
+Django is pronounced **JANG**-oh. Rhymes with FANG-oh.
 
 .. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt
-.. _Wikipedia: http://en.wikipedia.org/wiki/Django_Reinhardt
 
 Is Django stable?
 -----------------
 
-We've been using Django for almost two years. Sites built on Django have
-weathered traffic spikes of over one million hits an hour, and at least
-one Slashdotting. Yes, it's quite stable.
+Yes. World Online has been using Django for more than two years. Sites built on
+Django have weathered traffic spikes of over one million hits an hour and at
+least one Slashdotting. Yes, it's quite stable.
 
 Does Django scale?
 ------------------
 
 Yes. Compared to development time, hardware is cheap, and so Django is
 designed to take advantage of as much hardware as you can throw at it.
-Django ships with clean separation of the database layer from the
-application layer and a simple-yet-powerful `cache framework`_.
+
+Django uses a &quot;shared-nothing&quot; architecture, which means you can add hardware
+at any level -- database servers, caching servers or Web/application servers.
+
+The framework cleanly separates components such as its database layer and
+application layer. And it ships with a simple-yet-powerful `cache framework`_.
 
 .. _`cache framework`: http://www.djangoproject.com/documentation/cache/
 
@@ -60,32 +69,34 @@ Lawrence, Kansas, USA.
 `Adrian Holovaty`_
     Adrian is a Web developer with a background in journalism. He was lead
     developer at World Online for 2.5 years, during which time Django was
-    developed and implemented on World Online's sites. Now he's editor of
-    editorial innovations at washingtonpost.com, and he continues to oversee
-    Django development. He likes playing guitar (Django Reinhardt style) and
-    hacking on side projects such as `chicagocrime.org`_. He lives in Chicago.
+    developed and implemented on World Online's sites. Now he works for
+    washingtonpost.com building rich, database-backed information sites, and
+    continues to oversee Django development. He likes playing guitar (Django
+    Reinhardt style) and hacking on side projects such as `chicagocrime.org`_.
+    He lives in Chicago.
 
     On IRC, Adrian goes by ``adrian_h``.
 
+`Jacob Kaplan-Moss`_
+    Jacob is a whipper-snapper from California who spends equal time coding and
+    cooking. He's lead developer at World Online and actively hacks on various
+    cool side projects. He's contributed to the Python-ObjC bindings and was
+    the first guy to figure out how to write Tivo apps in Python. Lately he's
+    been messing with Python on the PSP. He lives in Lawrence, Kansas.
+
+    On IRC, Jacob goes by ``jacobkm``.
+
 `Simon Willison`_
     Simon is a well-respected Web developer from England. He had a one-year
     internship at World Online, during which time he and Adrian developed
-    Django from scratch. He's enthusiastic, he's passionate about best
-    practices in Web development, and he really likes squirrels. Probably to a
-    fault. He went back to university to finish his degree and is poised to
-    continue doing big, exciting things on the Web. He lives in England.
+    Django from scratch. The most enthusiastic Brit you'll ever meet, he's
+    passionate about best practices in Web development and has maintained a
+    well-read Web-development blog for years at http://simon.incutio.com.
+    He works for Yahoo UK, where he managed to score the title &quot;Hacker Liason.&quot;
+    He lives in London.
 
     On IRC, Simon goes by ``SimonW``.
 
-`Jacob Kaplan-Moss`_
-    Jacob is a whipper-snapper from California who spends equal time coding and
-    cooking. He does Web development for World Online and actively hacks on
-    various cool side projects. He's contributed to the Python-ObjC bindings and
-    was the first guy to figure out how to write Tivo apps in Python. Lately
-    he's been messing with Python on the PSP. He lives in Lawrence, Kansas.
-
-    On IRC, Jacob goes by ``jacobkm``.
-
 `Wilson Miner`_
     Wilson's design-fu makes us all look like rock stars. When not sneaking
     into apartment complex swimming pools, he's the Commercial Development
@@ -106,18 +117,17 @@ Lawrence, Kansas, USA.
 Which sites use Django?
 -----------------------
 
-The Django wiki features a `list of Django-powered sites`_. Feel free to add
-your Django-powered site to the list.
+The Django wiki features a consistently growing `list of Django-powered sites`_.
+Feel free to add your Django-powered site to the list.
 
 .. _list of Django-powered sites: http://code.djangoproject.com/wiki/DjangoPoweredSites
 
 Django appears to be a MVC framework, but you call the Controller the &quot;view&quot;, and the View the &quot;template&quot;. How come you don't use the standard names?
 -----------------------------------------------------------------------------------------------------------------------------------------------------
 
-That's because Django isn't strictly a MVC framework. We don't really believe in
-any capital-M Methodologies; we do what &quot;feels&quot; right. If you squint the right
-way, you can call Django's ORM the &quot;Model&quot;, the view functions the &quot;View&quot;, and
-the dynamically-generated API the &quot;Controller&quot; -- but not really.
+That's because Django isn't strictly a MVC framework. If you squint the right
+way, you can call Django's database layer the &quot;Model&quot;, the view functions the
+&quot;View&quot;, and the URL dispatcher the &quot;Controller&quot; -- but not really.
 
 In fact, you might say that Django is a &quot;MTV&quot; framework -- that is, Model,
 Template, and View make much more sense to us.
@@ -183,9 +193,13 @@ begin maintaining backwards compatibility. This should happen in a couple of
 months or so, although it's entirely possible that it could happen earlier.
 That translates into summer 2006.
 
+The merging of Django's `magic-removal branch`_ went a long way toward Django
+1.0.
+
 Of course, you should note that `quite a few production sites`_ use Django in
 its current status. Don't let the lack of a 1.0 turn you off.
 
+.. _magic-removal branch: http://code.djangoproject.com/wiki/RemovingTheMagic
 .. _quite a few production sites: http://code.djangoproject.com/wiki/DjangoPoweredSites
 
 How can I download the Django documentation to read it offline?
@@ -225,12 +239,12 @@ How do I get started?
 How do I fix the &quot;install a later version of setuptools&quot; error?
 ---------------------------------------------------------------
 
-Just run the ``ex_setup.py`` script in the Django distribution.
+Just run the ``ez_setup.py`` script in the Django distribution.
 
 What are Django's prerequisites?
 --------------------------------
 
-Django requires Python_ 2.3 or later.
+Django requires Python_ 2.3 or later. No other Python libraries are required.
 
 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
@@ -256,7 +270,7 @@ Not if you just want to play around and develop things on your local computer.
 Django comes with its own Web server, and things should Just Work.
 
 For production use, though, we recommend mod_python. The Django developers have
-been running it on mod_python for about two years, and it's quite stable.
+been running it on mod_python for more than two years, and it's quite stable.
 
 However, if you don't want to use mod_python, you can use a different server,
 as long as that server has WSGI_ hooks. See the `server arrangements wiki page`_.
@@ -325,6 +339,14 @@ but we recognize that choosing a template language runs close to religion.
 There's nothing about Django that requires using the template language, so
 if you're attached to ZPT, Cheetah, or whatever, feel free to use those.
 
+Do I have to use your model/database layer?
+-------------------------------------------
+
+Nope. Just like the template system, the model/database layer is decoupled from
+the rest of the framework. The one exception is: If you use a different
+database library, you won't get to use Django's automatically-generated admin
+site. That app is coupled to the Django database layer.
+
 How do I use image and file fields?
 -----------------------------------
 
@@ -367,9 +389,8 @@ input.
 If you do care about deleting data, you'll have to execute the ``ALTER TABLE``
 statements manually in your database. That's the way we've always done it,
 because dealing with data is a very sensitive operation that we've wanted to
-avoid automating. That said, there's some work being done to add a
-``django-admin.py updatedb`` command, which would output the necessary
-``ALTER TABLE`` statements, if any.
+avoid automating. That said, there's some work being done to add partially
+automated database-upgrade functionality.
 
 Do Django models support multiple-column primary keys?
 ------------------------------------------------------
@@ -392,19 +413,19 @@ How can I see the raw SQL queries Django is running?
 Make sure your Django ``DEBUG`` setting is set to ``True``. Then, just do
 this::
 
-    &gt;&gt;&gt; from django.core.db import db
-    &gt;&gt;&gt; db.queries
+    &gt;&gt;&gt; from django.db import connection
+    &gt;&gt;&gt; connection.queries
     [{'sql': 'SELECT polls_polls.id,polls_polls.question,polls_polls.pub_date FROM polls_polls',
     'time': '0.002'}]
 
-``db.queries`` is only available if ``DEBUG`` is ``True``. It's a list of
-dictionaries in order of query execution. Each dictionary has the following::
+``connection.queries`` is only available if ``DEBUG`` is ``True``. It's a list
+of dictionaries in order of query execution. Each dictionary has the following::
 
     ``sql`` -- The raw SQL statement
     ``time`` -- How long the statement took to execute, in seconds.
 
-``db.queries`` includes all SQL statements -- INSERTs, UPDATES, SELECTs, etc.
-Each time your app hits the database, the query will be recorded.
+``connection.queries`` includes all SQL statements -- INSERTs, UPDATES,
+SELECTs, etc. Each time your app hits the database, the query will be recorded.
 
 Can I use Django with a pre-existing database?
 ----------------------------------------------
@@ -465,8 +486,8 @@ documentation.
 My &quot;list_filter&quot; contains a ManyToManyField, but the filter doesn't display.
 ----------------------------------------------------------------------------
 
-Django won't bother displaying the filter for a ManyToManyField if there are
-fewer than two related objects.
+Django won't bother displaying the filter for a ``ManyToManyField`` if there
+are fewer than two related objects.
 
 For example, if your ``list_filter`` includes ``sites``, and there's only one
 site in your database, it won't display a &quot;Site&quot; filter. In that case,
@@ -477,9 +498,9 @@ How can I customize the functionality of the admin interface?
 
 You've got several options. If you want to piggyback on top of an add/change
 form that Django automatically generates, you can attach arbitrary JavaScript
-modules to the page via the model's ``admin.js`` parameter. That parameter is
-a list of URLs, as strings, pointing to JavaScript modules that will be
-included within the admin form via a &lt;script&gt; tag.
+modules to the page via the model's ``class Admin`` ``js`` parameter. That
+parameter is a list of URLs, as strings, pointing to JavaScript modules that
+will be included within the admin form via a ``&lt;script&gt;`` tag.
 
 If you want more flexibility than simply tweaking the auto-generated forms,
 feel free to write custom views for the admin. The admin is powered by Django
@@ -492,10 +513,23 @@ next question.
 The dynamically-generated admin site is ugly! How can I change it?
 ------------------------------------------------------------------
 
-We think it's very purty, but if you don't agree, you can modify the admin
-site's presentation by editing the CSS stylesheet and/or associated image files.
-The site is built using semantic HTML, so any changes you'd like to make should
-be possible by editing the CSS stylesheet. We've got a `guide to the CSS used in
-the admin`_ to get you started.
+We like it, but if you don't agree, you can modify the admin site's
+presentation by editing the CSS stylesheet and/or associated image files. The
+site is built using semantic HTML and plenty of CSS hooks, so any changes you'd
+like to make should be possible by editing the stylesheet. We've got a
+`guide to the CSS used in the admin`_ to get you started.
 
 .. _`guide to the CSS used in the admin`: http://www.djangoproject.com/documentation/admin_css/
+
+How do I create users without having to edit password hashes?
+-------------------------------------------------------------
+
+We don't recommend you create users via the admin interface, because at the
+moment it requires you to edit password hashes manually. (Passwords are hashed
+using one-way hash algorithms for security; there's currently no Web interface
+for changing passwords by entering the actual password rather than the hash.)
+
+To create a user, you'll have to use the Python API. See `creating users`_ for
+full info.
+
+.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users</diff>
      <filename>docs/faq.txt</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,8 @@ The flatpages app
 =================
 
 Django comes with an optional &quot;flatpages&quot; application. It lets you store simple
-&quot;flat&quot; HTML content in a database and handles the management for you.
+&quot;flat&quot; HTML content in a database and handles the management for you via
+Django's admin interface and a Python API.
 
 A flatpage is a simple object with a URL, title and content. Use it for
 one-off, special-case pages, such as &quot;About&quot; or &quot;Privacy Policy&quot; pages, that
@@ -23,10 +24,10 @@ Installation
 
 To install the flatpages app, follow these steps:
 
-    1. Add ``&quot;django.contrib.flatpages&quot;`` to your INSTALLED_APPS_ setting.
-    2. Add ``&quot;django.contrib.flatpages.middleware.FlatpageFallbackMiddleware&quot;``
+    1. Add ``'django.contrib.flatpages'`` to your INSTALLED_APPS_ setting.
+    2. Add ``'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'``
        to your MIDDLEWARE_CLASSES_ setting.
-    3. Run the command ``django-admin.py install flatpages``.
+    3. Run the command ``manage.py syncdb``.
 
 .. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
 .. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
@@ -34,10 +35,10 @@ To install the flatpages app, follow these steps:
 How it works
 ============
 
-``django-admin.py install flatpages`` creates two tables in your database:
-``django_flatpages`` and ``django_flatpages_sites``. ``django_flatpages`` is a
-simple lookup table that essentially maps a URL to a title and bunch of text
-content. ``django_flatpages_sites`` associates a flatpage with a site.
+``manage.py syncdb`` creates two tables in your database: ``django_flatpage``
+and ``django_flatpage_sites``. ``django_flatpage`` is a simple lookup table
+that simply maps a URL to a title and bunch of text content.
+``django_flatpage_sites`` associates a flatpage with a site.
 
 The ``FlatpageFallbackMiddleware`` does all of the work. Each time any Django
 application raises a 404 error, this middleware checks the flatpages database
@@ -49,7 +50,7 @@ If it finds a match, it follows this algorithm:
     * If the flatpage has a custom template, it loads that template. Otherwise,
       it loads the template ``flatpages/default``.
     * It passes that template a single context variable, ``flatpage``, which is
-      the flatpage object. It uses DjangoContext_ in rendering the template.
+      the flatpage object. It uses RequestContext_ in rendering the template.
 
 If it doesn't find a match, the request continues to be processed as usual.
 
@@ -63,7 +64,7 @@ resort.
 For more on middleware, read the `middleware docs`_.
 
 .. _SITE_ID: http://www.djangoproject.com/documentation/settings/#site-id
-.. _DjangoContext: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
+.. _RequestContext: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
 .. _middleware docs: http://www.djangoproject.com/documentation/middleware/
 
 How to add, change and delete flatpages
@@ -80,8 +81,8 @@ Via the Python API
 ------------------
 
 Flatpages are represented by a standard `Django model`_, which lives in
-`django/contrib/flatpages/models/flatpages.py`_. You can access flatpage
-objects via the `Django database API`_.
+`django/contrib/flatpages/models.py`_. You can access flatpage objects via the
+`Django database API`_.
 
 .. _Django model: http://www.djangoproject.com/documentation/model_api/
 .. _django/contrib/flatpages/models/flatpages.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models/flatpages.py
@@ -90,17 +91,17 @@ objects via the `Django database API`_.
 Flatpage templates
 ==================
 
-By default, flatpages are rendered via the template ``flatpages/default``, but
-you can override that for a particular flatpage.
+By default, flatpages are rendered via the template ``flatpages/default.html``,
+but you can override that for a particular flatpage.
 
-Creating the ``flatpages/default`` template is your responsibility; in your
-template directory, just create a ``flatpages`` directory containing a file
-``default.html``.
+Creating the ``flatpages/default.html`` template is your responsibility; in
+your template directory, just create a ``flatpages`` directory containing a
+file ``default.html``.
 
 Flatpage templates are passed a single context variable, ``flatpage``, which is
 the flatpage object.
 
-Here's a sample ``flatpages/default`` template::
+Here's a sample ``flatpages/default.html`` template::
 
     &lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;
         &quot;http://www.w3.org/TR/REC-html40/loose.dtd&quot;&gt;</diff>
      <filename>docs/flatpages.txt</filename>
    </modified>
    <modified>
      <diff>@@ -9,10 +9,7 @@ code. It is, and this document explains how the framework works.
     .. admonition:: A note to the lazy
 
         If all you want to do is present forms for a user to create and/or
-        update a given object, don't read any further. Instead, click thyself
-        to the `generic views`_ documentation. The following exercises are
-        for those interested in how Django's form framework works and those
-        needing to do more than simple creation/updating.
+        update a given object, you may be able to use `generic views`_.
 
 We'll take a top-down approach to examining Django's form validation framework,
 because much of the time you won't need to use the lower-level APIs. Throughout
@@ -32,13 +29,14 @@ this document, we'll be working with the following model, a &quot;place&quot; object::
         state = meta.USStateField()
         zip_code = meta.CharField(maxlength=5, blank=True)
         place_type = meta.IntegerField(choices=PLACE_TYPES)
-        class META:
-            admin = meta.Admin()
 
-        def __repr__(self):
+        class Admin:
+            pass
+
+        def __str__(self):
             return self.name
 
-Defining the above class is enough to create an admin interface to a ``place``,
+Defining the above class is enough to create an admin interface to a ``Place``,
 but what if you want to allow public users to submit places?
 
 Manipulators
@@ -53,11 +51,11 @@ similar, but the former knows how to create new instances of the model, while
 the later modifies existing instances.  Both types of classes are automatically
 created when you define a new class::
 
-    &gt;&gt;&gt; from django.models.places import places
-    &gt;&gt;&gt; places.AddManipulator
-    &lt;class django.models.places.PlaceManipulatorAdd at 0x4c1540&gt;
-    &gt;&gt;&gt; places.ChangeManipulator
-    &lt;class django.models.places.PlaceManipulatorChange at 0x4c1630&gt;
+    &gt;&gt;&gt; from mysite.myapp.models import Place
+    &gt;&gt;&gt; Place.AddManipulator
+    &lt;class 'django.models.manipulators.AddManipulator'&gt;
+    &gt;&gt;&gt; Place.ChangeManipulator
+    &lt;class 'django.models.manipulators.ChangeManipulator'&gt;
 
 Using the ``AddManipulator``
 ----------------------------
@@ -65,16 +63,15 @@ Using the ``AddManipulator``
 We'll start with the ``AddManipulator``.  Here's a very simple view that takes
 POSTed data from the browser and creates a new ``Place`` object::
 
-    from django.core.exceptions import Http404
-    from django.core.extensions import render_to_response
-    from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
-    from django.models.places import places
-    from django.core import formfields
+    from django.shortcuts import render_to_response
+    from django.http import Http404, HttpResponse, HttpResponseRedirect
+    from django import forms
+    from mysite.myapp.models import Place
 
     def naive_create_place(request):
         &quot;&quot;&quot;A naive approach to creating places; don't actually use this!&quot;&quot;&quot;
         # Create the AddManipulator.
-        manipulator = places.AddManipulator()
+        manipulator = Place.AddManipulator()
 
         # Make a copy of the POSTed data so that do_html2python can
         # modify it in place (request.POST is immutable).
@@ -110,16 +107,17 @@ view with a form that submits to this flawed creation view::
         &quot;&quot;&quot;Simplistic place form view; don't actually use anything like this!&quot;&quot;&quot;
         # Create a FormWrapper object that the template can use. Ignore
         # the last two arguments to FormWrapper for now.
-        form = formfields.FormWrapper(places.AddManipulator(), {}, {})
-        return render_to_response('places/naive_create_form', {'form': form})
+        form = forms.FormWrapper(Place.AddManipulator(), {}, {})
+        return render_to_response('places/naive_create_form.html', {'form': form})
 
 (This view, as well as all the following ones, has the same imports as in the
 first example above.)
 
-The ``formfields.FormWrapper`` object is a wrapper that templates can
-easily deal with to create forms. Here's the ``naive_create_form`` template::
+The ``forms.FormWrapper`` object is a wrapper that templates can
+easily deal with to create forms. Here's the ``naive_create_form.html``
+template::
 
-    {% extends &quot;base&quot; %}
+    {% extends &quot;base.html&quot; %}
 
     {% block content %}
     &lt;h1&gt;Create a place:&lt;/h1&gt;
@@ -156,23 +154,23 @@ don't have any validation. Let's revise the validation issue by writing a new
 creation view that takes validation into account::
 
     def create_place_with_validation(request):
-        manipulator = places.AddManipulator()
+        manipulator = Place.AddManipulator()
         new_data = request.POST.copy()
 
         # Check for validation errors
         errors = manipulator.get_validation_errors(new_data)
         if errors:
-            return render_to_response('places/errors', {'errors': errors})
+            return render_to_response('places/errors.html', {'errors': errors})
         else:
-            manipulator.do_html2python(request.POST)
-            new_place = manipulator.save(request.POST)
+            manipulator.do_html2python(new_data)
+            new_place = manipulator.save(new_data)
             return HttpResponse(&quot;Place created: %s&quot; % new_place)
 
 In this new version, errors will be found -- ``manipulator.get_validation_errors``
 handles all the validation for you -- and those errors can be nicely presented
 on an error page (templated, of course)::
 
-    {% extends &quot;base&quot; %}
+    {% extends &quot;base.html&quot; %}
 
     {% block content %}
 
@@ -200,7 +198,7 @@ data is valid). An added bonus of this approach is that errors and the form will
 both be available on the same page, so errors with fields can be presented in
 context.
 
-.. admonition:: Philosophy::
+.. admonition:: Philosophy:
 
     Finally, for the HTTP purists in the audience (and the authorship), this
     nicely matches the &quot;true&quot; meanings of HTTP GET and HTTP POST: GET fetches
@@ -209,7 +207,7 @@ context.
 Below is the finished view::
 
     def create_place(request):
-        manipulator = places.AddManipulator()
+        manipulator = Place.AddManipulator()
 
         if request.POST:
             # If data was POSTed, we're trying to create a new Place.
@@ -233,18 +231,18 @@ Below is the finished view::
             errors = new_data = {}
 
         # Create the FormWrapper, template, context, response.
-        form = formfields.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('places/create_form', {'form': form})
+        form = forms.FormWrapper(manipulator, new_data, errors)
+        return render_to_response('places/create_form.html', {'form': form})
 
 and here's the ``create_form`` template::
 
-    {% extends &quot;base&quot; %}
+    {% extends &quot;base.html&quot; %}
 
     {% block content %}
     &lt;h1&gt;Create a place:&lt;/h1&gt;
 
     {% if form.has_errors %}
-    &lt;h2&gt;Please correct the following error{{ errors|pluralize }}:&lt;/h2&gt;
+    &lt;h2&gt;Please correct the following error{{ form.error_dict|pluralize }}:&lt;/h2&gt;
     {% endif %}
 
     &lt;form method=&quot;post&quot; action=&quot;.&quot;&gt;
@@ -289,7 +287,8 @@ The second argument is the error list retrieved from
 this gives each field an ``errors`` item (which is a list of error messages
 associated with the field) as well as a ``html_error_list`` item, which is a
 ``&lt;ul&gt;`` of error messages. The above template uses these error items to
-display a simple error message next to each field.
+display a simple error message next to each field. The error list is saved as
+an ``error_dict`` attribute of the ``FormWrapper`` object.
 
 Using the ``ChangeManipulator``
 -------------------------------
@@ -301,8 +300,8 @@ about editing an existing one? It's shockingly similar to creating a new one::
         # Get the place in question from the database and create a
         # ChangeManipulator at the same time.
         try:
-            manipulator = places.ChangeManipulator(place_id)
-        except places.PlaceDoesNotExist:
+            manipulator = Place.ChangeManipulator(place_id)
+        except Place.DoesNotExist:
             raise Http404
 
         # Grab the Place object in question for future use.
@@ -322,8 +321,8 @@ about editing an existing one? It's shockingly similar to creating a new one::
             # This makes sure the form accurate represents the fields of the place.
             new_data = place.__dict__
 
-        form = formfields.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('places/edit_form', {'form': form, 'place': place})
+        form = forms.FormWrapper(manipulator, new_data, errors)
+        return render_to_response('places/edit_form.html', {'form': form, 'place': place})
 
 The only real differences are:
 
@@ -362,7 +361,7 @@ your own custom manipulators for handling custom forms.
 Custom manipulators are pretty simple. Here's a manipulator that you might use
 for a &quot;contact&quot; form on a website::
 
-    from django.core import formfields
+    from django import forms
 
     urgency_choices = (
         (1, &quot;Extremely urgent&quot;),
@@ -371,18 +370,18 @@ for a &quot;contact&quot; form on a website::
         (4, &quot;Unimportant&quot;),
     )
 
-    class ContactManipulator(formfields.Manipulator):
+    class ContactManipulator(forms.Manipulator):
         def __init__(self):
             self.fields = (
-                formfields.EmailField(field_name=&quot;from&quot;, is_required=True),
-                formfields.TextField(field_name=&quot;subject&quot;, length=30, maxlength=200, is_required=True),
-                formfields.SelectField(field_name=&quot;urgency&quot;, choices=urgency_choices),
-                formfields.LargeTextField(field_name=&quot;contents&quot;, is_required=True),
+                forms.EmailField(field_name=&quot;from&quot;, is_required=True),
+                forms.TextField(field_name=&quot;subject&quot;, length=30, maxlength=200, is_required=True),
+                forms.SelectField(field_name=&quot;urgency&quot;, choices=urgency_choices),
+                forms.LargeTextField(field_name=&quot;contents&quot;, is_required=True),
             )
 
 A certain similarity to Django's models should be apparent. The only required
 method of a custom manipulator is ``__init__`` which must define the fields
-present in the manipulator.  See the ``django.core.formfields`` module for
+present in the manipulator.  See the ``django.forms`` module for
 all the form fields provided by Django.
 
 You use this custom manipulator exactly as you would use an auto-generated one.
@@ -401,8 +400,8 @@ Here's a simple function that might drive the above form::
                 return HttpResponseRedirect(&quot;/contact/thankyou/&quot;)
         else:
             errors = new_data = {}
-        form = formfields.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('contact_form', {'form': form})
+        form = forms.FormWrapper(manipulator, new_data, errors)
+        return render_to_response('contact_form.html', {'form': form})
 
 Validators
 ==========
@@ -410,16 +409,17 @@ Validators
 One useful feature of manipulators is the automatic validation. Validation is
 done using a simple validation API: A validator is a callable that raises a
 ``ValidationError`` if there's something wrong with the data.
-``django.core.validators`` defines a host of validator functions, but defining
-your own couldn't be easier::
+``django.core.validators`` defines a host of validator functions (see below),
+but defining your own couldn't be easier::
 
-    from django.core import validators, formfields
+    from django.core import validators
+    from django import forms
 
-    class ContactManipulator(formfields.Manipulator):
+    class ContactManipulator(forms.Manipulator):
         def __init__(self):
             self.fields = (
                 # ... snip fields as above ...
-                formfields.EmailField(field_name=&quot;to&quot;, validator_list=[self.isValidToAddress])
+                forms.EmailField(field_name=&quot;to&quot;, validator_list=[self.isValidToAddress])
             )
 
         def isValidToAddress(self, field_data, all_data):
@@ -432,10 +432,153 @@ the field's ``validator_list``.
 
 The arguments to a validator function take a little explanation.  ``field_data``
 is the value of the field in question, and ``all_data`` is a dictionary of all
-the data being validated.  Note that at the point validators are called all
-data will still be strings (as ``do_html2python`` hasn't been called yet).
+the data being validated.
+
+.. admonition:: Note::
+
+    At the point validators are called all data will still be
+    strings (as ``do_html2python`` hasn't been called yet).
 
 Also, because consistency in user interfaces is important, we strongly urge you
 to put punctuation at the end of your validation messages.
 
+Ready-made Validators
+---------------------
+
+Writing your own validator is not difficult, but there are some situations
+that come up over and over again. Django comes with a number of validators
+that can be used directly in your code. All of these functions and classes
+reside in ``django/core/validators.py``.
+
+The following validators should all be self-explanatory. Each one provides a
+check for the given property:
+
+    * isAlphaNumeric
+    * isAlphaNumericURL
+    * isSlug
+    * isLowerCase
+    * isUpperCase
+    * isCommaSeparatedIntegerList
+    * isCommaSeparatedEmailList
+    * isValidIPAddress4
+    * isNotEmpty
+    * isOnlyDigits
+    * isNotOnlyDigits
+    * isInteger
+    * isOnlyLetters
+    * isValidANSIDate
+    * isValidANSITime
+    * isValidEmail
+    * isValidImage
+    * isValidImageURL
+    * isValidPhone
+    * isValidQuicktimeVideoURL
+    * isValidURL
+    * isValidHTML
+    * isWellFormedXml
+    * isWellFormedXmlFragment
+    * isExistingURL
+    * isValidUSState
+    * hasNoProfanities
+
+There are also a group of validators that are slightly more flexible. For
+these validators, you create a validator instance, passing in the parameters
+described below. The returned object is a callable that can be used as a
+validator.
+
+For example::
+
+    from django.core import validators
+    from django import forms
+
+    power_validator = validators.IsAPowerOf(2)
+
+    class InstallationManipulator(forms.Manipulator)
+        def __init__(self):
+            self.fields = (
+                ...
+                forms.IntegerField(field_name = &quot;size&quot;, validator_list=[power_validator])
+            )
+
+Here, ``validators.IsAPowerOf(...)`` returned something that could be used as
+a validator (in this case, a check that a number was a power of 2).
+
+Each of the standard validators that take parameters have an optional final
+argument (``error_message``) that is the message returned when validation
+fails. If no message is passed in, a default message is used.
+
+``AlwaysMatchesOtherField``
+    Takes a field name and the current field is valid if and only if its value
+    matches the contents of the other field.
+
+``ValidateIfOtherFieldEquals``
+    Takes three parameters: ``other_field``, ``other_value`` and
+    ``validator_list``, in that order. If ``other_field`` has a value of
+    ``other_vaue``, then the validators in ``validator_list`` are all run
+    against the current field.
+
+``RequiredIfOtherFieldNotGiven``
+    Takes the name of the other field and this field is only required if the
+    other field has no value.
+
+``RequiredIfOtherFieldsNotGiven``
+    Similar to ``RequiredIfOtherFieldNotGiven``, except that it takes a list
+    of field names and if any one of the supplied fields does not have a value
+    provided, the field being validated is required.
+
+``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
+    Each of these validator classes takes a field name and a value (in that
+    order). If the given field does (or does not have, in the latter case) the
+    given value, then the current field being validated is required.
+
+    Note that because validators are called before any ``do_html2python()``
+    functions, the value being compared against is a string. So
+    ``RequiredIfOtherFieldEquals('choice', '1')`` is correct, whilst
+    ``RequiredIfOtherFieldEquals('choice', 1)`` will never result in the
+    equality test succeeding.
+
+``IsLessThanOtherField``
+    Takes a field name and validates that the current field being validated
+    has a value that is less than (or equal to) the other field's value.
+    Again, comparisons are done using strings, so be cautious about using
+    this function to compare data that should be treated as another type. The
+    string &quot;123&quot; is less than the string &quot;2&quot;, for example. If you don't want
+    string comparison here, you will need to write your own validator.
+
+``IsAPowerOf``
+    Takes an integer argument and when called as a validator, checks that the
+    field being validated is a power of the integer.
+
+``IsValidFloat``
+    Takes a maximum number of digits and number of decimal places (in that
+    order) and validates whether the field is a float with less than the
+    maximum number of digits and decimal place.
+
+``MatchesRegularExpression``
+    Takes a regular expression (a string) as a parameter and validates the
+    field value against it.
+
+``AnyValidator``
+    Takes a list of validators as a parameter. At validation time, if the
+    field successfully validates against any one of the validators, it passes
+    validation. The validators are tested in the order specified in the
+    original list.
+
+``URLMimeTypeCheck``
+    Used to validate URL fields. Takes a list of MIME types (such as
+    ``text/plain``) at creation time. At validation time, it verifies that the
+    field is indeed a URL and then tries to retrieve the content at the URL.
+    Validation succeeds if the content could be retrieved and it has a content
+    type from the list used to create the validator.
+
+``RelaxNGCompact``
+    Used to validate an XML document against a Relax NG compact schema. Takes
+    a file path to the location of the schema and an optional root element
+    (which is wrapped around the XML fragment before validation, if supplied).
+    At validation time, the XML fragment is validated against the schema using
+    the executable specified in the ``JING_PATH`` setting (see the settings_
+    document for more details).
+
 .. _`generic views`: http://www.djangoproject.com/documentation/generic_views/
+.. _`models API`: http://www.djangoproject.com/documentation/model_api/
+.. _settings: http://www.djangoproject.com/documentation/settings/</diff>
      <filename>docs/forms.txt</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,11 @@
-===================
-Using generic views
-===================
+=============
+Generic views
+=============
 
 Writing Web applications can be monotonous, because we repeat certain patterns
 again and again. In Django, the most common of these patterns have been
 abstracted into &quot;generic views&quot; that let you quickly provide common views of
-an object without actually needing to write any views.
+an object without actually needing to write any Python code.
 
 Django's generic views contain the following:
 
@@ -28,14 +28,14 @@ Django's generic views contain the following:
 
 All of these views are used by creating configuration dictionaries in
 your URLconf files and passing those dictionaries as the third member of the
-URLconf tuple. For example, here's the URLconf for the simple weblog app that
-drives the blog on djangoproject.com::
+URLconf tuple for a given pattern. For example, here's the URLconf for the
+simple weblog app that drives the blog on djangoproject.com::
 
     from django.conf.urls.defaults import *
+    from django_website.apps.blog.models import Entry
 
     info_dict = {
-        'app_label': 'blog',
-        'module_name': 'entries',
+        'queryset': Entry.objects.all(),
         'date_field': 'pub_date',
     }
 
@@ -47,388 +47,902 @@ drives the blog on djangoproject.com::
        (r'^/?$',                                                                  'archive_index', info_dict),
     )
 
-As you can see, this URLconf defines a few options in ``info_dict`` that tell
-the generic view which model to use (``blog.entries`` in this case), as well as
-some extra information.
+As you can see, this URLconf defines a few options in ``info_dict``.
+``'queryset'`` gives the generic view a ``QuerySet`` of objects to use (in this
+case, all of the ``Entry`` objects) and tells the generic view which model is
+being used.
 
 Documentation of each generic view follows, along with a list of all keyword
 arguments that a generic view expects. Remember that as in the example above,
 arguments may either come from the URL pattern (as ``month``, ``day``,
 ``year``, etc. do above) or from the additional-information dictionary (as for
-``app_label``, ``module_name``, etc.).
+``queryset``, ``date_field``, etc.).
 
-Most of the generic views that follow require the ``app_label`` and
-``module_name`` keys. These values are easiest to explain through example::
+Most generic views require the ``queryset`` key, which is a ``QuerySet``
+instance; see the `database API docs`_ for more information about ``Queryset``
+objects.
 
-    &gt;&gt;&gt; from django.models.blog import entries
-
-In the above line, ``blog`` is the ``app_label`` (the name of the file that
-holds all your model definitions) and ``entries`` is the ``module_name``
-(either a pluralized, lowercased version of the model class name, or the value
-of the ``module_name`` option of your model). In the docs below, these keys
-will not be repeated, but each generic view requires them.
-
-Using &quot;simple&quot; generic views
-============================
+&quot;Simple&quot; generic views
+======================
 
 The ``django.views.generic.simple`` module contains simple views to handle a
 couple of common cases: rendering a template when no view logic is needed,
-and issuing a redirect.  These views are:
+and issuing a redirect.
+
+``django.views.generic.simple.direct_to_template``
+--------------------------------------------------
+
+**Description:**
+
+Renders a given template, passing it a ``{{ params }}`` template variable,
+which is a dictionary of the parameters captured in the URL.
+
+**Required arguments:**
+
+    * ``template``: The full name of a template to use.
+
+**Example:**
 
-``direct_to_template``
-    Renders a given template, passing it a ``{{ params }}`` template variable,
-    which is a dictionary of the parameters captured in the URL. This requires
-    the ``template`` argument.
+Given the following URL patterns::
 
-    For example, given the following URL patterns::
+    urlpatterns = patterns('django.views.generic.simple',
+        (r'^foo/$',             'direct_to_template', {'template': 'foo_index.html'}),
+        (r'^foo/(?P&lt;id&gt;\d+)/$', 'direct_to_template', {'template': 'foo_detail.html'}),
+    )
+
+... a request to ``/foo/`` would render the template ``foo_index.html``, and a
+request to ``/foo/15/`` would render the ``foo_detail.html`` with a context
+variable ``{{ params.id }}`` that is set to ``15``.
+
+``django.views.generic.simple.redirect_to``
+-------------------------------------------
+
+**Description:**
 
-        urlpatterns = patterns('django.views.generic.simple',
-            (r'^foo/$',             'direct_to_template', {'template': 'foo_index'}),
-            (r'^foo/(?P&lt;id&gt;\d+)/$', 'direct_to_template', {'template': 'foo_detail'}),
-        )
+Redirects to a given URL.
 
-    ... a request to ``/foo/`` would cause the ``foo_index`` template to be
-    rendered, and a request to ``/foo/15/`` would cause the ``foo_detail``
-    template to be rendered with a context variable ``{{ params.id }}`` that is
-    set to ``15``.
+The given URL may contain dictionary-style string formatting, which will be
+interpolated against the parameters captured in the URL.
 
-``redirect_to``
-    Issue a redirect to a given URL.
+If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
 
-    The given URL may contain dict-style string formatting, which will be
-    interpolated against the params in the URL.  For example, to redirect from
-    ``/foo/&lt;id&gt;/`` to ``/bar/&lt;id&gt;/``, you could use the following urlpattern::
+**Required arguments:**
 
-        urlpatterns = patterns('django.views.generic.simple',
-            ('^foo/(?p&lt;id&gt;\d+)/$', 'redirect_to', {'url' : '/bar/%(id)s/'}),
-        )
+    * ``url``: The URL to redirect to, as a string. Or ``None`` to raise a 410
+      (Gone) HTTP error.
 
-    If the given URL is ``None``, an ``HttpResponseGone`` (410) will be issued.
+**Example:**
 
-Using date-based generic views
-==============================
+This example redirects from ``/foo/&lt;id&gt;/`` to ``/bar/&lt;id&gt;/``::
+
+    urlpatterns = patterns('django.views.generic.simple',
+        ('^foo/(?p&lt;id&gt;\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
+    )
+
+This example returns a 410 HTTP error for requests to ``/bar/``::
+
+    urlpatterns = patterns('django.views.generic.simple',
+        ('^bar/$', 'redirect_to', {'url': None}),
+    )
+
+Date-based generic views
+========================
 
 Date-based generic views (in the module ``django.views.generic.date_based``)
-feature six functions for dealing with date-based data. Besides ``app_label``
-and ``module_name``, all date-based generic views require that the
-``date_field`` argument be passed to them. This is the name of the field that
-stores the date the objects should key off of.
+are views for displaying drilldown pages for date-based data.
+
+``django.views.generic.date_based.archive_index``
+-------------------------------------------------
+
+**Description:**
+
+A top-level index page showing the &quot;latest&quot; objects, by date. Objects with
+a date in the *future* are not included.
+
+**Required arguments:**
+
+    * ``queryset``: A ``QuerySet`` of objects for which the archive serves.
+
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the date-based archive should use to
+      determine the objects on the page.
+
+**Optional arguments:**
+
+    * ``num_latest``: The number of latest objects to send to the template
+      context. By default, it's 15.
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``False``.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_archive.html`` by default, where:
+
+    * ``&lt;model_name&gt;`` is your model's name in all lowercase. For a model
+        ``StaffMember``, that'd be ``staffmember``.
+
+    * ``&lt;app_label&gt;`` is the right-most part of the full Python path to
+        your model's app. For example, if your model lives in
+        ``apps/blog/models.py``, that'd be ``blog``.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``date_list``: A list of ``datetime.date`` objects representing all
+      years that have objects available according to ``queryset``. These are
+      ordered in reverse. This is equivalent to
+      ``queryset.dates(date_field, 'year')[::-1]``.
+    * ``latest``: The ``num_latest`` objects in the system, ordered descending
+      by ``date_field``. For example, if ``num_latest`` is ``10``, then
+      ``latest`` will be a list of the latest 10 objects in ``queryset``.
+
+.. _RequestContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
+
+``django.views.generic.date_based.archive_year``
+------------------------------------------------
+
+**Description:**
+
+A yearly archive page showing all available months in a given year. Objects
+with a date in the *future* are not displayed.
+
+**Required arguments:**
+
+    * ``year``: The four-digit year for which the archive serves.
+
+    * ``queryset``: A ``QuerySet`` of objects for which the archive serves.
+
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the date-based archive should use to
+      determine the objects on the page.
+
+**Optional arguments:**
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``False``.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_archive_year.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``date_list``: A list of ``datetime.date`` objects representing all
+      months that have objects available in the given year, according to
+      ``queryset``, in ascending order.
+    * ``year``: The given year, as a four-character string.
+
+``django.views.generic.date_based.archive_month``
+-------------------------------------------------
+
+**Description:**
+
+A monthly archive page showing all objects in a given month. Objects with a
+date in the *future* are not displayed.
+
+**Required arguments:**
+
+    * ``year``: The four-digit year for which the archive serves (a string).
 
-Additionally, all date-based generic views have the following optional
-arguments:
+    * ``month``: The month for which the archive serves, formatted according to
+      the ``month_format`` argument.
 
-    =======================  ==================================================
-    Argument                 Description
-    =======================  ==================================================
-    ``template_name``        Overrides the default template name used for the
-                             view.
+    * ``queryset``: A ``QuerySet`` of objects for which the archive serves.
 
-    ``extra_lookup_kwargs``  A dictionary of extra lookup parameters (see
-                             the `database API docs`_).
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the date-based archive should use to
+      determine the objects on the page.
 
-    ``extra_context``        A dictionary of extra data to put into the
-                             template's context.
+**Optional arguments:**
 
-    ``processors``           A tuple of processors to apply to the
-                             ``DjangoContext`` of this view's template. See the
-                             `DjangoContext docs`_
-    =======================  ==================================================
+    * ``month_format``: A format string that regulates what format the
+      ``month`` parameter uses. This should be in the syntax accepted by
+      Python's ``time.strftime``. (See the `strftime docs`_.) It's set to
+      ``&quot;%b&quot;`` by default, which is a three-letter month abbreviation. To
+      change it to use numbers, use ``&quot;%m&quot;``.
 
-.. _database API docs: http://www.djangoproject.com/documentation/db_api/
-.. _DjangoContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
 
-The date-based generic functions are:
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
 
-``archive_index``
-    A top-level index page showing the &quot;latest&quot; objects.
-
-    Takes the following optional arguments:
-
-        =======================  =================================================
-        Argument                 Description
-        =======================  =================================================
-        ``num_latest``           The number of items to display on the page.
-                                 Defaults to 15.
-
-        ``allow_empty``          If ``False`` and there are no objects to display,
-                                 the view will raise a 404 instead of displaying
-                                 an empty index page. ``False`` is default.
-        =======================  =================================================
-
-    Uses the template ``app_label/module_name_archive`` by default.
-
-    Has the following template context:
-
-        ``date_list``
-            List of years with objects
-        ``latest``
-            Latest objects by date
-
-``archive_year``
-    Yearly archive. Requires that the ``year`` argument be present in the URL
-    pattern.
-
-    **New in Django development version:** Takes an optional ``allow_empty``
-    parameter, as ``archive_index``.
-
-    Uses the template ``app_label/module_name_archive_year`` by default.
-
-    Has the following template context:
-
-        ``date_list``
-            List of months in the given year with objects
-        ``year``
-            The given year (an integer)
-
-``archive_month``
-    Monthly archive. Requires that ``year`` and ``month`` arguments be given.
-    You can pass the additional option ``month_format`` if you'd like to change
-    the way months are specified in the URL.
-
-    ``month_format`` is a format string in the same syntax accepted by Python's
-    ``time.strftime``. (See the `strftime docs`_.) It's set to ``&quot;%b&quot;`` by
-    default, which is a three-letter month abbreviation. To change it to use
-    numbers, use ``&quot;%m&quot;``.
-
-    **New in Django development version:** Takes an optional ``allow_empty``
-    parameter, as ``archive_index``.
-
-    **New in Django development version:** Takes an optional
-    ``template_object_name`` parameter, which designates the name of the
-    template variable to use. Default is ``'object'``.
-
-    Uses the template ``app_label/module_name_archive_month`` by default.
-
-    Has the following template context:
-
-        ``month``
-            The given month (a datetime.date object)
-        ``next_month``
-            **New in Django development version.** The first day of the next
-            month, or None if the next month is in the future (a datetime.date
-            object)
-        ``previous_month``
-            **New in Django development version.** The first day of the
-            previous month (a datetime.date object)
-        ``object_list``
-            List of objects published in the given month.
-            In the Django development version, you can change this variable
-            name from ``object_list`` by using the ``template_object_name``
-            parameter. (See above.) For example, if ``template_object_name`` is
-            ``foo``, the variable will be ``foo_list``.
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
 
-``archive_day``
-    Daily archive. Requires that ``year``, ``month``, and ``day`` arguments be
-    given.
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``False``.
 
-    As in ``archive_month``, you can pass an optional ``month_format``. You can
-    also pass ``day_format``, which defaults to ``&quot;%d&quot;`` (day of the month as a
-    decimal number, 01-31).
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
 
-    **New in Django development version:** Takes an optional
-    ``template_object_name`` parameter, which designates the name of the
-    template variable to use. Default is ``'object'``.
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``. The
+       view will append ``'_list'`` to the value of this parameter in
+       determining the variable's name.
 
-    Uses the template ``app_label/module_name_archive_day`` by default.
-
-    Has the following template context:
+**Template name:**
 
-        ``object_list``
-            List of objects published on the given day.
-            In the Django development version, you can change this variable
-            name from ``object_list`` by using the ``template_object_name``
-            parameter. (See above.) For example, if ``template_object_name`` is
-            ``foo``, the variable will be ``foo_list``.
-        ``day``
-            The given day (a datetime.datetime object)
-        ``previous_day``
-            The previous day (a datetime.datetime object)
-        ``next_day``
-            The next day (a datetime.datetime object), or None if the given
-            day is today
-
-``archive_today``
-    List of objects for today. Exactly the same as ``archive_day``, except
-    the year/month/day arguments are not given, and today's date is used
-    instead.
-
-``object_detail``
-    Individual object page. Requires ``year``/``month``/``day`` arguments like
-    ``archive_day``. This function can be used with two types of URLs: either
-    ``/year/month/day/slug/`` or ``/year/month/day/object_id/``.
-
-    If you're using the slug-style URLs, you'll need to have a ``slug`` item in
-    your URLconf, and you'll need to pass a ``slug_field`` key in your info
-    dictionary to indicate the name of the slug field.
-
-    If you're using the object_id-style URLs, you'll just need to give the URL
-    pattern an ``object_id`` field.
-
-    You can also pass the ``template_name_field`` argument to indicate that the
-    the object stores the name of its template in a field on the object itself.
-
-    As in ``archive_day``, ``object_detail`` takes optional ``month_format``
-    and ``day_format`` parameters.
-
-    **New in Django development version:** Takes an optional
-    ``template_object_name`` parameter, which designates the name of the
-    template variable to use. Default is ``'object'``.
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_archive_month.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``month``: A ``datetime.date`` object representing the given month.
+
+    * ``next_month``: A ``datetime.date`` object representing the first day of
+      the next month. If the next month is in the future, this will be
+      ``None``.
+
+    * ``previous_month``: A ``datetime.date`` object representing the first day
+      of the previous month. Unlike ``next_month``, this will never be
+      ``None``.
+
+    * ``object_list``: A list of objects available for the given month. This
+      variable's name depends on the ``template_object_name`` parameter, which
+      is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
+      this variable's name will be ``foo_list``.
 
 .. _strftime docs: http://www.python.org/doc/current/lib/module-time.html#l2h-1941
 
-Using list/detail generic views
-===============================
+``django.views.generic.date_based.archive_week``
+------------------------------------------------
+
+**Description:**
+
+A weekly archive page showing all objects in a given week. Objects with a date
+in the *future* are not displayed.
+
+**Required arguments:**
+
+    * ``year``: The four-digit year for which the archive serves (a string).
+
+    * ``week``: The week of the year for which the archive serves (a string).
+      Weeks start with Sunday.
+
+    * ``queryset``: A ``QuerySet`` of objects for which the archive serves.
+
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the date-based archive should use to
+      determine the objects on the page.
+
+**Optional arguments:**
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``True``.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``. The
+       view will append ``'_list'`` to the value of this parameter in
+       determining the variable's name.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_archive_week.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``week``: A ``datetime.date`` object representing the first day of the
+      given week.
+
+    * ``object_list``: A list of objects available for the given week. This
+      variable's name depends on the ``template_object_name`` parameter, which
+      is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
+      this variable's name will be ``foo_list``.
+
+``django.views.generic.date_based.archive_day``
+-----------------------------------------------
+
+**Description:**
+
+A day archive page showing all objects in a given day. Days in the future throw
+a 404 error, regardless of whether any objects exist for future days.
+
+**Required arguments:**
+
+    * ``year``: The four-digit year for which the archive serves (a string).
+
+    * ``month``: The month for which the archive serves, formatted according to
+      the ``month_format`` argument.
+
+    * ``day``: The day for which the archive serves, formatted according to the
+      ``day_format`` argument.
+
+    * ``queryset``: A ``QuerySet`` of objects for which the archive serves.
+
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the date-based archive should use to
+      determine the objects on the page.
+
+**Optional arguments:**
+
+    * ``month_format``: A format string that regulates what format the
+      ``month`` parameter uses. This should be in the syntax accepted by
+      Python's ``time.strftime``. (See the `strftime docs`_.) It's set to
+      ``&quot;%b&quot;`` by default, which is a three-letter month abbreviation. To
+      change it to use numbers, use ``&quot;%m&quot;``.
+
+    * ``day_format``: Like ``month_format``, but for the ``day`` parameter.
+      It defaults to ``&quot;%d&quot;`` (day of the month as a decimal number, 01-31).
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``False``.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``. The
+       view will append ``'_list'`` to the value of this parameter in
+       determining the variable's name.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_archive_day.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``day``: A ``datetime.date`` object representing the given day.
+
+    * ``next_day``: A ``datetime.date`` object representing the next day. If
+      the next day is in the future, this will be ``None``.
+
+    * ``previous_day``: A ``datetime.date`` object representing the given day.
+      Unlike ``next_day``, this will never be ``None``.
+
+    * ``object_list``: A list of objects available for the given day. This
+      variable's name depends on the ``template_object_name`` parameter, which
+      is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
+      this variable's name will be ``foo_list``.
+
+``django.views.generic.date_based.archive_today``
+-------------------------------------------------
+
+**Description:**
+
+A day archive page showing all objects for *today*. This is exactly the same as
+``archive_day``, except the ``year``/``month``/``day`` arguments are not used,
+and today's date is used instead.
+
+``django.views.generic.date_based.object_detail``
+-------------------------------------------------
+
+**Description:**
+
+A page representing an individual object.
+
+**Required arguments:**
+
+    * ``year``: The object's four-digit year (a string).
+
+    * ``month``: The object's month , formatted according to the
+      ``month_format`` argument.
+
+    * ``day``: The object's day , formatted according to the ``day_format``
+      argument.
+
+    * ``queryset``: A ``QuerySet`` that contains the object.
+
+    * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
+      the ``QuerySet``'s model that the generic view should use to look up the
+      object according to ``year``, ``month`` and ``day``.
+
+    * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
+
+      If you provide ``object_id``, it should be the value of the primary-key
+      field for the object being displayed on this page.
+
+      Otherwise, ``slug`` should be the slug of the given object, and
+      ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
+      model.
+
+**Optional arguments:**
+
+    * ``month_format``: A format string that regulates what format the
+      ``month`` parameter uses. This should be in the syntax accepted by
+      Python's ``time.strftime``. (See the `strftime docs`_.) It's set to
+      ``&quot;%b&quot;`` by default, which is a three-letter month abbreviation. To
+      change it to use numbers, use ``&quot;%m&quot;``.
+
+    * ``day_format``: Like ``month_format``, but for the ``day`` parameter.
+      It defaults to ``&quot;%d&quot;`` (day of the month as a decimal number, 01-31).
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_name_field``: The name of a field on the object whose value is
+      the template name to use. This lets you store template names in the data.
+      In other words, if your object has a field ``'the_template'`` that
+      contains a string ``'foo.html'``, and you set ``template_name_field`` to
+      ``'the_template'``, then the generic view for this object will use the
+      template ``'foo.html'``.
+
+      It's a bit of a brain-bender, but it's useful in some cases.
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_detail.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``object``: The object. This variable's name depends on the
+      ``template_object_name`` parameter, which is ``'object'`` by default. If
+      ``template_object_name`` is ``'foo'``, this variable's name will be
+      ``foo``.
+
+List/detail generic views
+=========================
 
 The list-detail generic-view framework (in the
 ``django.views.generic.list_detail`` module) is similar to the date-based one,
 except the former simply has two views: a list of objects and an individual
 object page.
 
-All these views take the same four optional arguments as the date-based ones
--- and, clearly, they don't accept the ``date_field`` argument.
-
-Individual views are:
-
-``object_list``
-    List of objects.
-
-    Takes the following optional arguments:
-
-        ========================  =================================================
-        Argument                  Description
-        ========================  =================================================
-        ``paginate_by``           If set to an integer, the view will paginate
-                                  objects with ``paginate_by`` objects per page.
-                                  The view will expect a ``page`` GET param with
-                                  the (zero-indexed) page number.
-
-        ``allow_empty``           If ``False`` and there are no objects to display,
-                                  the view will raise a 404 instead of displaying
-                                  an empty index page. ``False`` is default.
-
-        ``template_object_name``  **New in Django development version.** Designates
-                                  the name of the object template variable. Default
-                                  is ``'object'``.
-        ========================  =================================================
-
-    Uses the template ``app_label/module_name_list`` by default.
-
-    Has the following template context:
-
-        ``object_list``
-            List of objects. In the Django development version, you can change
-            this variable name from ``object_list`` by using the
-            ``template_object_name`` parameter. (See above.) For example, if
-            ``template_object_name`` is ``foo``, the variable will be
-            ``foo_list``.
-        ``is_paginated``
-            Are the results paginated? Either True or False
-
-    If the results are paginated, the context will have some extra variables:
-
-        ``results_per_page``
-            Number of objects per page
-        ``has_next``
-            Is there a next page?
-        ``has_previous``
-            Is there a previous page?
-        ``page``
-            The current page number
-        ``next``
-            The next page number
-        ``previous``
-            The previous page
-        ``pages``
-            Number of pages total
-        ``hits``
-            Total number of objects
-
-``object_detail``
-    Object detail page. This works like and takes the same arguments as
-    the date-based ``object_detail`` above, except this one, obviously,
-    does not take the year/month/day arguments.
-
-Using create/update/delete generic views
-========================================
+``django.views.generic.list_detail.object_list``
+------------------------------------------------
+
+**Description:**
+
+A page representing a list of objects.
+
+**Required arguments:**
+
+    * ``queryset``: A ``QuerySet`` that represents the objects.
+
+**Optional arguments:**
+
+    * ``paginate_by``: An integer specifying how many objects should be
+      displayed per page. If this is given, the view will paginate objects with
+      ``paginate_by`` objects per page. The view will expect a ``page`` query
+      string (GET) parameter containing a zero-indexed page number.
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``allow_empty``: A boolean specifying whether to display the page if no
+      objects are available. If this is ``False`` and no objects are available,
+      the view will raise a 404 instead of displaying an empty page. By
+      default, this is ``False``.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``. The
+       view will append ``'_list'`` to the value of this parameter in
+       determining the variable's name.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_list.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``object_list``: The list of objects. This variable's name depends on the
+      ``template_object_name`` parameter, which is ``'object'`` by default. If
+      ``template_object_name`` is ``'foo'``, this variable's name will be
+      ``foo_list``.
+
+    * ``is_paginated``: A boolean representing whether the results are
+      paginated. Specifically, this is set to ``False`` if the number of
+      available objects is less than or equal to ``paginate_by``.
+
+If the results are paginated, the context will contain these extra variables:
+
+    * ``results_per_page``: The number of objects per page. (Same as the
+      ``paginate_by`` parameter.)
+
+    * ``has_next``: A boolean representing whether there's a next page.
+
+    * ``has_previous``: A boolean representing whether there's a previous page.
+
+    * ``page``: The current page number, as an integer. This is 1-based.
+
+    * ``next``: The next page number, as an integer. If there's no next page,
+      this will still be an integer representing the theoretical next-page
+      number. This is 1-based.
+
+    * ``previous``: The previous page number, as an integer. This is 1-based.
+
+    * ``pages``: The total number of pages, as an integer.
+
+    * ``hits``: The total number of objects across *all* pages, not just this
+      page.
+
+``django.views.generic.list_detail.object_detail``
+--------------------------------------------------
+
+A page representing an individual object.
+
+**Description:**
+
+A page representing an individual object.
+
+**Required arguments:**
+
+    * ``queryset``: A ``QuerySet`` that contains the object.
+
+    * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
+
+      If you provide ``object_id``, it should be the value of the primary-key
+      field for the object being displayed on this page.
+
+      Otherwise, ``slug`` should be the slug of the given object, and
+      ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
+      model.
+
+**Optional arguments:**
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_name_field``: The name of a field on the object whose value is
+      the template name to use. This lets you store template names in the data.
+      In other words, if your object has a field ``'the_template'`` that
+      contains a string ``'foo.html'``, and you set ``template_name_field`` to
+      ``'the_template'``, then the generic view for this object will use the
+      template ``'foo.html'``.
+
+      It's a bit of a brain-bender, but it's useful in some cases.
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_detail.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``object``: The object. This variable's name depends on the
+      ``template_object_name`` parameter, which is ``'object'`` by default. If
+      ``template_object_name`` is ``'foo'``, this variable's name will be
+      ``foo``.
+
+Create/update/delete generic views
+==================================
 
 The ``django.views.generic.create_update`` module contains a set of functions
-for creating, editing and deleting objects. These views take the same global
-arguments as the above sets of generic views. They also have a
-``login_required`` argument which, if ``True``, requires the user to be logged
-in to have access to the page. (``login_required`` defaults to ``False``.)
+for creating, editing and deleting objects.
+
+``django.views.generic.create_update.create_object``
+----------------------------------------------------
+
+**Description:**
+
+A page that displays a form for creating an object, redisplaying the form with
+validation errors (if there are any) and saving the object. This uses the
+automatic manipulators that come with Django models.
+
+**Required arguments:**
+
+    * ``model``: The Django model class of the object that the form will
+      create.
+
+**Optional arguments:**
+
+    * ``post_save_redirect``: A URL to which the view will redirect after
+      saving the object. By default, it's ``object.get_absolute_url()``.
+
+      ``post_save_redirect`` may contain dictionary string formatting, which
+      will be interpolated against the object's field attributes. For example,
+      you could use ``post_save_redirect=&quot;/polls/%(slug)s/&quot;``.
+
+    * ``login_required``: A boolean that designates whether a user must be
+      logged in, in order to see the page and save changes. This hooks into the
+      Django `authentication system`_. By default, this is ``False``.
+
+      If this is ``True``, and a non-logged-in user attempts to visit this page
+      or save the form, Django will redirect the request to ``/accounts/login/``.
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_form.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``form``: A ``django.forms.FormWrapper`` instance representing the form
+      for editing the object. This lets you refer to form fields easily in the
+      template system.
+
+      For example, if ``model`` has two fields, ``name`` and ``address``::
+
+          &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
+          &lt;p&gt;&lt;label for=&quot;id_name&quot;&gt;Name:&lt;/label&gt; {{ form.name }}&lt;/p&gt;
+          &lt;p&gt;&lt;label for=&quot;id_address&quot;&gt;Address:&lt;/label&gt; {{ form.address }}&lt;/p&gt;
+          &lt;/form&gt;
+
+      See the `manipulator and formfield documentation`_ for more information
+      about using ``FormWrapper`` objects in templates.
+
+.. _authentication system: http://www.djangoproject.com/documentation/authentication/
+.. _manipulator and formfield documentation: http://www.djangoproject.com/documentation/forms/
+
+``django.views.generic.create_update.update_object``
+----------------------------------------------------
+
+**Description:**
+
+A page that displays a form for editing an existing object, redisplaying the
+form with validation errors (if there are any) and saving changes to the
+object. This uses the automatic manipulators that come with Django models.
+
+**Required arguments:**
+
+    * ``model``: The Django model class of the object that the form will
+      create.
+
+    * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
+
+      If you provide ``object_id``, it should be the value of the primary-key
+      field for the object being displayed on this page.
+
+      Otherwise, ``slug`` should be the slug of the given object, and
+      ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
+      model.
+
+**Optional arguments:**
+
+    * ``post_save_redirect``: A URL to which the view will redirect after
+      saving the object. By default, it's ``object.get_absolute_url()``.
+
+      ``post_save_redirect`` may contain dictionary string formatting, which
+      will be interpolated against the object's field attributes. For example,
+      you could use ``post_save_redirect=&quot;/polls/%(slug)s/&quot;``.
+
+    * ``login_required``: A boolean that designates whether a user must be
+      logged in, in order to see the page and save changes. This hooks into the
+      Django `authentication system`_. By default, this is ``False``.
+
+      If this is ``True``, and a non-logged-in user attempts to visit this page
+      or save the form, Django will redirect the request to ``/accounts/login/``.
+
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
+
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
+
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
+
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
+
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``.
+
+**Template name:**
+
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_form.html`` by default.
+
+**Template context:**
+
+In addition to ``extra_context``, the template's context will be:
+
+    * ``form``: A ``django.forms.FormWrapper`` instance representing the form
+      for editing the object. This lets you refer to form fields easily in the
+      template system.
+
+      For example, if ``model`` has two fields, ``name`` and ``address``::
+
+          &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
+          &lt;p&gt;&lt;label for=&quot;id_name&quot;&gt;Name:&lt;/label&gt; {{ form.name }}&lt;/p&gt;
+          &lt;p&gt;&lt;label for=&quot;id_address&quot;&gt;Address:&lt;/label&gt; {{ form.address }}&lt;/p&gt;
+          &lt;/form&gt;
+
+      See the `manipulator and formfield documentation`_ for more information
+      about using ``FormWrapper`` objects in templates.
+
+    * ``object``: The original object being edited. This variable's name
+      depends on the ``template_object_name`` parameter, which is ``'object'``
+      by default. If ``template_object_name`` is ``'foo'``, this variable's
+      name will be ``foo``.
+
+``django.views.generic.create_update.delete_object``
+----------------------------------------------------
+
+**Description:**
 
-The create/update/delete views are:
+A view that displays a confirmation page and deletes an existing object. The
+given object will only be deleted if the request method is ``POST``. If this
+view is fetched via ``GET``, it will display a confirmation page that should
+contain a form that POSTs to the same URL.
 
-``create_object``
-    Create a new object. Has an extra optional argument, ``post_save_redirect``,
-    which is a URL to which the view will redirect after saving the object.
-    It defaults to ``object.get_absolute_url()``.
+**Required arguments:**
 
-    ``post_save_redirect`` may contain dictionary string formatting, which will
-    be interpolated against the object's field attributes. For example, you
-    could use ``post_save_redirect=&quot;/polls/%(slug)s/&quot;``.
+    * ``model``: The Django model class of the object that the form will
+      create.
 
-    Uses the template ``app_label/module_name_form`` by default. This is the
-    same template as the ``update_object`` view below. Your template can tell
-    the difference by the presence or absence of ``{{ object }}`` in the
-    context.
+    * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
 
-    Has the following template context:
+      If you provide ``object_id``, it should be the value of the primary-key
+      field for the object being displayed on this page.
 
-        form
-            The form wrapper for the object
+      Otherwise, ``slug`` should be the slug of the given object, and
+      ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
+      model.
 
-    .. admonition:: Note
+    * ``post_delete_redirect``: A URL to which the view will redirect after
+      deleting the object.
 
-        See the `manipulator and formfield documentation`_ for more information
-        about using form wrappers in templates.
+**Optional arguments:**
 
-.. _`manipulator and formfield documentation`: http://www.djangoproject.com/documentation/forms/
+    * ``login_required``: A boolean that designates whether a user must be
+      logged in, in order to see the page and save changes. This hooks into the
+      Django `authentication system`_. By default, this is ``False``.
 
-``update_object``
-    Edit an existing object. Has the same extra slug/ID parameters as
-    ``list_detail.object_detail`` does (see above), and the same
-    ``post_save_redirect`` as ``create_object`` does.
+      If this is ``True``, and a non-logged-in user attempts to visit this page
+      or save the form, Django will redirect the request to ``/accounts/login/``.
 
-    **New in Django development version:** Takes an optional
-    ``template_object_name`` parameter, which designates the name of the
-    template variable to use. Default is ``'object'``.
+    * ``template_name``: The full name of a template to use in rendering the
+      page. This lets you override the default template name (see below).
 
-    Uses the template ``app_label/module_name_form`` by default.
+    * ``template_loader``: The template loader to use when loading the
+      template. By default, it's ``django.template.loader``.
 
-    Has the following template context:
+    * ``extra_context``: A dictionary of values to add to the template context.
+      If a value in the dictionary is callable, the generic view will call it
+      just before rendering the template. By default, this is an empty
+      dictionary.
 
-        form
-            The form wrapper for the object
-        object
-            The original object being edited.
-            In the Django development version, you can change this variable
-            name from ``object`` by using the ``template_object_name``
-            parameter. (See above.) For example, if ``template_object_name`` is
-            ``foo``, the variable will be ``foo`` instead of ``object``.
+    * ``context_processors``: A list of template-context processors to apply to
+      the view's template. See the `RequestContext docs`_.
 
-``delete_object``
-    Delete an existing object. The given object will only actually be deleted
-    if the request method is POST. If this view is fetched with GET, it will
-    display a confirmation page that should contain a form that POSTs to the
-    same URL.
+    * ``template_object_name``:  Designates the name of the template variable
+       to use in the template context. By default, this is ``'object'``.
 
-    You must provide the ``post_delete_redirect`` argument to this function, so
-    that the view knows where to go after the object is deleted.
+**Template name:**
 
-    If fetched with GET, it uses the template
-    ``app_label/module_name_confirm_delete`` by default. It uses no template
-    if POSTed -- it simply deletes the object and redirects.
+If ``template_name`` isn't specified, this view will use the template
+``&lt;app_label&gt;/&lt;model_name&gt;_confirm_delete.html`` by default.
 
-    **New in Django development version:** Takes an optional
-    ``template_object_name`` parameter, which designates the name of the
-    template variable to use. Default is ``'object'``.
+**Template context:**
 
-    Has the following template context:
+In addition to ``extra_context``, the template's context will be:
 
-        object
-            The object about to be deleted
-            In the Django development version, you can change this variable
-            name from ``object`` by using the ``template_object_name``
-            parameter. (See above.) For example, if ``template_object_name`` is
-            ``foo``, the variable will be ``foo`` instead of ``object``.
+    * ``object``: The original object that's about to be deleted. This
+      variable's name depends on the ``template_object_name`` parameter, which
+      is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
+      this variable's name will be ``foo``.</diff>
      <filename>docs/generic_views.txt</filename>
    </modified>
    <modified>
      <diff>@@ -150,14 +150,14 @@ If you don't like the verbose name ``gettext_lazy``, you can just alias it as
 
 Always use lazy translations in `Django models`_. And it's a good idea to add
 translations for the field names and table names, too. This means writing
-explicit ``verbose_name`` and ``verbose_name_plural`` options in the ``META``
+explicit ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta``
 class, though::
 
     from django.utils.translation import gettext_lazy as _
 
     class MyThing(meta.Model):
         name = meta.CharField(_('name'), help_text=_('This is the help text'))
-        class META:
+        class Meta:
             verbose_name = _('my thing')
             verbose_name_plural = _('mythings')
 
@@ -224,14 +224,14 @@ To pluralize, specify both the singular and plural forms with the
 Internally, all block and inline translations use the appropriate
 ``gettext`` / ``ngettext`` call.
 
-Each ``DjangoContext`` has access to two translation-specific variables:
+Each ``RequestContext`` has access to two translation-specific variables:
 
     * ``LANGUAGES`` is a list of tuples in which the first element is the
       language code and the second is the language name (in that language).
     * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
       Example: ``en-us``. (See &quot;How language preference is discovered&quot;, below.)
 
-If you don't use the ``DjangoContext`` extension, you can get those values with
+If you don't use the ``RequestContext`` extension, you can get those values with
 two tags::
 
     {% get_current_language as LANGUAGE_CODE %}
@@ -404,7 +404,7 @@ should follow these guidelines:
 For example, your ``MIDDLEWARE_CLASSES`` might look like this::
 
     MIDDLEWARE_CLASSES = (
-       'django.middleware.sessions.SessionMiddleware',
+       'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'django.middleware.common.CommonMiddleware',
     )</diff>
      <filename>docs/i18n.txt</filename>
    </modified>
    <modified>
      <diff>@@ -77,9 +77,9 @@ It's easy either way.
 Installing the official version
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-1. Download Django-0.91.tar.gz from our `download page`_.
-2. ``tar xzvf Django-0.91.tar.gz``
-3. ``cd Django-0.91``
+1. Download Django-0.92.tar.gz from our `download page`_.
+2. ``tar xzvf Django-0.92.tar.gz``
+3. ``cd Django-0.92``
 4. ``sudo python setup.py install``
 
 Note that the last command will automatically download and install setuptools_</diff>
      <filename>docs/install.txt</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,7 @@ You'll need to tell Django what your database connection parameters are, and
 what the name of the database is. Do that by editing these settings in your
 `settings file`_:
 
+    * `DATABASE_NAME`
     * `DATABASE_ENGINE`_
     * `DATABASE_USER`_
     * `DATABASE_PASSWORD`_
@@ -26,6 +27,7 @@ what the name of the database is. Do that by editing these settings in your
     * `DATABASE_PORT`_
 
 .. _settings file: http://www.djangoproject.com/documentation/settings/
+.. _DATABASE_NAME: http://www.djangoproject.com/documentation/settings/#database-name
 .. _DATABASE_ENGINE: http://www.djangoproject.com/documentation/settings/#database-engine
 .. _DATABASE_USER: http://www.djangoproject.com/documentation/settings/#database-user
 .. _DATABASE_PASSWORD: http://www.djangoproject.com/documentation/settings/#database-password
@@ -39,57 +41,29 @@ Auto-generate the models
 Django comes with a utility that can create models by introspecting an existing
 database. You can view the output by running this command::
 
-    django-admin.py inspectdb [databasename] --settings=path.to.settings
-
-...where &quot;[databasename]&quot; is the name of your database.
+    django-admin.py inspectdb --settings=path.to.settings
 
 Save this as a file by using standard Unix output redirection::
 
-    django-admin.py inspectdb [databasename] --settings=path.to.settings &gt; appname.py
+    django-admin.py inspectdb --settings=path.to.settings &gt; models.py
 
 This feature is meant as a shortcut, not as definitive model generation. See
 the `django-admin.py documentation`_ for more information.
 
-Once you've cleaned up the model, put the module in the ``models`` directory of
-your app, and add it to your ``INSTALLED_APPS`` setting.
+Once you've cleaned up your models, name the file ``models.py`` and put it in
+the Python package that holds your app. Then add the app to your
+``INSTALLED_APPS`` setting.
 
 .. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
 
 Install the core Django tables
 ==============================
 
-Next, run the ``django-admin.py init`` command to install Django's core tables
-in your database::
+Next, run the ``manage.py syncdb`` command to install any extra needed database
+records such as admin permissions and content types::
 
     django-admin.py init --settings=path.to.settings
 
-This won't work if your database already contains tables that have any of the
-following names:
-
-    * ``sites``
-    * ``packages``
-    * ``content_types``
-    * ``core_sessions``
-    * ``auth_permissions``
-    * ``auth_groups``
-    * ``auth_users``
-    * ``auth_messages``
-    * ``auth_groups_permissions``
-    * ``auth_users_groups``
-    * ``auth_users_user_permissions``
-
-If that's the case, try renaming one of your tables to resolve naming
-conflicts. Currently, there's no way of customizing the names of Django's
-database tables without editing Django's source code itself.
-
-Install metadata about your app
-===============================
-
-Django has a couple of database tables that contain metadata about your apps.
-You'll need to execute the SQL output by this command::
-
-    django-admin.py sqlinitialdata [appname] --settings=path.to.settings
-
 See whether it worked
 =====================
 </diff>
      <filename>docs/legacy_databases.txt</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,8 @@ name. For example, here's the default ``MIDDLEWARE_CLASSES`` created by
 
     MIDDLEWARE_CLASSES = (
         &quot;django.middleware.common.CommonMiddleware&quot;,
+        &quot;django.contrib.sessions.middleware.SessionMiddleware&quot;,
+        &quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;,
         &quot;django.middleware.doc.XViewMiddleware&quot;,
     )
 
@@ -95,13 +97,37 @@ Handles conditional GET operations. If the response has a ``ETag`` or
 Also removes the content from any response to a HEAD request and sets the
 ``Date`` and ``Content-Length`` response-headers.
 
-django.middleware.sessions.SessionMiddleware
---------------------------------------------
+django.contrib.sessions.middleware.SessionMiddleware
+----------------------------------------------------
 
 Enables session support. See the `session documentation`_.
 
 .. _`session documentation`: http://www.djangoproject.com/documentation/sessions/
 
+django.contrib.auth.middleware.AuthenticationMiddleware
+-------------------------------------------------------
+
+Adds the ``user`` attribute, representing the currently-logged-in user, to
+every incoming ``HttpRequest`` object. See `Authentication in Web requests`_.
+
+.. _Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
+
+django.middleware.transaction.TransactionMiddleware
+---------------------------------------------------
+
+Binds commit and rollback to the request/response phase. If a view function runs
+successfully, a commit is done. If it fails with an exception, a rollback is
+done.
+
+The order of this middleware in the stack is important: middleware modules
+running outside of it run with commit-on-save - the default Django behavior.
+Middleware modules running inside it (coming later in the stack) will be under
+the same transaction control as the view functions.
+
+See the `transaction management documentation`_.
+
+.. _`transaction management documentation`: http://www.djangoproject.com/documentation/transaction/
+
 Writing your own middleware
 ===========================
 
@@ -176,8 +202,8 @@ Guidelines
       to it.
 
     * Feel free to look at Django's available middleware for examples. The
-      default Django middleware classes are in ``django/middleware/`` in the
-      Django distribution.
+      core Django middleware classes are in ``django/middleware/`` in the
+      Django distribution. The session middleware is in ``django/contrib/sessions``.
 
     * If you write a middleware component that you think would be useful to
       other people, contribute to the community! Let us know, and we'll</diff>
      <filename>docs/middleware.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,465 +8,617 @@ model maps to a single database table.
 
 The basics:
 
-    * Each model is a Python class that subclasses ``django.core.meta.Model``.
+    * Each model is a Python class that subclasses ``django.db.models.Model``.
     * Each attribute of the model represents a database field.
-    * Model metadata (non-field information) goes in an inner class named ``META``.
+    * Model metadata (non-field information) goes in an inner class named
+      ``Meta``.
+    * Metadata used for Django's admin site goes into an inner class named
+      ``Admin``.
+    * With all of this, Django gives you an automatically-generated
+      database-access API, which is explained in the `Database API reference`_.
 
 A companion to this document is the `official repository of model examples`_.
 
-.. _`official repository of model examples`: http://www.djangoproject.com/documentation/models/
+.. _Database API reference: http://www.djangoproject.com/documentation/db_api/
+.. _official repository of model examples: http://www.djangoproject.com/documentation/models/
 
-Field objects
+Quick example
 =============
 
-The most important part of a model is the list of database fields it defines.
-Fields are defined by class attributes. Each class attribute in a model, aside
-from the optional inner ``class META``, should be an instance of a
-``meta.Field`` subclass.
+This example model defines a ``Person``, which has a ``first_name`` and
+``last_name``::
 
-In this example, there are two fields, ``first_name`` and ``last_name`` ::
+    from django.db import models
 
-    class Person(meta.Model):
-        first_name = meta.CharField(maxlength=30)
-        last_name = meta.CharField(maxlength=30)
+    class Person(models.Model):
+        first_name = models.CharField(maxlength=30)
+        last_name = models.CharField(maxlength=30)
 
-Django will use ``first_name`` and ``last_name`` as the database column names.
+``first_name`` and ``last_name`` are *fields* of the model. Each field is
+specified as a class attribute, and each attribute maps to a database column.
 
-Each field type, except for ``ForeignKey``, ``ManyToManyField`` and
-``OneToOneField``, takes an optional first positional argument -- a
-human-readable name. If the human-readable name isn't given, Django will
-automatically create the human-readable name by using the machine-readable
-name, converting underscores to spaces.
+The above ``Person`` model would create an SQL table like this::
 
-In this example, the human-readable name is ``&quot;Person's first name&quot;``::
+    CREATE TABLE myapp_person (
+        &quot;id&quot; serial NOT NULL PRIMARY KEY,
+        &quot;first_name&quot; varchar(30) NOT NULL,
+        &quot;last_name&quot; varchar(30) NOT NULL
+    );
 
-    first_name = meta.CharField(&quot;Person's first name&quot;, maxlength=30)
+Three technical notes:
 
-In this example, the human-readable name is ``&quot;first name&quot;``::
+    * The name of the table, ``myapp_person``, is automatically derived from
+      some model metadata but can be overridden. See _`Table names` below.
+    * An ``id`` field is added automatically, but this behavior can be
+      overriden. See _`Automatic primary key fields` below.
+    * The ``CREATE TABLE`` SQL in this example is formatted using PostgreSQL
+      syntax, but it's worth noting Django uses SQL tailored to the database
+      backend specified in your `settings file`_.
 
-    first_name = meta.CharField(maxlength=30)
+.. _settings file: http://www.djangoproject.com/documentation/settings/
 
-``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first
-argument to be a model class, so use the ``verbose_name`` keyword argument to
-specify the human-readable name::
+Fields
+======
 
-    poll = meta.ForeignKey(Poll, verbose_name=&quot;the related poll&quot;)
-    sites = meta.ManyToManyField(Site, verbose_name=&quot;list of sites&quot;)
-    place = meta.OneToOneField(Place, verbose_name=&quot;related place&quot;)
+The most important part of a model -- and the only required part of a model --
+is the list of database fields it defines. Fields are specified by class
+attributes.
 
-Convention is not to capitalize the first letter of the ``verbose_name``.
-Django will automatically capitalize the first letter where it needs to.
+Example::
 
-General field options
----------------------
+    class Musician(models.Model):
+        first_name = models.CharField(maxlength=50)
+        last_name = models.CharField(maxlength=50)
+        instrument = models.CharField(maxlength=100)
 
-The following arguments are available to all field types. All are optional.
+    class Album(models.Model):
+        artist = models.ForeignKey(Musician)
+        name = models.CharField(maxlength=100)
+        release_date = models.DateField()
+        num_stars = models.IntegerField()
 
-``null``
-    If ``True``, Django will store empty values as ``NULL`` in the database.
-    Default is ``False``.
+Field name restrictions
+-----------------------
 
-    Note that empty string values will always get stored as empty strings, not
-    as ``NULL`` -- so use ``null=True`` for non-string fields such as integers,
-    booleans and dates.
+Django places only two restrictions on model field names:
 
-    Avoid using ``null`` on string-based fields such as ``CharField`` and
-    ``TextField`` unless you have an excellent reason. If a string-based field
-    has ``null=True``, that means it has two possible values for &quot;no data&quot;:
-    ``NULL``, and the empty string. In most cases, it's redundant to have two
-    possible values for &quot;no data;&quot; Django convention is to use the empty
-    string, not ``NULL``.
+    1. A field name cannot be a Python reserved word, because that would result
+       in a Python syntax error. For example::
 
-``blank``
-    If ``True``, the field is allowed to be blank.
+           class Example(models.Model):
+               pass = models.IntegerField() # 'pass' is a reserved word!
 
-    Note that this is different than ``null``. ``null`` is purely
-    database-related, whereas ``blank`` is validation-related. If a field has
-    ``blank=True``, validation on Django's admin site will allow entry of an
-    empty value. If a field has ``blank=False``, the field will be required.
+    2. A field name cannot contain more than one underscore in a row, due to
+       the way Django's query lookup syntax works. For example::
 
-``choices``
-    A list of 2-tuples to use as choices for this field.
+           class Example(models.Model):
+               foo__bar = models.IntegerField() 'foo__bar' has two underscores!
 
-    If this is given, Django's admin will use a select box instead of the
-    standard text field and will limit choices to the choices given.
+These limitations can be worked around, though, because your field name doesn't
+necessarily have to match your database column name. See `db_column`_ below.
 
-    A choices list looks like this::
+SQL reserved words, such as ``join``, ``where`` or ``select`, *are* allowed as
+model field names, because Django escapes all database table names and column
+names in every underlying SQL query. It uses the quoting syntax of your
+particular database engine.
 
-        YEAR_IN_SCHOOL_CHOICES = (
-            ('FR', 'Freshman'),
-            ('SO', 'Sophomore'),
-            ('JR', 'Junior'),
-            ('SR', 'Senior'),
-            ('GR', 'Graduate'),
-        )
+Field types
+-----------
 
-    The first element in each tuple is the actual value to be stored. The
-    second element is the human-readable name for the option.
+Each field in your model should be an instance of the appropriate ``Field``
+class. Django uses the field class types to determine a few things:
 
-    Define the choices list **outside** of your model class, not inside it.
-    For example, this is not valid::
+    * The database column type (e.g. ``INTEGER``, ``VARCHAR``).
+    * The widget to use in Django's admin interface, if you care to use it
+      (e.g. ``&lt;input type=&quot;text&quot;&gt;``, ``&lt;select&gt;``).
+    * The minimal validation requirements, used in Django's admin and in
+      manipulators.
 
-        class Foo(meta.Model):
-            GENDER_CHOICES = (
-                ('M', 'Male'),
-                ('F', 'Female'),
-            )
-            gender = meta.CharField(maxlength=1, choices=GENDER_CHOICES)
+Here are all available field types:
 
-    But this is valid::
+``AutoField``
+~~~~~~~~~~~~~
 
-        GENDER_CHOICES = (
-            ('M', 'Male'),
-            ('F', 'Female'),
-        )
-        class Foo(meta.Model):
-            gender = meta.CharField(maxlength=1, choices=GENDER_CHOICES)
+An ``IntegerField`` that automatically increments according to available IDs.
+You usually won't need to use this directly; a primary key field will
+automatically be added to your model if you don't specify otherwise. See
+_`Automatic primary key fields`.
 
-``core``
-    For objects that are edited inline to a related object.
+``BooleanField``
+~~~~~~~~~~~~~~~~
 
-    In the Django admin, if all &quot;core&quot; fields in an inline-edited object are
-    cleared, the object will be deleted.
+A true/false field.
 
-    It is an error to have an inline-editable relation without at least one
-    ``core=True`` field.
+The admin represents this as a checkbox.
 
-``db_column``
-    The name of the database column to use for this field. If this isn't given,
-    Django will use the field's name.
+``CharField``
+~~~~~~~~~~~~~
 
-    If your database column name is an SQL reserved word, or contains
-    characters that aren't allowed in Python variable names -- notably, the
-    hyphen -- that's OK. Django quotes column and table names behind the
-    scenes.
+A string field, for small- to large-sized strings.
 
-``db_index``
-    If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
-    statement for this field.
+For large amounts of text, use ``TextField``.
 
-``default``
-    The default value for the field.
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-``editable``
-    If ``False``, the field will not be editable in the admin. Default is  ``True``.
+``CharField`` has an extra required argument, ``maxlength``, the maximum length
+(in characters) of the field. The maxlength is enforced at the database level
+and in Django's validation.
 
-``help_text``
-    Extra &quot;help&quot; text to be displayed under the field on the object's admin
-    form. It's useful for documentation even if your object doesn't have an
-    admin form.
+``CommaSeparatedIntegerField``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-``primary_key``
-    If ``True``, this field is the primary key for the model.
+A field of integers separated by commas. As in ``CharField``, the ``maxlength``
+argument is required.
 
-    If you don't specify ``primary_key=True`` for any fields in your model,
-    Django will automatically add this field::
+``DateField``
+~~~~~~~~~~~~~
 
-        id = meta.AutoField('ID', primary_key=True)
+A date field. Has a few extra optional arguments:
 
-    Thus, you don't need to set ``primary_key=True`` on any of your fields
-    unless you want to override the default primary-key behavior.
+    ======================  ===================================================
+    Argument                Description
+    ======================  ===================================================
+    ``auto_now``            Automatically set the field to now every time the
+                            object is saved. Useful for &quot;last-modified&quot;
+                            timestamps.
 
-    ``primary_key=True`` implies ``blank=False``, ``null=False`` and
-    ``unique=True``. Only one primary key is allowed on an object.
+    ``auto_now_add``        Automatically set the field to now when the object
+                            is first created. Useful for creation of
+                            timestamps.
+    ======================  ===================================================
 
-``radio_admin``
-    By default, Django's admin uses a select-box interface (&lt;select&gt;) for
-    fields that are ``ForeignKey`` or have ``choices`` set. If ``radio_admin``
-    is set to ``True``, Django will use a radio-button interface instead.
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` with a JavaScript
+calendar and a shortcut for &quot;Today.&quot;
 
-    Don't use this for a field unless it's a ``ForeignKey`` or has ``choices``
-    set.
+``DateTimeField``
+~~~~~~~~~~~~~~~~~
 
-``unique``
-    If ``True``, this field must be unique throughout the table.
+A date and time field. Takes the same extra options as ``DateField``.
 
-    This is enforced at the database level and at the Django admin-form level.
+The admin represents this as two ``&lt;input type=&quot;text&quot;&gt;`` fields, with
+JavaScript shortcuts.
 
-``unique_for_date``
-    Set this to the name of a ``DateField`` or ``DateTimeField`` to require
-    that this field be unique for the value of the date field.
+``EmailField``
+~~~~~~~~~~~~~~
 
-    For example, if you have a field ``title`` that has
-    ``unique_for_date=&quot;pub_date&quot;``, then Django wouldn't allow the entry of
-    two records with the same ``title`` and ``pub_date``.
+A ``CharField`` that checks that the value is a valid e-mail address.
+This doesn't accept ``maxlength``.
 
-    This is enforced at the Django admin-form level but not at the database level.
+``FileField``
+~~~~~~~~~~~~~
 
-``unique_for_month``
-    Like ``unique_for_date``, but requires the field to be unique with respect
-    to the month.
+A file-upload field.
 
-``unique_for_year``
-    Like ``unique_for_date`` and ``unique_for_month``.
+Has an extra required argument, ``upload_to``, a local filesystem path to
+which files should be upload. This path may contain `strftime formatting`_,
+which will be replaced by the date/time of the file upload (so that
+uploaded files don't fill up the given directory).
 
-``validator_list``
-    A list of extra validators to apply to the field. Each should be a callable
-    that takes the parameters ``field_data, all_data`` and raises
-    ``django.core.validators.ValidationError`` for errors. (See the
-    `validator docs`_.)
+The admin represents this as an ``&lt;input type=&quot;file&quot;&gt;`` (a file-upload widget).
 
-    Django comes with quite a few validators. They're in ``django.core.validators``.
+Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few
+steps:
 
-.. _validator docs: http://www.djangoproject.com/documentation/forms/#validators
+    1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the
+        full path to a directory where you'd like Django to store uploaded
+        files. (For performance, these files are not stored in the database.)
+        Define ``MEDIA_URL`` as the base public URL of that directory. Make
+        sure that this directory is writable by the Web server's user
+        account.
 
-Field types
------------
+    2. Add the ``FileField`` or ``ImageField`` to your model, making sure
+        to define the ``upload_to`` option to tell Django to which
+        subdirectory of ``MEDIA_ROOT`` it should upload files.
 
-Each field in your model should be an instance of the appropriate ``Field``
-class. Django uses the field class types to determine a few things:
+    3. All that will be stored in your database is a path to the file
+        (relative to ``MEDIA_ROOT``). You'll must likely want to use the
+        convenience ``get_&lt;fieldname&gt;_url`` function provided by Django. For
+        example, if your ``ImageField`` is called ``mug_shot``, you can get
+        the absolute URL to your image in a template with ``{{
+        object.get_mug_shot_url }}``.
 
-    * The database column type (e.g. ``INTEGER``, ``VARCHAR``).
-    * The widget to use in Django's admin (e.g. ``&lt;input type=&quot;text&quot;&gt;``, ``&lt;select&gt;``).
-    * The minimal validation requirements, used in Django's admin and in manipulators.
+.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
 
-Here are all available field types:
+``FilePathField``
+~~~~~~~~~~~~~~~~~
 
-``AutoField``
-    An ``IntegerField`` that automatically increments according to available
-    IDs. You usually won't need to use this directly; a primary key field will
-    automatically be added to your model if you don't specify otherwise. (See
-    ``primary_key`` in ``General field options`` above.)
+A field whose choices are limited to the filenames in a certain directory
+on the filesystem. Has three special arguments, of which the first is
+required:
 
-``BooleanField``
-    A true/false field.
+    ======================  ===================================================
+    Argument                Description
+    ======================  ===================================================
+    ``path``                Required. The absolute filesystem path to a
+                            directory from which this ``FilePathField`` should
+                            get its choices. Example: ``&quot;/home/images&quot;``.
 
-    The admin represents this as a checkbox.
+    ``match``               Optional. A regular expression, as a string, that
+                            ``FilePathField`` will use to filter filenames.
+                            Note that the regex will be applied to the
+                            base filename, not the full path. Example:
+                            ``&quot;foo.*\.txt^&quot;``, which will match a file called
+                            ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``.
 
-``CharField``
-    A string field, for small- to large-sized strings.
+    ``recursive``           Optional. Either ``True`` or ``False``. Default is
+                            ``False``. Specifies whether all subdirectories of
+                            ``path`` should be included.
+    ======================  ===================================================
 
-    For large amounts of text, use ``TextField``.
+Of course, these arguments can be used together.
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+The one potential gotcha is that ``match`` applies to the base filename,
+not the full path. So, this example::
 
-    ``CharField`` has an extra required argument, ``maxlength``, the maximum
-    length (in characters) of the field. The maxlength is enforced at the
-    database level and in Django's validation.
+    FilePathField(path=&quot;/home/images&quot;, match=&quot;foo.*&quot;, recursive=True)
 
-``CommaSeparatedIntegerField``
-    A field of integers separated by commas. As in ``CharField``, the
-    ``maxlength`` argument is required.
+...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif``
+because the ``match`` applies to the base filename (``foo.gif`` and
+``bar.gif``).
 
-``DateField``
-    A date field. Has a few extra optional arguments:
+``FloatField``
+~~~~~~~~~~~~~~
 
-        ======================  ===================================================
-        Argument                Description
-        ======================  ===================================================
-        ``auto_now``            Automatically set the field to now every time the
-                                object is saved. Useful for &quot;last-modified&quot;
-                                timestamps.
+A floating-point number. Has two **required** arguments:
 
-        ``auto_now_add``        Automatically set the field to now when the object
-                                is first created. Useful for creation of
-                                timestamps.
-        ======================  ===================================================
+    ======================  ===================================================
+    Argument                Description
+    ======================  ===================================================
+    ``max_digits``          The maximum number of digits allowed in the number.
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` with a JavaScript
-    calendar and a shortcut for &quot;Today.&quot;
+    ``decimal_places``      The number of decimal places to store with the
+                            number.
+    ======================  ===================================================
 
-``DateTimeField``
-    A date and time field. Takes the same extra options as ``DateField``.
+For example, to store numbers up to 999 with a resolution of 2 decimal places,
+you'd use::
 
-    The admin represents this as two ``&lt;input type=&quot;text&quot;&gt;`` fields, with
-    JavaScript shortcuts.
+    models.FloatField(..., max_digits=5, decimal_places=2)
 
-``EmailField``
-    A ``CharField`` that checks that the value is a valid e-mail address.
-    This doesn't accept ``maxlength``.
+And to store numbers up to approximately one billion with a resolution of 10
+decimal places::
 
-``FileField``
-    A file-upload field.
+    models.FloatField(..., max_digits=19, decimal_places=10)
 
-    Has an extra required argument, ``upload_to``, a local filesystem path to
-    which files should be upload. This path may contain `strftime formatting`_,
-    which will be replaced by the date/time of the file upload (so that
-    uploaded files don't fill up the given directory).
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-    The admin represents this as an ``&lt;input type=&quot;file&quot;&gt;`` (a file-upload widget).
+``ImageField``
+~~~~~~~~~~~~~~
 
-    Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few
-    steps:
+Like ``FileField``, but validates that the uploaded object is a valid
+image. Has two extra optional arguments, ``height_field`` and
+``width_field``, which, if set, will be auto-populated with the height and
+width of the image each time a model instance is saved.
 
-        1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the
-           full path to a directory where you'd like Django to store uploaded
-           files. (For performance, these files are not stored in the database.)
-           Define ``MEDIA_URL`` as the base public URL of that directory. Make
-           sure that this directory is writable by the Web server's user
-           account.
+Requires the `Python Imaging Library`_.
 
-        2. Add the ``FileField`` or ``ImageField`` to your model, making sure
-           to define the ``upload_to`` option to tell Django to which
-           subdirectory of ``MEDIA_ROOT`` it should upload files.
+.. _Python Imaging Library: http://www.pythonware.com/products/pil/
 
-        3. All that will be stored in your database is a path to the file
-           (relative to ``MEDIA_ROOT``). You'll must likely want to use the
-           convenience ``get_&lt;fieldname&gt;_url`` function provided by Django. For
-           example, if your ``ImageField`` is called ``mug_shot``, you can get
-           the absolute URL to your image in a template with ``{{
-           object.get_mug_shot_url }}``.
+``IntegerField``
+~~~~~~~~~~~~~~~~
 
-    .. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
+An integer.
 
-``FilePathField``
-    A field whose choices are limited to the filenames in a certain directory
-    on the filesystem. Has three special arguments, of which the first is
-    required:
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-        ======================  ===================================================
-        Argument                Description
-        ======================  ===================================================
-        ``path``                Required. The absolute filesystem path to a
-                                directory from which this ``FilePathField`` should
-                                get its choices. Example: ``&quot;/home/images&quot;``.
+``IPAddressField``
+~~~~~~~~~~~~~~~~~~
 
-        ``match``               Optional. A regular expression, as a string, that
-                                ``FilePathField`` will use to filter filenames.
-                                Note that the regex will be applied to the
-                                base filename, not the full path. Example:
-                                ``&quot;foo.*\.txt^&quot;``, which will match a file called
-                                ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``.
+An IP address, in string format (i.e. &quot;24.124.1.30&quot;).
 
-        ``recursive``           Optional. Either ``True`` or ``False``. Default is
-                                ``False``. Specifies whether all subdirectories of
-                                ``path`` should be included.
-        ======================  ===================================================
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-    Of course, these arguments can be used together.
+``NullBooleanField``
+~~~~~~~~~~~~~~~~~~~~
 
-    The one potential gotcha is that ``match`` applies to the base filename,
-    not the full path. So, this example::
+Like a ``BooleanField``, but allows ``NULL`` as one of the options.  Use this
+instead of a ``BooleanField`` with ``null=True``.
 
-        FilePathField(path=&quot;/home/images&quot;, match=&quot;foo.*&quot;, recursive=True)
+The admin represents this as a ``&lt;select&gt;`` box with &quot;Unknown&quot;, &quot;Yes&quot; and &quot;No&quot; choices.
 
-    ...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif``
-    because the ``match`` applies to the base filename (``foo.gif`` and
-    ``bar.gif``).
+``PhoneNumberField``
+~~~~~~~~~~~~~~~~~~~~
 
-``FloatField``
-    A floating-point number. Has two **required** arguments:
+A ``CharField`` that checks that the value is a valid U.S.A.-style phone
+number (in the format ``XXX-XXX-XXXX``).
 
-        ======================  ===================================================
-        Argument                Description
-        ======================  ===================================================
-        ``max_digits``          The maximum number of digits allowed in the number.
+``PositiveIntegerField``
+~~~~~~~~~~~~~~~~~~~~~~~~
 
-        ``decimal_places``      The number of decimal places to store with the
-                                number.
-        ======================  ===================================================
+Like an ``IntegerField``, but must be positive.
 
-    For example, to store numbers up to 999 with a resolution of 2 decimal places,
-    you'd use::
+``PositiveSmallIntegerField``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-        meta.FloatField(..., max_digits=5, decimal_places=2)
+Like a ``PositiveIntegerField``, but only allows values under a certain
+(database-dependent) point.
 
-    And to store numbers up to approximately one billion with a resolution of 10
-    decimal places::
+``SlugField``
+~~~~~~~~~~~~~
 
-        meta.FloatField(..., max_digits=19, decimal_places=10)
+&quot;Slug&quot; is a newspaper term. A slug is a short label for something,
+containing only letters, numbers, underscores or hyphens. They're generally
+used in URLs.
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+In the Django development version, you can specify ``maxlength``. If
+``maxlength`` is not specified, Django will use a default length of 50. In
+previous Django versions, there's no way to override the length of 50.
 
-``ImageField``
-    Like ``FileField``, but validates that the uploaded object is a valid
-    image. Has two extra optional arguments, ``height_field`` and
-    ``width_field``, which, if set, will be auto-populated with the height and
-    width of the image each time a model instance is saved.
+Implies ``db_index=True``.
 
-    Requires the `Python Imaging Library`_.
+Accepts an extra option, ``prepopulate_from``, which is a list of fields
+from which to auto-populate the slug, via JavaScript, in the object's admin
+form::
 
-    .. _Python Imaging Library: http://www.pythonware.com/products/pil/
+    models.SlugField(prepopulate_from=(&quot;pre_name&quot;, &quot;name&quot;))
 
-``IntegerField``
-    An integer.
+``prepopulate_from`` doesn't accept DateTimeFields.
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+The admin represents ``SlugField`` as an ``&lt;input type=&quot;text&quot;&gt;`` (a
+single-line input).
 
-``IPAddressField``
-    An IP address, in string format (i.e. &quot;24.124.1.30&quot;).
+``SmallIntegerField``
+~~~~~~~~~~~~~~~~~~~~~
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+Like an ``IntegerField``, but only allows values under a certain
+(database-dependent) point.
 
-``NullBooleanField``
-    Like a ``BooleanField``, but allows ``NULL`` as one of the options.  Use this
-    instead of a ``BooleanField`` with ``null=True``.
+``TextField``
+~~~~~~~~~~~~~
 
-    The admin represents this as a ``&lt;select&gt;`` box with &quot;Unknown&quot;, &quot;Yes&quot; and &quot;No&quot; choices.
+A large text field.
 
-``PhoneNumberField``
-    A ``CharField`` that checks that the value is a valid U.S.A.-style phone
-    number (in the format ``XXX-XXX-XXXX``).
+The admin represents this as a ``&lt;textarea&gt;`` (a multi-line input).
 
-``PositiveIntegerField``
-    Like an ``IntegerField``, but must be positive.
+``TimeField``
+~~~~~~~~~~~~~
 
-``PositiveSmallIntegerField``
-    Like a ``PositiveIntegerField``, but only allows values under a certain
-    (database-dependent) point.
+A time. Accepts the same auto-population options as ``DateField`` and
+``DateTimeField``.
 
-``SlugField``
-    &quot;Slug&quot; is a newspaper term. A slug is a short label for something,
-    containing only letters, numbers, underscores or hyphens. They're generally
-    used in URLs.
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` with some
+JavaScript shortcuts.
 
-    In the Django development version, you can specify ``maxlength``. If
-    ``maxlength`` is not specified, Django will use a default length of 50. In
-    previous Django versions, there's no way to override the length of 50.
+``URLField``
+~~~~~~~~~~~~
 
-    Implies ``db_index=True``.
+A field for a URL. If the ``verify_exists`` option is ``True`` (default),
+the URL given will be checked for existence (i.e., the URL actually loads
+and doesn't give a 404 response).
 
-    Accepts an extra option, ``prepopulate_from``, which is a list of fields
-    from which to auto-populate the slug, via JavaScript, in the object's admin
-    form::
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-        meta.SlugField(prepopulate_from=(&quot;pre_name&quot;, &quot;name&quot;))
+``USStateField``
+~~~~~~~~~~~~~~~~
 
-    ``prepopulate_from`` doesn't accept DateTimeFields.
+A two-letter U.S. state abbreviation.
 
-    The admin represents ``SlugField`` as an ``&lt;input type=&quot;text&quot;&gt;`` (a
-    single-line input).
+The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
 
-``SmallIntegerField``
-    Like an ``IntegerField``, but only allows values under a certain
-    (database-dependent) point.
+``XMLField``
+~~~~~~~~~~~~
 
-``TextField``
-    A large text field.
+A ``TextField`` that checks that the value is valid XML that matches a
+given schema. Takes one required argument, ``schema_path``, which is the
+filesystem path to a RelaxNG_ schema against which to validate the field.
 
-    The admin represents this as a ``&lt;textarea&gt;`` (a multi-line input).
+.. _RelaxNG: http://www.relaxng.org/
 
-``TimeField``
-    A time. Accepts the same auto-population options as ``DateField`` and
-    ``DateTimeField``.
+Field options
+-------------
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` with some
-    JavaScript shortcuts.
+The following arguments are available to all field types. All are optional.
 
-``URLField``
-    A field for a URL. If the ``verify_exists`` option is ``True`` (default),
-    the URL given will be checked for existence (i.e., the URL actually loads
-    and doesn't give a 404 response).
+``null``
+~~~~~~~~
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+If ``True``, Django will store empty values as ``NULL`` in the database.
+Default is ``False``.
 
-``USStateField``
-    A two-letter U.S. state abbreviation.
+Note that empty string values will always get stored as empty strings, not
+as ``NULL`` -- so use ``null=True`` for non-string fields such as integers,
+booleans and dates.
 
-    The admin represents this as an ``&lt;input type=&quot;text&quot;&gt;`` (a single-line input).
+Avoid using ``null`` on string-based fields such as ``CharField`` and
+``TextField`` unless you have an excellent reason. If a string-based field
+has ``null=True``, that means it has two possible values for &quot;no data&quot;:
+``NULL``, and the empty string. In most cases, it's redundant to have two
+possible values for &quot;no data;&quot; Django convention is to use the empty
+string, not ``NULL``.
 
-``XMLField``
-    A ``TextField`` that checks that the value is valid XML that matches a
-    given schema. Takes one required argument, ``schema_path``, which is the
-    filesystem path to a RelaxNG_ schema against which to validate the field.
+``blank``
+~~~~~~~~~
+
+If ``True``, the field is allowed to be blank.
+
+Note that this is different than ``null``. ``null`` is purely
+database-related, whereas ``blank`` is validation-related. If a field has
+``blank=True``, validation on Django's admin site will allow entry of an
+empty value. If a field has ``blank=False``, the field will be required.
+
+``choices``
+~~~~~~~~~~~
+
+A list of 2-tuples to use as choices for this field.
+
+If this is given, Django's admin will use a select box instead of the
+standard text field and will limit choices to the choices given.
 
-    .. _RelaxNG: http://www.relaxng.org/
+A choices list looks like this::
+
+    YEAR_IN_SCHOOL_CHOICES = (
+        ('FR', 'Freshman'),
+        ('SO', 'Sophomore'),
+        ('JR', 'Junior'),
+        ('SR', 'Senior'),
+        ('GR', 'Graduate'),
+    )
+
+The first element in each tuple is the actual value to be stored. The
+second element is the human-readable name for the option.
+
+The choices list can be defined either as part of your model class::
+
+    class Foo(models.Model):
+        GENDER_CHOICES = (
+            ('M', 'Male'),
+            ('F', 'Female'),
+        )
+        gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
+
+or outside your model class altogether::
+
+    GENDER_CHOICES = (
+        ('M', 'Male'),
+        ('F', 'Female'),
+    )
+    class Foo(models.Model):
+        gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
+
+``core``
+~~~~~~~~
+
+For objects that are edited inline to a related object.
+
+In the Django admin, if all &quot;core&quot; fields in an inline-edited object are
+cleared, the object will be deleted.
+
+It is an error to have an inline-editable relation without at least one
+``core=True`` field.
+
+``db_column``
+~~~~~~~~~~~~~
+
+The name of the database column to use for this field. If this isn't given,
+Django will use the field's name.
+
+If your database column name is an SQL reserved word, or contains
+characters that aren't allowed in Python variable names -- notably, the
+hyphen -- that's OK. Django quotes column and table names behind the
+scenes.
+
+``db_index``
+~~~~~~~~~~~~
+
+If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
+statement for this field.
+
+``default``
+~~~~~~~~~~~
+
+The default value for the field.
+
+``editable``
+~~~~~~~~~~~~
+
+If ``False``, the field will not be editable in the admin. Default is  ``True``.
+
+``help_text``
+~~~~~~~~~~~~~
+
+Extra &quot;help&quot; text to be displayed under the field on the object's admin
+form. It's useful for documentation even if your object doesn't have an
+admin form.
+
+``primary_key``
+~~~~~~~~~~~~~~~
+
+If ``True``, this field is the primary key for the model.
+
+If you don't specify ``primary_key=True`` for any fields in your model,
+Django will automatically add this field::
+
+    id = models.AutoField('ID', primary_key=True)
+
+Thus, you don't need to set ``primary_key=True`` on any of your fields
+unless you want to override the default primary-key behavior.
+
+``primary_key=True`` implies ``blank=False``, ``null=False`` and
+``unique=True``. Only one primary key is allowed on an object.
+
+``radio_admin``
+~~~~~~~~~~~~~~~
+
+By default, Django's admin uses a select-box interface (&lt;select&gt;) for
+fields that are ``ForeignKey`` or have ``choices`` set. If ``radio_admin``
+is set to ``True``, Django will use a radio-button interface instead.
+
+Don't use this for a field unless it's a ``ForeignKey`` or has ``choices``
+set.
+
+``unique``
+~~~~~~~~~~
+
+If ``True``, this field must be unique throughout the table.
+
+This is enforced at the database level and at the Django admin-form level.
+
+``unique_for_date``
+~~~~~~~~~~~~~~~~~~~
+
+Set this to the name of a ``DateField`` or ``DateTimeField`` to require
+that this field be unique for the value of the date field.
+
+For example, if you have a field ``title`` that has
+``unique_for_date=&quot;pub_date&quot;``, then Django wouldn't allow the entry of
+two records with the same ``title`` and ``pub_date``.
+
+This is enforced at the Django admin-form level but not at the database level.
+
+``unique_for_month``
+~~~~~~~~~~~~~~~~~~~~
+
+Like ``unique_for_date``, but requires the field to be unique with respect
+to the month.
+
+``unique_for_year``
+~~~~~~~~~~~~~~~~~~~
+
+Like ``unique_for_date`` and ``unique_for_month``.
+
+``validator_list``
+~~~~~~~~~~~~~~~~~~
+
+A list of extra validators to apply to the field. Each should be a callable
+that takes the parameters ``field_data, all_data`` and raises
+``django.core.validators.ValidationError`` for errors. (See the
+`validator docs`_.)
+
+Django comes with quite a few validators. They're in ``django.core.validators``.
+
+.. _validator docs: http://www.djangoproject.com/documentation/forms/#validators
+
+Verbose field names
+-------------------
+
+Each field type, except for ``ForeignKey``, ``ManyToManyField`` and
+``OneToOneField``, takes an optional first positional argument -- a
+verbose name. If the verbose name isn't given, Django will automatically create
+it using the field's attribute name, converting underscores to spaces.
+
+In this example, the verbose name is ``&quot;Person's first name&quot;``::
+
+    first_name = models.CharField(&quot;Person's first name&quot;, maxlength=30)
+
+In this example, the verbose name is ``&quot;first name&quot;``::
+
+    first_name = models.CharField(maxlength=30)
+
+``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first
+argument to be a model class, so use the ``verbose_name`` keyword argument::
+
+    poll = models.ForeignKey(Poll, verbose_name=&quot;the related poll&quot;)
+    sites = models.ManyToManyField(Site, verbose_name=&quot;list of sites&quot;)
+    place = models.OneToOneField(Place, verbose_name=&quot;related place&quot;)
+
+Convention is not to capitalize the first letter of the ``verbose_name``.
+Django will automatically capitalize the first letter where it needs to.
 
 Relationships
 -------------
 
 Clearly, the power of relational databases lies in relating tables to each
-other. Django offers ways to define the most common types of database
+other. Django offers ways to define the three most common types of database
 relationships: Many-to-one, many-to-many and one-to-one.
 
 Many-to-one relationships
@@ -479,23 +631,34 @@ any other ``Field`` type: by including it as a class attribute of your model.
 related.
 
 For example, if a ``Place`` model is in a ``City`` -- that is, a ``City``
-contains multiple places but each ``Place`` is only in one ``City`` -- here's
-how you'd represent that::
+contains multiple places but each ``Place`` is only in one ``City`` -- use the
+following definitions::
 
-    class City(meta.Model):
+    class City(models.Model):
         # ...
 
-    class Place(meta.Model):
+    class Place(models.Model):
         # ...
-        city = meta.ForeignKey(City)
+        city = models.ForeignKey(City)
 
 To create a recursive relationship -- an object that has a many-to-one
-relationship with itself -- use ``meta.ForeignKey(&quot;self&quot;)``.
+relationship with itself -- use ``models.ForeignKey('self')``.
+
+If you need to create a relationship on a model that has not yet been defined,
+you can use the name of the model, rather than the model object itself::
+
+    class Place(models.Model):
+        # ...
+        city = models.ForeignKey(&quot;City&quot;)
+
+    class City(models.Model):
+        # ...
 
 The name of a ``ForeignKey`` (``city`` in the example above) generally should
-be the name of the model, singular. Behind the scenes, Django appends &quot;_id&quot; to
-the field name to create its database column name. But your code should never
-have to deal with the database column name, unless you write custom SQL.
+be the name of the model, in singular form. Behind the scenes, Django appends
+&quot;_id&quot; to the field name to create its database column name. However, your code
+should never have to deal with the database column name, unless you write
+custom SQL.
 
 See the `Many-to-one relationship model example`_ for a full example.
 
@@ -510,7 +673,7 @@ relationship should work. All are optional:
     ``edit_inline``          If not ``False``, this related object is edited
                              &quot;inline&quot; on the related object's page. This means
                              that the object will not have its own admin
-                             interface. Use either ``meta.TABULAR`` or ``meta.STACKED``,
+                             interface. Use either ``models.TABULAR`` or ``models.STACKED``,
                              which, respectively, designate whether the inline-editable
                              objects are displayed as a table or as a &quot;stack&quot; of
                              fieldsets.
@@ -518,10 +681,10 @@ relationship should work. All are optional:
     ``limit_choices_to``     A dictionary of lookup arguments and values (see
                              the `Database API reference`_) that limit the
                              available admin choices for this object. Use this
-                             with ``meta.LazyDate`` to limit choices of objects
+                             with ``models.LazyDate`` to limit choices of objects
                              by date. For example::
 
-                                limit_choices_to = {'pub_date__lte' : meta.LazyDate()}
+                                limit_choices_to = {'pub_date__lte' : models.LazyDate()}
 
                              only allows the choice of related objects with a
                              ``pub_date`` before the current date/time to be
@@ -565,20 +728,18 @@ relationship should work. All are optional:
                              object back to this one.  For example, when if
                              ``Topping`` has this field::
 
-                                    meta.ForeignKey(Pizza)
+                                    models.ForeignKey(Pizza)
 
-                             the ``related_name`` will be &quot;topping&quot; (taken from
+                             the ``related_name`` will be &quot;topping_set&quot; (taken from
                              the class name), which will in turn give ``Pizza``
-                             the methods ``get_topping_list()`` and
-                             ``get_topping_count()``.
+                             a ``topping_set`` Object Set Descriptor.
 
                              If you instead were to use::
 
-                                    meta.ForeignKey(Pizza, related_name=&quot;munchie&quot;)
+                                    models.ForeignKey(Pizza, related_name=&quot;munchies&quot;)
 
-                             then the methods would be called
-                             ``get_munchie_list()``, ``get_munchie_count()``,
-                             etc.
+                             then the Object Set Descriptor on ``Topping`` would
+                             be called ``munchies``.
 
                              This is only really useful when you have a single
                              object that relates to the same object more than
@@ -587,12 +748,12 @@ relationship should work. All are optional:
                              fields, to make sure that the ``Category`` objects
                              have the correct methods, you'd use fields like::
 
-                                    meta.ForeignKey(Category, related_name=&quot;primary_story&quot;)
-                                    meta.ForeignKey(Category, related_name=&quot;secondary_story&quot;)
+                                    models.ForeignKey(Category, related_name=&quot;primary_stories&quot;)
+                                    models.ForeignKey(Category, related_name=&quot;secondary_stories&quot;)
 
-                             ...which would give the ``Category`` objects
-                             methods named ``get_primary_story_list()`` and
-                             ``get_secondary_story_list()``.
+                             ...which would give ``Category`` objects two Object Set
+                             descriptors - one called ``primary_stories`` and one
+                             called ``secondary_stories``.
 
     ``to_field``             The field on the related object that the relation
                              is to. By default, Django uses the primary key of
@@ -615,15 +776,19 @@ For example, if a ``Pizza`` has multiple ``Topping`` objects -- that is, a
 ``Topping`` can be on multiple pizzas and each ``Pizza`` has multiple toppings --
 here's how you'd represent that::
 
-    class Topping(meta.Model):
+    class Topping(models.Model):
         # ...
 
-    class Pizza(meta.Model):
+    class Pizza(models.Model):
         # ...
-        toppings = meta.ManyToManyField(Topping)
+        toppings = models.ManyToManyField(Topping)
 
-The name of a ``ManyToManyField`` (``toppings`` in the example above) generally
-should be the name of the model, plural.
+As with ``ForeignKey``, a relationship to self can be defined by using the
+string ``&quot;self&quot;`` instead of the model name; references to as-yet undefined
+models can be made by using a string containing the model name.
+
+The name of a ``ManyToManyField`` (``toppings`` in the example above) should
+generally be a plural describing the set of related model objects.
 
 Behind the scenes, Django creates an intermediary join table to represent the
 many-to-many relationship.
@@ -654,7 +819,7 @@ the relationship should work. All are optional:
     ``filter_interface``     Use a nifty unobtrusive Javascript &quot;filter&quot; interface
                              instead of the usability-challenged ``&lt;select multiple&gt;``
                              in the admin form for this object. The value should be
-                             ``meta.HORIZONTAL`` or ``meta.VERTICAL`` (i.e.
+                             ``models.HORIZONTAL`` or ``models.VERTICAL`` (i.e.
                              should the interface be stacked horizontally or
                              vertically).
 
@@ -667,6 +832,24 @@ the relationship should work. All are optional:
                              version of the class being linked to.  Use the singular
                              parameter to change this, which is if you want one model to
                              have multiple ``ManyToMany`` relationships to another model.
+
+    ``symmetrical``          Only used in the definition of ManyToManyFields on self.
+                             Consider the following model:
+
+                             class Person(models.Model):
+                                 friends = models.ManyToManyField(&quot;self&quot;)
+
+                             When Django processes this model, it identifies that it has
+                             a ManyToManyField on itself, and as a result, it doesn't add
+                             a ``person_set`` attribute to the Person class. Instead, the
+                             ManyToManyField is assumed to be symmetrical - that is, if
+                             I am your friend, then you are my friend.
+
+                             If you do not want symmetry in ManyToMany relationships with
+                             self, set ``symmetrical`` to False. This will force Django to
+                             add the descriptor for the reverse relationship, allow
+                             ManyToMany relationships to be non-symmetrical.
+
     =======================  ============================================================
 
 One-to-one relationships
@@ -689,171 +872,178 @@ repeating yourself and replicating those fields in the ``Restaurant`` model, you
 could make ``Restaurant`` have a ``OneToOneField`` to ``Place`` (because a
 restaurant &quot;is-a&quot; place).
 
-This ``OneToOneField`` will actually replace the primary key ``id`` field
-(since one-to-one relations share the same primary key), and has a few
-differences in the admin interface:
-
-    * No ``Place`` selection interface is displayed on ``Restaurant`` pages.
-      There will be one (and only one) ``Restaurant`` for each ``Place``.
+As with ``ForeignKey``, a relationship to self can be defined by using the
+string ``&quot;self&quot;`` instead of the model name; references to as-yet undefined
+models can be made by using a string containing the model name.
 
-    * On the ``Restaurant`` change list, every ``Place`` -- whether it has an
-      associated ``Restaurant`` or not -- will be displayed. Adding a
-      ``Restaurant`` to a ``Place`` just means filling out the required
-      ``Restaurant`` fields.
+This ``OneToOneField`` will actually replace the primary key ``id`` field
+(since one-to-one relations share the same primary key), and will be displayed
+as a read-only field when you edit an object in the admin interface:
 
 See the `One-to-one relationship model example`_ for a full example.
 
 .. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/
 
-META options
+Meta options
 ============
 
-Give your model metadata by using an inner ``&quot;class META&quot;``, like so::
+Give your model metadata by using an inner ``class Meta``, like so::
 
-    class Foo(meta.Model):
-        bar = meta.CharField(maxlength=30)
-        # ...
-        class META:
-            admin = meta.Admin()
-            # ...
+    class Foo(models.Model):
+        bar = models.CharField(maxlength=30)
 
-Model metadata is &quot;anything that's not a field&quot; -- ordering options, admin
-options, etc.
+        class Meta:
+            # ...
 
-Here's a list of all possible ``META`` options. No options are required. Adding
-``class META`` to a model is completely optional.
+Model metadata is &quot;anything that's not a field&quot;, such as ordering options, etc.
 
-``admin``
-    A ``meta.Admin`` object; see `Admin options`_. If this field is given, the
-    object will have an admin interface. If it isn't given, the object won't
-    have one.
+Here's a list of all possible ``Meta`` options. No options are required. Adding
+``class Meta`` to a model is completely optional.
 
 ``db_table``
-    The name of the database table to use for the module::
+------------
 
-        db_table = &quot;pizza_orders&quot;
+The name of the database table to use for the module::
 
-    If this isn't given, Django will use ``app_label + '_' + module_name``.
+    db_table = &quot;pizza_orders&quot;
 
-    If your database table name is an SQL reserved word, or contains characters
-    that aren't allowed in Python variable names -- notably, the hyphen --
-    that's OK. Django quotes column and table names behind the scenes.
+If this isn't given, Django will use ``app_label + '_' + model_class_name``.
 
-``exceptions``
-    Names of extra exception subclasses to include in the generated module.
-    These exceptions are available from instance methods and from module-level
-    methods::
-
-        exceptions = (&quot;DisgustingToppingsException&quot;, &quot;BurntCrust&quot;)
+If your database table name is an SQL reserved word, or contains characters
+that aren't allowed in Python variable names -- notably, the hyphen --
+that's OK. Django quotes column and table names behind the scenes.
 
 ``get_latest_by``
-    The name of a ``DateField`` or ``DateTimeField``. If given, the module will
-    have a ``get_latest()`` function that fetches the &quot;latest&quot; object according
-    to that field::
-
-        get_latest_by = &quot;order_date&quot;
-
-    See `Getting the &quot;latest&quot; object`_ for a full example.
-
-    .. _Getting the &quot;latest&quot; object: http://www.djangoproject.com/documentation/models/get_latest/
+-----------------
 
-``module_constants``
-    A dictionary of names/values to use as extra module-level constants::
+The name of a ``DateField`` or ``DateTimeField``. If given, the module will
+have a ``get_latest()`` function that fetches the &quot;latest&quot; object according
+to that field::
 
-        module_constants = {
-            'MEAT_TYPE_PEPPERONI' : 1,
-            'MEAT_TYPE_SAUSAGE' : 2,
-        }
+    get_latest_by = &quot;order_date&quot;
 
-``module_name``
-    The name of the module::
+See `Getting the &quot;latest&quot; object`_ for a full example.
 
-        module_name = &quot;pizza_orders&quot;
-
-    If this isn't given, Django will use a lowercased version of the class
-    name, plus ``&quot;s&quot;``. This &quot;poor man's pluralization&quot; is intentional: Any
-    other level of magic pluralization would get confusing.
+.. _Getting the &quot;latest&quot; object: http://www.djangoproject.com/documentation/models/get_latest/
 
 ``order_with_respect_to``
-    Marks this object as &quot;orderable&quot; with respect to the given field. This is
-    almost always used with related objects to allow them to be ordered with
-    respect to a parent object. For example, if a ``PizzaToppping`` relates to
-    a ``Pizza`` object, you might use::
+-------------------------
+
+Marks this object as &quot;orderable&quot; with respect to the given field. This is
+almost always used with related objects to allow them to be ordered with
+respect to a parent object. For example, if a ``PizzaToppping`` relates to
+a ``Pizza`` object, you might use::
 
-        order_with_respect_to = 'pizza'
+    order_with_respect_to = 'pizza'
 
-    to allow the toppings to be ordered with respect to the associated pizza.
+...to allow the toppings to be ordered with respect to the associated pizza.
 
 ``ordering``
-    The default ordering for the object, for use by ``get_list`` and the admin::
+------------
+
+The default ordering for the object, for use when obtaining lists of objects::
 
-        ordering = ['-order_date']
+    ordering = ['-order_date']
 
-    This is a tuple or list of strings. Each string is a field name with an
-    optional &quot;-&quot; prefix, which indicates descending order. Fields without a
-    leading &quot;-&quot; will be ordered ascending. Use the string &quot;?&quot; to order randomly.
+This is a tuple or list of strings. Each string is a field name with an
+optional &quot;-&quot; prefix, which indicates descending order. Fields without a
+leading &quot;-&quot; will be ordered ascending. Use the string &quot;?&quot; to order randomly.
 
-    For example, to order by a ``pub_date`` field ascending, use this::
+For example, to order by a ``pub_date`` field ascending, use this::
 
-        ordering = ['pub_date']
+    ordering = ['pub_date']
 
-    To order by ``pub_date`` descending, use this::
+To order by ``pub_date`` descending, use this::
 
-        ordering = ['-pub_date']
+    ordering = ['-pub_date']
 
-    To order by ``pub_date`` descending, then by ``author`` ascending, use this::
+To order by ``pub_date`` descending, then by ``author`` ascending, use this::
 
-        ordering = ['-pub_date', 'author']
+    ordering = ['-pub_date', 'author']
 
-    See `Specifying ordering`_ for more examples.
+See `Specifying ordering`_ for more examples.
 
-    Note that, regardless of how many fields are in ``ordering``, the admin
-    site uses only the first field.
+Note that, regardless of how many fields are in ``ordering``, the admin
+site uses only the first field.
 
-    .. _Specifying ordering: http://www.djangoproject.com/documentation/models/ordering/
+.. _Specifying ordering: http://www.djangoproject.com/documentation/models/ordering/
 
 ``permissions``
-    Extra permissions to enter into the permissions table when creating this
-    object. Add, delete and change permissions are automatically created for
-    each object that has ``admin`` set. This example specifies an extra
-    permission, ``can_deliver_pizzas``::
+---------------
 
-        permissions = ((&quot;can_deliver_pizzas&quot;, &quot;Can deliver pizzas&quot;),)
+Extra permissions to enter into the permissions table when creating this
+object. Add, delete and change permissions are automatically created for
+each object that has ``admin`` set. This example specifies an extra
+permission, ``can_deliver_pizzas``::
 
-    This is a list or tuple of 2-tuples in the format
-    ``(permission_code, human_readable_permission_name)``.
+    permissions = ((&quot;can_deliver_pizzas&quot;, &quot;Can deliver pizzas&quot;),)
+
+This is a list or tuple of 2-tuples in the format
+``(permission_code, human_readable_permission_name)``.
 
 ``unique_together``
-    Sets of field names that, taken together, must be unique::
+-------------------
 
-        unique_together = ((&quot;driver&quot;, &quot;restaurant&quot;),)
+Sets of field names that, taken together, must be unique::
 
-    This is a list of lists of fields that must be unique when considered
-    together. It's used in the Django admin and is enforced at the database
-    level (i.e., the appropriate ``UNIQUE`` statements are included in the
-    ``CREATE TABLE`` statement).
+    unique_together = ((&quot;driver&quot;, &quot;restaurant&quot;),)
+
+This is a list of lists of fields that must be unique when considered
+together. It's used in the Django admin and is enforced at the database
+level (i.e., the appropriate ``UNIQUE`` statements are included in the
+``CREATE TABLE`` statement).
 
 ``verbose_name``
-    A human-readable name for the object, singular::
+----------------
+
+A human-readable name for the object, singular::
 
-        verbose_name = &quot;pizza&quot;
+    verbose_name = &quot;pizza&quot;
 
-    If this isn't given, Django will use a munged version of the class name:
-    ``CamelCase`` becomes ``camel case``.
+If this isn't given, Django will use a munged version of the class name:
+``CamelCase`` becomes ``camel case``.
 
 ``verbose_name_plural``
-    The plural name for the object::
+-----------------------
+
+The plural name for the object::
+
+    verbose_name_plural = &quot;stories&quot;
 
-        verbose_name_plural = &quot;stories&quot;
+If this isn't given, Django will use ``verbose_name + &quot;s&quot;``.
+
+
+
+========================================
+THE REST OF THIS HAS NOT YET BEEN EDITED
+========================================
+
+
+
+Table names
+===========
+
+Automatic primary key fields
+============================
 
-    If this isn't given, Django will use ``verbose_name + &quot;s&quot;``.
 
 Admin options
 =============
 
-The ``admin`` field in the model tells Django how to construct the admin
-interface for the object.  The field is an instance of the ``meta.Admin``
-object, which takes the following parameters. All are optional.
+If you want your model to be visible to the automatic Administration
+system, your model must have an inner ``&quot;class Admin&quot;``, like so::
+
+    class Foo(models.Model):
+        bar = models.CharField(maxlength=30)
+        # ...
+        class Admin:
+            # ...
+
+The Admin class gives instructions to Django on how to display the Model
+to the Administration system.
+
+Here's a list of all possible ``Admin`` options. No options are required. Adding
+``class Admin`` to a model is completely optional.
 
 ``date_hierarchy``
     To allow filtering of objects in the admin by date, set ``date_hierarchy``
@@ -885,24 +1075,31 @@ object, which takes the following parameters. All are optional.
             &quot;click to expand&quot; link.  Fieldsets with the ``wide`` style will be
             given extra horizontal space.
 
+        ``description``
+            Optional extra text to be displayed at the top of each fieldset,
+            underneath the heading of the fieldset.  It is used verbatim,
+            so you can use any HTML and you must escape any special HTML
+            characters (such as ampersand) yourself.
+
     For example (taken from the ``django.contrib.flatpages`` model)::
 
-        fields = (
-            (None, {
-                'fields': ('url', 'title', 'content', 'sites')
-            }),
-            ('Advanced options', {
-                'classes': 'collapse',
-                'fields' : ('enable_comments', 'registration_required', 'template_name')
-            }),
-        ),
+        class Admin:
+            ...
+            fields = (
+                (None, {
+                    'fields': ('url', 'title', 'content', 'sites')
+                }),
+                ('Advanced options', {
+                    'classes': 'collapse',
+                    'fields' : ('enable_comments', 'registration_required', 'template_name')
+                }),
+            )
 
     results in an admin that looks like:
 
         .. image:: http://media.djangoproject.com/img/doc/flatfiles_admin.png
 
-    If ``fields`` isn't given but a model does define ``admin`` as a
-    ``meta.Admin`` object, Django will default to displaying each field that
+    If ``fields`` isn't given Django will default to displaying each field that
     isn't an ``AutoField`` and has ``editable=True``, in a single fieldset, in
     the same order as the fields are defined in the model.
 
@@ -931,9 +1128,9 @@ object, which takes the following parameters. All are optional.
           ``short_description`` function attribute, for use as the header for
           the field.
 
-        * Use the string ``&quot;__repr__&quot;`` to output the representation of the
-          object, according to your model's ``__repr__()`` function. If you
-          don't define ``list_display``, Django will use the ``__repr__`` by
+        * Use the string ``&quot;__str__&quot;`` to output the representation of the
+          object, according to your model's ``__str__()`` function. If you
+          don't define ``list_display``, Django will use the ``__str__`` by
           default.
 
     See the example below.
@@ -945,8 +1142,10 @@ object, which takes the following parameters. All are optional.
     Here's an example of how ``list_display`` and ``list_filter`` work (taken
     from the ``auth.user`` model)::
 
-        list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff'),
-        list_filter = ('is_staff', 'is_superuser'),
+        class Admin:
+            #...
+            list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
+            list_filter = ('is_staff', 'is_superuser')
 
     The above code results in an admin that looks like this:
 
@@ -963,7 +1162,7 @@ object, which takes the following parameters. All are optional.
     if one of the ``list_display`` fields is a ``ForeignKey``.
 
 ``ordering``
-    A list or tuple (see the `META options`_, above) that gives a
+    A list or tuple (see the `Meta options`_, above) that gives a
     different ordering for the admin change list. If this isn't given, the
     model's default ordering will be used.
 
@@ -985,6 +1184,84 @@ object, which takes the following parameters. All are optional.
     obviously, be some kind of text field, such as ``CharField`` or
     ``TextField``.
 
+Managers
+========
+
+The Manager is the interface through which database query operations
+are provided to Django applications. At least one Manager exists for
+every model in a Django application.
+
+By default, Django will add a Manager with the name of ``objects`` to
+every Django model. However, if you wish to use ``objects`` as a field
+name, or if you wish to use a name other than ``objects`` for the Manager,
+you can rename the Manager on a per-model basis. To rename the Manager
+for a given class, define a class attribute of type models.Manager()
+on that model. For example::
+
+    from django.db import models
+
+    class Person(models.Model):
+        #...
+        people = models.Manager()
+
+In this example, ``Person.objects.all()`` will generate an error, but
+``Person.people.all()`` will provide a list of all ``Person`` objects.
+
+Managers can also be customized. This is achieved by extending the
+base Manager class, and instantiating the new Manager on your model.
+There are two reasons that you may want to customize a Manager: firstly,
+to add utility methods to the Manager, and secondly, to modify the
+initial Query Set provided by the Manager.
+
+To modify the initial Query Set provided by a Manager, override the
+``get_query_set()`` method to return a Query Set with the properties
+you require. For example::
+
+    class PersonManager(models.Manager):
+        # Add some custom behavior to the Manager
+        def move_house(self):
+            # Some logic to help a person move house
+
+        # Modify the initial Query Set provided by the manager
+        def get_query_set(self):
+            return super(Manager, self).get_query_set().filter(name__startswith=&quot;Fred&quot;)
+
+    class Person(models.Model):
+        #...
+        objects = PersonManager()
+
+In this example, ``Person.objects.all()`` will only return people whose name starts
+with &quot;Fred&quot;; ``Person.objects.move_house()`` will also be available.
+
+If required, you can add multiple Managers to a model. Every Manager attribute
+added to a model can be accessed and used as a manager. This is an easy way
+to define common filters types for your models. For example, the model::
+
+    class MaleManager(models.Manager):
+        def get_query_set(self):
+            return super(Manager, self).get_query_set().filter(sex='M')
+
+    class FemaleManager(models.Manager):
+        def get_query_set(self):
+            return super(Manager, self).get_query_set().filter(sex='F')
+
+    class Person(models.Model):
+        #...
+        people = models.Manager()
+        men = MaleManager()
+        women = FemaleManager()
+
+... will allow end users to request ``Person.men.all()``, ``Person.women.all()``,
+and ``Person.people.all()``, yielding predictable results.
+
+If you are going to install a customized Manager, be warned that the first
+Manager that Django encounters in a model definition has special status.
+Django interprets the first Manager defined in a class as the default Manager.
+Certain operations use the default Manager to obtain lists of objects, so it
+is generally a good idea for the first Manager to be relatively unfiltered.
+In the last example, ``people`` is defined first - so the default Manager
+will include everyone.
+
 Model methods
 =============
 
@@ -992,11 +1269,11 @@ There are a number of methods you can define on model objects to control the
 object's behavior.  First, any methods you define will be available as methods
 of object instances. For example::
 
-    class Pizza(meta.Model):
+    class Pizza(models.Model):
         # ...
 
         def is_disgusting(self):
-            return &quot;anchovies&quot; in [topping.name for topping in self.get_topping_list()]
+            return &quot;anchovies&quot; in [topping.name for topping in self.toppings.all()]
 
 Now, every ``Pizza`` object will have a ``is_disgusting()`` method.
 
@@ -1016,16 +1293,16 @@ See `Giving models custom methods`_ for a full example.
 
 A few object methods have special meaning:
 
-``__repr__``
-    Django uses ``repr(obj)`` in a number of places, most notably as the value
+``__str__``
+    Django uses ``str(obj)`` in a number of places, most notably as the value
     inserted into a template when it displays an object. Thus, you should always
-    return a nice, human-readable string for the object's ``__repr__``.
+    return a nice, human-readable string for the object's ``__str__``.
 
-    Although defining ``__repr__()`` isn't required, it's strongly encouraged.
+    Although defining ``__str__()`` isn't required, it's strongly encouraged.
 
-    See `Adding repr`_ for a full example.
+    See `Adding str`_ for a full example.
 
-    .. _Adding repr: http://www.djangoproject.com/documentation/models/repr/
+    .. _Adding str: http://www.djangoproject.com/documentation/models/repr/
 
 ``get_absolute_url``
     Define a ``get_absolute_url`` method to tell Django how to calculate the
@@ -1041,49 +1318,34 @@ A few object methods have special meaning:
     It's good practice to use ``get_absolute_url()`` in templates, instead of
     hard-coding your objects' URLs.
 
-``_pre_save``
-    This method is called just before an object is saved to the database. For
-    example, you can use it to calculate aggregate values from other fields
-    before the object is saved.
-
-    See `Adding hooks before/after saving and deleting`_ for a full example.
-
-    .. _Adding hooks before/after saving and deleting: http://www.djangoproject.com/documentation/models/save_delete_hooks/
-
-``_post_save``
-    This method is called just after the object is saved to the database. This
-    could be used to update other tables, update cached information, etc.
-
-``_pre_delete``
-    Like ``_pre_save``, but for deletion.
-
-``_post_delete``
-    Like ``_post_save``, but for deletion.
-
 Module-level methods
 --------------------
 
-Since each data class effectively turns into a &quot;magic&quot; Python module under
-``django.models``, there are times you'll want to write methods that live in
-that module.  Any model method that begins with &quot;_module_&quot; is turned into a
-module-level function::
+If you want to add a method to the Model, rather than instances of the model,
+you can use the Python ``staticmethod`` and ``classmethod`` operators. For
+example::
 
-    class Pizza(meta.Model):
+    class Pizza(models.Model):
         # ...
 
-        def _module_get_pizzas_to_deliver():
+        def get_pizzas_to_deliver():
             return get_list(delivered__exact=False)
+        get_pizzas_to_deliver = staticmethod(get_pizzas_to_deliver)
+
+Or, using Python 2.4 decorators::
+
+    # ...
+    @staticmethod
+    def get_pizzas_to_deliver():
+        # ...
 
 This will make the top-level ``pizzas`` module have a ``get_pizzas_to_deliver()``
 method::
 
-    &gt;&gt;&gt; from django.models.pizza_hut import pizzas
-    &gt;&gt;&gt; pizzas.get_pizzas_to_deliver()
+    &gt;&gt;&gt; from pizza_hut.models import Pizza
+    &gt;&gt;&gt; Pizza.get_pizzas_to_deliver()
     [ ... ]
 
-Note that the scope of these methods is modified to be the same as the module
-scope. These methods do NOT have access to globals within your model's module.
-
 Manipulator methods
 -------------------
 
@@ -1092,7 +1354,7 @@ that being with &quot;_manipulator_&quot;. This is most useful for providing custom
 validators for certain fields, because manipulators automatically call any
 method that begins with &quot;validate&quot;::
 
-    class Pizza(meta.Model):
+    class Pizza(models.Model):
         # ...
 
         def _manipulator_validate_customer_id(self, field_data, all_data):
@@ -1106,14 +1368,15 @@ Executing custom SQL
 --------------------
 
 Feel free to write custom SQL statements in custom model methods and
-module-level methods. Each custom method automatically has access to the
-variable ``db``, which is the current database connection. To use it, call
-``db.cursor()`` to get a cursor object. Then, call ``cursor.execute(sql, [params])``
+module-level methods. The object ``django.db.connection`` object represents
+the current database connection. To use it, call ``connection.cursor()`` to
+get a cursor object. Then, call ``cursor.execute(sql, [params])``
 to execute the SQL and ``cursor.fetchone()`` or ``cursor.fetchall()`` to return
 the resulting rows. Example::
 
     def my_custom_sql(self):
-        cursor = db.cursor()
+        from django.db import connection
+        cursor = connection.cursor()
         cursor.execute(&quot;SELECT foo FROM bar WHERE baz = %s&quot;, [self.baz])
         row = cursor.fetchone()
         return row
@@ -1122,11 +1385,12 @@ If your custom SQL statement alters the data in your database -- for example,
 via a ``DELETE`` or ``UPDATE`` -- you'll need to call ``db.commit()``. Example::
 
     def my_custom_sql2(self):
-        cursor = db.cursor()
+        from django.db import connection
+        cursor = connection.cursor()
         cursor.execute(&quot;DELETE FROM bar WHERE baz = %s&quot;, [self.baz])
-        db.commit()
+        connection.commit()
 
-``db`` and ``cursor`` simply use the standard `Python DB-API`_. If you're not
+``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If you're not
 familiar with the Python DB-API, note that the SQL statement in
 ``cursor.execute()`` uses placeholders, ``&quot;%s&quot;``, rather than adding parameters
 directly within the SQL. If you use this technique, the underlying database
@@ -1138,83 +1402,34 @@ just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
 API. See `Other lookup options`_.
 
 .. _Python DB-API: http://www.python.org/peps/pep-0249.html
-.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#other-lookup-options
+.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables
 
 Using models
 ============
 
-Once you've defined a model, you'll need to &quot;enable&quot; it in Django. This section
-explains how Django searches for available models.
-
-Save your models in a normal Python module. Put this module within a package
-called &quot;models&quot;, which should itself be a subpackage of some other package on
-your Python path. The ``__init__.py`` in your ``models`` package should contain
-an ``__all__`` variable that is set to a list of all model module names within
-the ``models`` directory.
-
-If this sounds confusing, just use ``django-admin.py startapp`` -- it'll create
-the proper directory structure and ``__init__.py`` files. (See the
-`django-admin.py documentation`_ .)
-
-For example, if you save your models in a module called ``mymodels.py``, here's
-a directory layout you might use::
-
-    myapp/
-        __init__.py          # Empty file
-        models/
-            __init__.py      # Contains &quot;__all__ = ['mymodels']&quot;
-            mymodels.py      # Contains your models
-
-Then, you'll have to tell Django that the ``myapp`` application is installed.
-Do this by editing your settings file and adding ``&quot;myapp&quot;`` to the
-``INSTALLED_APPS`` tuple.
-
-Again, if this sounds confusing, use ``django-admin.py startapp`` to take care
-of package creation for you. This documentation exists only to explain how
-Django works.
+Once you have created your model, you have to tell Django about your new application.
+This is done by editing your settings file and adding the name of the module that
+contains your models module to the ``INSTALLED_APPS`` tuple.
 
-Once you've added your app to ``INSTALLED_APPS``, you can open a Python
-interactive interpreter and play with your model::
+For example, if the models for your application are contained in the module
+``project.myapp.models`` (the package structure that is created for an application
+by the ``django-admin.py startapp`` script), ``INSTALLED_APPS`` should read, in part::
 
-    &gt;&gt;&gt; from django.models.mymodels import pizzas
-    &gt;&gt;&gt; pizzas.get_list()
-
-Note that the import is from ``django.models``, not ``myapp.models``. Django
-creates a &quot;magic&quot; module within ``django.models`` for every installed
-application. Each of those magic modules has a dynamic API. See the
-`database API reference`_ for full information on how to use this API.
-
-.. admonition:: Why is the INSTALLED_APPS setting necessary?
-
-   Model relationships work both ways, and the dynamically-generated Django API
-   creates API lookups in both directions. Thus, for Django to figure out all
-   the other models related to a particular model, it has to know the complete
-   spectrum of installed apps.
-
-.. _`django-admin.py documentation`: http://www.djangoproject.com/documentation/django_admin/
-.. _`database API reference`: http://www.djangoproject.com/documentation/db_api/
+    INSTALLED_APPS = (
+        #...
+        project.myapp,
+        #...
+    )
 
 Models across files
 ===================
 
 It's perfectly OK to relate a model to one from another module. To do this,
-just import the model module at the top of your model module, like so::
+just import the model module at the top of your model module. Then, just
+refer to the other model class wherever needed. For example::
 
-    from django.models import core
+    from myproject.otherapp import Site
 
-Make sure you're importing from ``django.models``, not directly from your model
-module.
-
-Then, just refer to the other model class wherever needed. For example::
-
-    class MyModel(meta.Model):
+    class MyModel(models.Model):
         # ...
-        sites = meta.ManyToManyField(core.Site)
-
-Models in multiple files
-========================
-
-If you want to have multiple model modules in a ``&quot;models&quot;`` directory, make
-sure you edit ``&quot;models/__init__.py&quot;`` and add the name of your model module
-to the ``__all__`` variable. If your ``models`` package doesn't have your model
-module in ``__all__``, Django won't see any of the models in that module.
+        sites = models.ManyToManyField(Site)</diff>
      <filename>docs/model-api.txt</filename>
    </modified>
    <modified>
      <diff>@@ -31,11 +31,11 @@ Then edit your ``httpd.conf`` file and add the following::
     &lt;Location &quot;/mysite/&quot;&gt;
         SetHandler python-program
         PythonHandler django.core.handlers.modpython
-        SetEnv DJANGO_SETTINGS_MODULE myproject.settings
+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
         PythonDebug On
     &lt;/Location&gt;
 
-...and replace ``myproject.settings`` with the Python path to your settings file.
+...and replace ``mysite.settings`` with the Python path to your settings file.
 
 This tells Apache: &quot;Use mod_python for any URL at or under '/mysite/', using the
 Django mod_python handler.&quot; It passes the value of ``DJANGO_SETTINGS_MODULE``
@@ -71,13 +71,13 @@ instance. Just use ``VirtualHost`` for that, like so::
     &lt;VirtualHost *&gt;
         ServerName www.example.com
         # ...
-        SetEnv DJANGO_SETTINGS_MODULE myproject.settings
+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
     &lt;/VirtualHost&gt;
 
     &lt;VirtualHost *&gt;
         ServerName www2.example.com
         # ...
-        SetEnv DJANGO_SETTINGS_MODULE myproject.other_settings
+        SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
     &lt;/VirtualHost&gt;
 
 If you need to put two Django installations within the same ``VirtualHost``,
@@ -89,13 +89,13 @@ mess things up. Use the ``PythonInterpreter`` directive to give different
         ServerName www.example.com
         # ...
         &lt;Location &quot;/something&quot;&gt;
-            SetEnv DJANGO_SETTINGS_MODULE myproject.settings
-            PythonInterpreter myproject
+            SetEnv DJANGO_SETTINGS_MODULE mysite.settings
+            PythonInterpreter mysite
         &lt;/Location&gt;
 
         &lt;Location &quot;/otherthing&quot;&gt;
-            SetEnv DJANGO_SETTINGS_MODULE myproject.other_settings
-            PythonInterpreter myproject_other
+            SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
+            PythonInterpreter mysite_other
         &lt;/Location&gt;
     &lt;/VirtualHost&gt;
 
@@ -153,7 +153,7 @@ the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif`` or
     &lt;Location &quot;/&quot;&gt;
         SetHandler python-program
         PythonHandler django.core.handlers.modpython
-        SetEnv DJANGO_SETTINGS_MODULE myproject.settings
+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
     &lt;/Location&gt;
 
     &lt;Location &quot;media&quot;&gt;</diff>
      <filename>docs/modpython.txt</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,7 @@ and Django's ``HttpResponse`` objects are file-like objects.
 Here's an example::
 
     import csv
-    from django.utils.httpwrappers import HttpResponse
+    from django.http import HttpResponse
 
     def some_view(request):
         # Create the HttpResponse object with the appropriate CSV header.
@@ -49,10 +49,10 @@ mention:
     * The response gets a special mimetype, ``text/csv``. This tells
       browsers that the document is a CSV file, rather than an HTML file. If
       you leave this off, browsers will probably interpret the output as HTML,
-      which would result in ugly, scary gobbledygook in the browser window.
+      which will result in ugly, scary gobbledygook in the browser window.
 
     * The response gets an additional ``Content-Disposition`` header, which
-      contains the name of the CSV file. This filename is arbitrary: Call it
+      contains the name of the CSV file. This filename is arbitrary; call it
       whatever you want. It'll be used by browsers in the &quot;Save as...&quot;
       dialogue, etc.
 
@@ -79,8 +79,8 @@ template output the commas in a ``{% for %}`` loop.
 
 Here's an example, which generates the same CSV file as above::
 
-    from django.utils.httpwrappers import HttpResponse
-    from django.core.template import loader, Context
+    from django.http import HttpResponse
+    from django.template import loader, Context
 
     def some_view(request):
         # Create the HttpResponse object with the appropriate CSV header.
@@ -94,7 +94,7 @@ Here's an example, which generates the same CSV file as above::
             ('Second row', 'A', 'B', 'C', '&quot;Testing&quot;', &quot;Here's a quote&quot;),
         )
 
-        t = loader.get_template('my_template_name')
+        t = loader.get_template('my_template_name.txt')
         c = Context({
             'data': csv_data,
         })
@@ -105,7 +105,7 @@ The only difference between this example and the previous example is that this
 one uses template loading instead of the CSV module. The rest of the code --
 such as the ``mimetype='text/csv'`` -- is the same.
 
-Then, create the template ``my_template_name``, with this template code::
+Then, create the template ``my_template_name.txt``, with this template code::
 
     {% for row in data %}&quot;{{ row.0|addslashes }}&quot;, &quot;{{ row.1|addslashes }}&quot;, &quot;{{ row.2|addslashes }}&quot;, &quot;{{ row.3|addslashes }}&quot;, &quot;{{ row.4|addslashes }}&quot;
     {% endfor %}</diff>
      <filename>docs/outputting_csv.txt</filename>
    </modified>
    <modified>
      <diff>@@ -48,7 +48,7 @@ objects.
 Here's a &quot;Hello World&quot; example::
 
     from reportlab.pdfgen import canvas
-    from django.utils.httpwrappers import HttpResponse
+    from django.http import HttpResponse
 
     def some_view(request):
         # Create the HttpResponse object with the appropriate PDF headers.</diff>
      <filename>docs/outputting_pdf.txt</filename>
    </modified>
    <modified>
      <diff>@@ -16,34 +16,39 @@ to start a project.
 Design your model
 =================
 
-Start by describing your database layout in Python code. Django's data-model API
-offers many rich ways of representing your models -- so far, it's been
-solving two years' worth of database-schema problems. Here's a quick example::
+Although you can use Django without a database, it comes with an
+object-relational mapper in which you describe your database layout in Python
+code.
 
-    class Reporter(meta.Model):
-        full_name = meta.CharField(maxlength=70)
+The data-model syntax offers many rich ways of representing your models -- so
+far, it's been solving two years' worth of database-schema problems. Here's a
+quick example::
 
-        def __repr__(self):
+    class Reporter(models.Model):
+        full_name = models.CharField(maxlength=70)
+
+        def __str__(self):
             return self.full_name
 
-    class Article(meta.Model):
-        pub_date = meta.DateTimeField()
-        headline = meta.CharField(maxlength=200)
-        article = meta.TextField()
-        reporter = meta.ForeignKey(Reporter)
+    class Article(models.Model):
+        pub_date = models.DateTimeField()
+        headline = models.CharField(maxlength=200)
+        article = models.TextField()
+        reporter = models.ForeignKey(Reporter)
 
-        def __repr__(self):
+        def __str__(self):
             return self.headline
 
 Install it
 ==========
 
-Next, run the Django command-line utility. It'll create the database tables for
-you automatically, in the database specified in your Django settings. Django
-works best with PostgreSQL, although we've recently added beta MySQL
-support and other database adapters are on the way::
+Next, run the Django command-line utility to create the database tables
+automatically::
+
+    manage.py syncdb
 
-    django-admin.py install news
+The ``syncdb`` command looks at all your available models and creates tables
+in your database for whichever tables don't already exist.
 
 Enjoy the free API
 ==================
@@ -51,16 +56,14 @@ Enjoy the free API
 With that, you've got a free, and rich, Python API to access your data. The API
 is created on the fly: No code generation necessary::
 
-    # Modules are dynamically created within django.models.
-    # Their names are plural versions of the model class names.
-    &gt;&gt;&gt; from django.models.news import reporters, articles
+    &gt;&gt;&gt; from mysite.models import Reporter, Article
 
     # No reporters are in the system yet.
-    &gt;&gt;&gt; reporters.get_list()
+    &gt;&gt;&gt; Reporter.objects.all()
     []
 
     # Create a new Reporter.
-    &gt;&gt;&gt; r = reporters.Reporter(full_name='John Smith')
+    &gt;&gt;&gt; r = Reporter(full_name='John Smith')
 
     # Save the object into the database. You have to call save() explicitly.
     &gt;&gt;&gt; r.save()
@@ -70,52 +73,48 @@ is created on the fly: No code generation necessary::
     1
 
     # Now the new reporter is in the database.
-    &gt;&gt;&gt; reporters.get_list()
+    &gt;&gt;&gt; Reporter.objects.all()
     [John Smith]
 
     # Fields are represented as attributes on the Python object.
     &gt;&gt;&gt; r.full_name
     'John Smith'
 
-    # Django provides a rich database lookup API that's entirely driven by keyword arguments.
-    &gt;&gt;&gt; reporters.get_object(id__exact=1)
+    # Django provides a rich database lookup API.
+    &gt;&gt;&gt; Reporter.objects.get(id=1)
     John Smith
-    &gt;&gt;&gt; reporters.get_object(full_name__startswith='John')
+    &gt;&gt;&gt; Reporter.objects.get(full_name__startswith='John')
     John Smith
-    &gt;&gt;&gt; reporters.get_object(full_name__contains='mith')
+    &gt;&gt;&gt; Reporter.objects.get(full_name__contains='mith')
     John Smith
-    &gt;&gt;&gt; reporters.get_object(id__exact=2)
+    &gt;&gt;&gt; Reporter.objects.get(id=2)
     Traceback (most recent call last):
         ...
-    django.models.news.ReporterDoesNotExist: Reporter does not exist for {'id__exact': 2}
-
-    # Lookup by a primary key is the most common case, so Django provides a
-    # shortcut for primary-key exact lookups.
-    # The following is identical to reporters.get_object(id__exact=1).
-    &gt;&gt;&gt; reporters.get_object(pk=1)
-    John Smith
+    DoesNotExist: Reporter does not exist for {'id__exact': 2}
 
     # Create an article.
     &gt;&gt;&gt; from datetime import datetime
-    &gt;&gt;&gt; a = articles.Article(pub_date=datetime.now(), headline='Django is cool', article='Yeah.', reporter_id=1)
+    &gt;&gt;&gt; a = Article(pub_date=datetime.now(), headline='Django is cool',
+    ...     article='Yeah.', reporter=r)
     &gt;&gt;&gt; a.save()
 
     # Now the article is in the database.
-    &gt;&gt;&gt; articles.get_list()
+    &gt;&gt;&gt; Article.objects.all()
     [Django is cool]
 
     # Article objects get API access to related Reporter objects.
-    &gt;&gt;&gt; r = a.get_reporter()
+    &gt;&gt;&gt; r = a.reporter
     &gt;&gt;&gt; r.full_name
     'John Smith'
 
     # And vice versa: Reporter objects get API access to Article objects.
-    &gt;&gt;&gt; r.get_article_list()
+    &gt;&gt;&gt; r.article_set.all()
     [Django is cool]
 
-    # The API follows relationships as far as you need.
-    # Find all articles by a reporter whose name starts with &quot;John&quot;.
-    &gt;&gt;&gt; articles.get_list(reporter__full_name__startswith=&quot;John&quot;)
+    # The API follows relationships as far as you need, performing efficient
+    # JOINs for you behind the scenes.
+    # This finds all articles by a reporter whose name starts with &quot;John&quot;.
+    &gt;&gt;&gt; Article.objects.filter(reporter__full_name__startswith=&quot;John&quot;)
     [Django is cool]
 
     # Change an object by altering its attributes and calling save().
@@ -128,61 +127,64 @@ is created on the fly: No code generation necessary::
 A dynamic admin interface: It's not just scaffolding -- it's the whole house
 ============================================================================
 
-Once your models are defined, Django can automatically create an administrative
-interface -- a Web site that lets authenticated users add, change and
-delete objects. It's as easy as adding an extra ``admin`` attribute to your
-model classes::
+Once your models are defined, Django can automatically create a professional,
+production ready administrative interface -- a Web site that lets authenticated
+users add, change and delete objects. It's as easy as adding a line of code to
+your model classes::
 
-    class Article(meta.Model):
-        pub_date = meta.DateTimeField()
-        headline = meta.CharField(maxlength=200)
-        article = meta.TextField()
-        reporter = meta.ForeignKey(Reporter)
-        class META:
-            admin = meta.Admin()
+    class Article(models.Model):
+        pub_date = models.DateTimeField()
+        headline = models.CharField(maxlength=200)
+        article = models.TextField()
+        reporter = models.ForeignKey(Reporter)
+        class Admin: pass
 
 The philosophy here is that your site is edited by a staff, or a client, or
 maybe just you -- and you don't want to have to deal with creating backend
 interfaces just to manage content.
 
-Our typical workflow at World Online is to create models and get the admin sites
-up and running as fast as possible, so our staff journalists can start
-populating data. Then we develop the way data is presented to the public.
+One typical workflow in creating Django apps is to create models and get the
+admin sites up and running as fast as possible, so your staff (or clients) can
+start populating data. Then, develop the way data is presented to the public.
 
 Design your URLs
 ================
 
 A clean, elegant URL scheme is an important detail in a high-quality Web
-application. Django lets you design URLs however you want, with no framework
-limitations.
+application. Django encourages beautiful URL design and doesn't put any cruft
+in URLs, like ``.php`` or ``.asp``.
 
-To design URLs for an app, you create a Python module. For the above
-Reporter/Article example, here's what that might look like::
+To design URLs for an app, you create a Python module called a URLconf. A table
+of contents for your app, it contains a simple mapping between URL patterns and
+Python callback functions. URLconfs also serve to decouple URLs from Python
+code.
+
+Here's what a URLconf might look like for the above ``Reporter``/``Article``
+example above::
 
     from django.conf.urls.defaults import *
 
     urlpatterns = patterns('',
-        (r'^/articles/(?P&lt;year&gt;\d{4})/$', 'myproject.news.views.year_archive'),
-        (r'^/articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/$', 'myproject.news.views.month_archive'),
-        (r'^/articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/(?P&lt;article_id&gt;\d+)/$', 'myproject.news.views.article_detail'),
+        (r'^/articles/(\d{4})/$', 'mysite.views.year_archive'),
+        (r'^/articles/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'),
+        (r'^/articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'),
     )
 
-The code above maps URLs, as regular expressions, to the location of Python
-callback functions (views). The regular expressions use parenthesis to &quot;capture&quot;
-values from the URLs. When a user requests a page, Django runs through each
-regular expression, in order, and stops at the first one that matches the
-requested URL. (If none of them matches, Django calls a special 404 view.) This
-is blazingly fast, because the regular expressions are compiled at load time.
+The code above maps URLs, as simple regular expressions, to the location of
+Python callback functions (&quot;views&quot;). The regular expressions use parenthesis to
+&quot;capture&quot; values from the URLs. When a user requests a page, Django runs
+through each pattern, in order, and stops at the first one that matches the
+requested URL. (If none of them matches, Django calls a special-case 404 view.)
+This is blazingly fast, because the regular expressions are compiled at load
+time.
 
 Once one of the regexes matches, Django imports and calls the given view, which
 is a simple Python function. Each view gets passed a request object --
-which contains request metadata and lets you access GET and POST data as simple
-dictionaries -- and the values captured in the regex, via keyword
-arguments.
+which contains request metadata -- and the values captured in the regex.
 
 For example, if a user requested the URL &quot;/articles/2005/05/39323/&quot;, Django
 would call the function ``myproject.news.views.article_detail(request,
-year='2005', month='05', article_id='39323')``.
+'2005', '05', '39323')``.
 
 Write your views
 ================
@@ -193,29 +195,29 @@ raising an exception such as ``Http404``. The rest is up to you.
 
 Generally, a view retrieves data according to the parameters, loads a template
 and renders the template with the retrieved data. Here's an example view for
-article_detail from above::
+``year_archive`` from above::
 
-    def article_detail(request, year, month, article_id):
-        # Use the Django API to find an object matching the URL criteria.
-        a = get_object_or_404(articles, pub_date__year=year, pub_date__month=month, pk=article_id)
-        return render_to_response('news/article_detail', {'article': a})
+    def year_archive(request, year):
+        a_list = Article.objects.filter(pub_date__year=year)
+        return render_to_response('news/year_archive.html', {'article_list': a_list})
 
-This example uses Django's template system, which has several key features.
+This example uses Django's template system, which has several powerful
+features but strives to stay simple enough for non-programmers to use.
 
 Design your templates
 =====================
 
-The code above loads the ``news/article_detail`` template.
+The code above loads the ``news/year_archive.html`` template.
 
 Django has a template search path, which allows you to minimize redundancy among
 templates. In your Django settings, you specify a list of directories to check
 for templates. If a template doesn't exist in the first directory, it checks the
 second, and so on.
 
-Let's say the ``news/article_detail`` template was found. Here's what that might
-look like::
+Let's say the ``news/article_detail.html`` template was found. Here's what that
+might look like::
 
-    {% extends &quot;base&quot; %}
+    {% extends &quot;base.html&quot; %}
 
     {% block title %}{{ article.headline }}{% endblock %}
 
@@ -226,12 +228,10 @@ look like::
     {{ article.article }}
     {% endblock %}
 
-
-It should look straightforward. Variables are surrounded by double-curly braces.
-``{{ article.headline }}`` means &quot;Output the value of the article's headline
-attribute.&quot; But dots aren't used only for attribute lookup: They also can do
-dictionary-key lookup, index lookup and function calls (as is the case with
-``article.get_reporter``).
+Variables are surrounded by double-curly braces. ``{{ article.headline }}``
+means &quot;Output the value of the article's headline attribute.&quot; But dots aren't
+used only for attribute lookup: They also can do dictionary-key lookup, index
+lookup and function calls (as is the case with ``article.get_reporter``).
 
 Note ``{{ article.pub_date|date:&quot;F j, Y&quot; }}`` uses a Unix-style &quot;pipe&quot; (the &quot;|&quot;
 character). This is called a template filter, and it's a way to filter the value
@@ -243,13 +243,13 @@ You can chain together as many filters as you'd like. You can write custom
 filters. You can write custom template tags, which run custom Python code behind
 the scenes.
 
-Finally, Django uses the concept of template inheritance: That's what the ``{%
-extends &quot;base&quot; %}`` does. It means &quot;First load the template called 'base', which
-has defined a bunch of blocks, and fill the blocks with the following blocks.&quot;
-In short, that lets you dramatically cut down on redundancy in templates: Each
-template has to define only what's unique to that template.
+Finally, Django uses the concept of &quot;template inheritance&quot;: That's what the
+``{% extends &quot;base.html&quot; %}`` does. It means &quot;First load the template called
+'base', which has defined a bunch of blocks, and fill the blocks with the
+following blocks.&quot; In short, that lets you dramatically cut down on redundancy
+in templates: Each template has to define only what's unique to that template.
 
-Here's what the &quot;base&quot; template might look like::
+Here's what the &quot;base.html&quot; template might look like::
 
     &lt;html&gt;
     &lt;head&gt;
@@ -265,13 +265,18 @@ Simplistically, it defines the look-and-feel of the site (with the site's logo),
 and provides &quot;holes&quot; for child templates to fill. This makes a site redesign as
 easy as changing a single file -- the base template.
 
+It also lets you create multiple versions of a site, with different base
+templates, while reusing child templates. Django's creators have used this
+technique to create strikingly different cell-phone editions of sites -- simply
+by creating a new base template.
+
 Note that you don't have to use Django's template system if you prefer another
 system. While Django's template system is particularly well-integrated with
 Django's model layer, nothing forces you to use it. For that matter, you don't
-have to use Django's API, either. You can use another database abstraction
-layer, you can read XML files, you can read files off disk, or anything you
-want. Each piece of Django -- models, views, templates -- is decoupled
-from the next.
+have to use Django's database API, either. You can use another database
+abstraction layer, you can read XML files, you can read files off disk, or
+anything you want. Each piece of Django -- models, views, templates -- is
+decoupled from the next.
 
 This is just the surface
 ========================</diff>
      <filename>docs/overview.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,12 +8,12 @@ redirects in a database and handles the redirecting for you.
 Installation
 ============
 
-To install the redirects app, follow these two steps:
+To install the redirects app, follow these steps:
 
-    1. Add ``&quot;django.contrib.redirects&quot;`` to your INSTALLED_APPS_ setting.
-    2. Add ``&quot;django.contrib.redirects.middleware.RedirectFallbackMiddleware&quot;``
+    1. Add ``'django.contrib.redirects'`` to your INSTALLED_APPS_ setting.
+    2. Add ``'django.contrib.redirects.middleware.RedirectFallbackMiddleware'``
        to your MIDDLEWARE_CLASSES_ setting.
-    3. Run the command ``django-admin.py install redirects``.
+    3. Run the command ``manage.py syncdb``.
 
 .. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
 .. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
@@ -21,9 +21,8 @@ To install the redirects app, follow these two steps:
 How it works
 ============
 
-``django-admin.py install redirects`` creates a ``django_redirects`` table in
-your database. This is a simple lookup table with ``site_id``, ``old_path`` and
-``new_path`` fields.
+``manage.py syncdb`` creates a ``django_redirect`` table in your database. This
+is a simple lookup table with ``site_id``, ``old_path`` and ``new_path`` fields.
 
 The ``RedirectFallbackMiddleware`` does all of the work. Each time any Django
 application raises a 404 error, this middleware checks the redirects database</diff>
      <filename>docs/redirects.txt</filename>
    </modified>
    <modified>
      <diff>@@ -37,6 +37,8 @@ All attributes except ``session`` should be considered read-only.
     A dictionary-like object containing all given HTTP POST parameters. See the
     ``QueryDict`` documentation below.
 
+    Note: ``POST`` does *not* include file-upload information. See ``FILES``.
+
 ``REQUEST``
     For convenience, a dictionary-like object that searches ``POST`` first,
     then ``GET``. Inspired by PHP's ``$_REQUEST``.
@@ -86,9 +88,9 @@ All attributes except ``session`` should be considered read-only.
         * ``SERVER_PORT`` -- The port of the server.
 
 ``user``
-    A ``django.models.auth.users.User`` object representing the currently
+    A ``django.contrib.auth.models.User`` object representing the currently
     logged-in user. If the user isn't currently logged in, ``user`` will be set
-    to an instance of ``django.parts.auth.anonymoususers.AnonymousUser``. You
+    to an instance of ``django.contrib.auth.models.AnonymousUser``. You
     can tell them apart with ``is_anonymous()``, like so::
 
         if request.user.is_anonymous():
@@ -96,6 +98,12 @@ All attributes except ``session`` should be considered read-only.
         else:
             # Do something for logged-in users.
 
+    ``user`` is only available if your Django installation has the
+    ``AuthenticationMiddleware`` activated. For more, see
+    `Authentication in Web requests`_.
+
+    .. Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
+
 ``session``
     A readable-and-writable, dictionary-like object that represents the current
     session. This is only available if your Django installation has session
@@ -131,10 +139,10 @@ QueryDict objects
 -----------------
 
 In an ``HttpRequest`` object, the ``GET`` and ``POST`` attributes are instances
-of ``django.utils.httpwrappers.QueryDict``. ``QueryDict`` is a dictionary-like
+of ``django.http.QueryDict``. ``QueryDict`` is a dictionary-like
 class customized to deal with multiple values for the same key. This is
-necessary because some HTML form elements, notably ``&lt;select multiple&gt;``, pass
-multiple values for the same key.
+necessary because some HTML form elements, notably
+``&lt;select multiple=&quot;multiple&quot;&gt;``, pass multiple values for the same key.
 
 ``QueryDict`` instances are immutable, unless you create a ``copy()`` of them.
 That means you can't change attributes of ``request.POST`` and ``request.GET``
@@ -269,11 +277,14 @@ In contrast to ``HttpRequest`` objects, which are created automatically by
 Django, ``HttpResponse`` objects are your responsibility. Each view you write
 is responsible for instantiating, populating and returning an ``HttpResponse``.
 
-The ``HttpResponse`` class lives at ``django.utils.httpwrappers.HttpResponse``.
+The ``HttpResponse`` class lives at ``django.http.HttpResponse``.
 
 Usage
 -----
 
+Passing strings
+~~~~~~~~~~~~~~~
+
 Typical usage is to pass the contents of the page, as a string, to the
 ``HttpResponse`` constructor::
 
@@ -297,16 +308,27 @@ You can add and delete headers using dictionary syntax::
 
 Note that ``del`` doesn't raise ``KeyError`` if the header doesn't exist.
 
+Passing iterators
+~~~~~~~~~~~~~~~~~
+
+Finally, you can pass ``HttpResponse`` an iterator rather than passing it
+hard-coded strings. If you use this technique, follow these guidelines:
+
+    * The iterator should return strings.
+    * If an ``HttpResponse`` has been initialized with an iterator as its
+      content, you can't use the ``HttpResponse`` instance as a file-like
+      object. Doing so will raise ``Exception``.
+
 Methods
 -------
 
 ``__init__(content='', mimetype=DEFAULT_MIME_TYPE)``
     Instantiates an ``HttpResponse`` object with the given page content (a
-    string) and MIME type. The ``DEFAULT_MIME_TYPE`` is ``&quot;text/html&quot;``.
+    string) and MIME type. The ``DEFAULT_MIME_TYPE`` is ``'text/html'``.
 
-    **New in Django development version:** ``content`` can be an iterator
-    instead of a string. This iterator should return strings, and those strings
-    will be joined together to form the content of the response.
+    ``content`` can be an iterator or a string. If it's an iterator, it should
+    return strings, and those strings will be joined together to form the
+    content of the response.
 
 ``__setitem__(header, value)``
     Sets the given header name to the given value. Both ``header`` and
@@ -343,14 +365,10 @@ Methods
     Deletes the cookie with the given key. Fails silently if the key doesn't
     exist.
 
-``get_content_as_string(encoding)``
-    Returns the content as a Python string, encoding it from a Unicode object
-    if necessary. **Removed in Django development version.**
-
 ``content``
-    **New in Django development version.** Returns the content as a Python
-    string, encoding it from a Unicode object if necessary. Note this is a
-    property, not a method, so use ``r.content`` instead of ``r.content()``.
+    Returns the content as a Python string, encoding it from a Unicode object
+    if necessary. Note this is a property, not a method, so use ``r.content``
+    instead of ``r.content()``.
 
 ``write(content)``, ``flush()`` and ``tell()``
     These methods make an ``HttpResponse`` instance a file-like object.
@@ -360,12 +378,12 @@ HttpResponse subclasses
 
 Django includes a number of ``HttpResponse`` subclasses that handle different
 types of HTTP responses. Like ``HttpResponse``, these subclasses live in
-``django.utils.httpwrappers``.
+``django.http``.
 
 ``HttpResponseRedirect``
     The constructor takes a single argument -- the path to redirect to. This
-    can be a fully qualified URL (e.g. ``&quot;http://www.yahoo.com/search/&quot;``) or an
-    absolute URL with no domain (e.g. ``&quot;/search/&quot;``). Note that this returns
+    can be a fully qualified URL (e.g. ``'http://www.yahoo.com/search/'``) or an
+    absolute URL with no domain (e.g. ``'/search/'``). Note that this returns
     an HTTP status code 302.
 
 ``HttpResponsePermanentRedirect``</diff>
      <filename>docs/request_response.txt</filename>
    </modified>
    <modified>
      <diff>@@ -10,33 +10,30 @@ Cookies contain a session ID -- not the data itself.
 Enabling sessions
 =================
 
-Session functionality is enabled by default.
+Sessions are implemented via middleware_.
 
-You can turn session functionality on and off by editing the
-``MIDDLEWARE_CLASSES`` setting. To activate sessions, make sure
-``MIDDLEWARE_CLASSES`` contains ``&quot;django.middleware.sessions.SessionMiddleware&quot;``.
+Turn session functionality on and off by editing the ``MIDDLEWARE_CLASSES``
+setting. To activate sessions, make sure ``MIDDLEWARE_CLASSES`` contains
+``&quot;django.contrib.sessions.middleware.SessionMiddleware&quot;``.
 
-If you're dealing with an admin site, make sure the ``SessionMiddleware`` line
-appears before the ``AdminUserRequired`` line. (The middleware classes are
-applied in order, and the admin middleware requires that the session middleware
-come first.)
+The default ``settings.py`` created by ``django-admin.py startproject`` has
+``SessionMiddleware`` activated.
 
 If you don't want to use sessions, you might as well remove the
 ``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES``. It'll save you a small
 bit of overhead.
 
+.. _middleware: http://www.djangoproject.com/documentation/middleware/
+
 Using sessions in views
 =======================
 
-Each ``HttpRequest`` object -- the first argument to any Django view function --
-has a ``session`` attribute, which is a dictionary-like object. You can read
-it and write to it.
+When ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the
+first argument to any Django view function -- will have a ``session``
+attribute, which is a dictionary-like object. You can read it and write to it.
 
 It implements the following standard dictionary methods:
 
-    * ``__contains__(key)``
-      Example: ``'fav_color' in request.session``
-
     * ``__getitem__(key)``
       Example: ``fav_color = request.session['fav_color']``
 
@@ -47,14 +44,15 @@ It implements the following standard dictionary methods:
       Example: ``del request.session['fav_color']``. This raises ``KeyError``
       if the given ``key`` isn't already in the session.
 
+    * ``__contains__(key)``
+      Example: ``'fav_color' in request.session``
+
     * ``get(key, default=None)``
       Example: ``fav_color = request.session.get('fav_color', 'red')``
 
     * ``keys()``
-      **New in Django development version.**
 
     * ``items()``
-      **New in Django development version.**
 
 It also has these three methods:
 
@@ -146,17 +144,17 @@ Here's a typical usage example::
             else:
                 return HttpResponse(&quot;Please enable cookies and try again.&quot;)
         request.session.set_test_cookie()
-        return render_to_response('foo/login_form')
+        return render_to_response('foo/login_form.html')
 
 Using sessions out of views
 ===========================
 
 Internally, each session is just a normal Django model. The ``Session`` model
-is defined in ``django/models/core.py``. Because it's a normal model, you can
-access sessions using the normal Django database API::
+is defined in ``django/contrib/sessions/models.py``. Because it's a normal
+model, you can access sessions using the normal Django database API::
 
-    &gt;&gt;&gt; from django.models.core import sessions
-    &gt;&gt;&gt; s = sessions.get_object(pk='2b1189a188b44ad18c35e113ac6ceead')
+    &gt;&gt;&gt; from django.contrib.sessions.models import Session
+    &gt;&gt;&gt; s = Session.objects.get_object(pk='2b1189a188b44ad18c35e113ac6ceead')
     &gt;&gt;&gt; s.expire_date
     datetime.datetime(2005, 8, 20, 13, 35, 12)
 
@@ -244,7 +242,7 @@ Technical details
     * The session dictionary should accept any pickleable Python object. See
       `the pickle module`_ for more information.
 
-    * Session data is stored in a database table named ``core_sessions`` .
+    * Session data is stored in a database table named ``django_session`` .
 
     * Django only sends a cookie if it needs to. If you don't set any session
       data, it won't send a session cookie.</diff>
      <filename>docs/sessions.txt</filename>
    </modified>
    <modified>
      <diff>@@ -19,7 +19,7 @@ Here are a couple of example settings::
 
 Because a settings file is a Python module, the following apply:
 
-    * It shouldn't have Python syntax errors.
+    * It doesn't allow for Python syntax errors.
     * It can assign settings dynamically using normal Python syntax.
       For example::
 
@@ -34,7 +34,7 @@ When you use Django, you have to tell it which settings you're using. Do this
 by using an environment variable, ``DJANGO_SETTINGS_MODULE``.
 
 The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
-``&quot;myproject.settings&quot;``. Note that the settings module should be on the
+``mysite.settings``. Note that the settings module should be on the
 Python `import search path`_.
 
 .. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
@@ -47,17 +47,17 @@ once, or explicitly pass in the settings module each time you run the utility.
 
 Example (Unix Bash shell)::
 
-    export DJANGO_SETTINGS_MODULE=myproject.settings
+    export DJANGO_SETTINGS_MODULE=mysite.settings
     django-admin.py runserver
 
 Example (Windows shell)::
 
-    set DJANGO_SETTINGS_MODULE=myproject.settings
+    set DJANGO_SETTINGS_MODULE=mysite.settings
     django-admin.py runserver
 
 Use the ``--settings`` command-line argument to specify the settings manually::
 
-    django-admin.py runserver --settings=myproject.settings
+    django-admin.py runserver --settings=mysite.settings
 
 .. _django-admin.py: http://www.djangoproject.com/documentation/django_admin/
 
@@ -70,7 +70,7 @@ settings file to use. Do that with ``SetEnv``::
     &lt;Location &quot;/mysite/&quot;&gt;
         SetHandler python-program
         PythonHandler django.core.handlers.modpython
-        SetEnv DJANGO_SETTINGS_MODULE myproject.settings
+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
     &lt;/Location&gt;
 
 Read the `Django mod_python documentation`_ for more information.
@@ -93,6 +93,17 @@ Here's the algorithm Django uses in compiling settings:
 Note that a settings file should *not* import from ``global_settings``, because
 that's redundant.
 
+Seeing which settings you've changed
+------------------------------------
+
+There's an easy way to view which of your settings deviate from the default
+settings. The command ``python manage.py diffsettings`` displays differences
+between the current settings file and Django's default settings.
+
+For more, see the `diffsettings documentation`_.
+
+.. _diffsettings documentation: http://www.djangoproject.com/documentation/django_admin/#diffsettings
+
 Using settings in Python code
 =============================
 
@@ -107,6 +118,8 @@ In your Django apps, use settings by importing them from
 Note that your code should *not* import from either ``global_settings`` or
 your own settings file. ``django.conf.settings`` abstracts the concepts of
 default settings and site-specific settings; it presents a single interface.
+It also decouples the code that uses settings from the location of your
+settings.
 
 Altering settings at runtime
 ============================
@@ -156,6 +169,9 @@ Default: ``()`` (Empty list)
 Used for admin-site settings modules, this should be a tuple of settings
 modules (in the format ``'foo.bar.baz'``) for which this site is an admin.
 
+The admin site uses this in its automatically-introspected documentation of
+models, views and template tags.
+
 ADMIN_MEDIA_PREFIX
 ------------------
 
@@ -228,6 +244,14 @@ Default: ``''`` (Empty string)
 Which host to use when connecting to the database. An empty string means
 localhost. Not used with SQLite.
 
+If this value starts with a forward slash (``'/'``) and you're using MySQL,
+MySQL will connect via a Unix socket to the specified socket. For example::
+
+    DATABASE_HOST = '/var/run/mysql'
+
+If you're using MySQL and this value *doesn't* start with a forward slash, then
+this value is assumed to be the host.
+
 DATABASE_NAME
 -------------
 
@@ -341,8 +365,6 @@ EMAIL_HOST_PASSWORD
 
 Default: ``''`` (Empty string)
 
-**New in Django development version.**
-
 Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty,
 Django won't attempt authentication.
 
@@ -353,8 +375,6 @@ EMAIL_HOST_USER
 
 Default: ``''`` (Empty string)
 
-**New in Django development version.**
-
 Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty,
 Django won't attempt authentication.
 
@@ -365,8 +385,6 @@ EMAIL_PORT
 
 Default: ``25``
 
-**New in Django development version.**
-
 Port to use for the SMTP server defined in ``EMAIL_HOST``.
 
 EMAIL_SUBJECT_PREFIX
@@ -383,8 +401,6 @@ ENABLE_PSYCO
 
 Default: ``False``
 
-**New in Django development version.**
-
 Whether to enable Psyco, which optimizes Python code. Requires Psyco_.
 
 .. _Psyco: http://psyco.sourceforge.net/
@@ -509,7 +525,8 @@ MIDDLEWARE_CLASSES
 
 Default::
 
-    (&quot;django.middleware.sessions.SessionMiddleware&quot;,
+    (&quot;django.contrib.sessions.middleware.SessionMiddleware&quot;,
+     &quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;,
      &quot;django.middleware.common.CommonMiddleware&quot;,
      &quot;django.middleware.doc.XViewMiddleware&quot;)
 
@@ -598,9 +615,9 @@ SITE_ID
 
 Default: Not defined
 
-The ID, as an integer, of the current site in the ``sites`` database. This is
-used so that application data can hook into specific site(s) and a single
-database can manage content for multiple sites.
+The ID, as an integer, of the current site in the ``django_site`` database
+table. This is used so that application data can hook into specific site(s)
+and a single database can manage content for multiple sites.
 
 TEMPLATE_CONTEXT_PROCESSORS
 ---------------------------
@@ -611,7 +628,7 @@ Default::
     &quot;django.core.context_processors.debug&quot;,
     &quot;django.core.context_processors.i18n&quot;)
 
-A tuple of callables that are used to populate the context in ``DjangoContext``.
+A tuple of callables that are used to populate the context in ``RequestContext``.
 These callables take a request object as their argument and return a dictionary
 of items to be merged into the context.
 
@@ -625,8 +642,8 @@ error page will display a detailed report for any ``TemplateSyntaxError``. This
 report contains the relevant snippet of the template, with the appropriate line
 highlighted.
 
-Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so you'll
-want to set that to take advantage of this setting.
+Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so
+you'll want to set that to take advantage of this setting.
 
 See also DEBUG.
 
@@ -640,18 +657,10 @@ these paths should use Unix-style forward slashes, even on Windows.
 
 See the `template documentation`_.
 
-TEMPLATE_FILE_EXTENSION
------------------------
-
-Default: ``'.html'``
-
-The file extension to append to all template names when searching for
-templates. See the `template documentation`_.
-
 TEMPLATE_LOADERS
 ----------------
 
-Default: ``('django.core.template.loaders.filesystem.load_template_source',)``
+Default: ``('django.template.loaders.filesystem.load_template_source',)``
 
 A tuple of callables (as strings) that know how to import templates from
 various sources. See the `template documentation`_.
@@ -661,8 +670,6 @@ TEMPLATE_STRING_IF_INVALID
 
 Default: ``''`` (Empty string)
 
-**New in Django development version.**
-
 Output, as a string, that the template system should use for invalid (e.g.
 misspelled) variables. See `How invalid variables are handled`_.
 </diff>
      <filename>docs/settings.txt</filename>
    </modified>
    <modified>
      <diff>@@ -31,7 +31,7 @@ How to do it
 
 Just put this in your URLconf_::
 
-    (r'^site_media/(?P&lt;path&gt;.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
+    (r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
 
 ...where ``site_media`` is the URL where your media will be rooted, and
 ``/path/to/media`` is the filesystem root for your media.
@@ -60,7 +60,7 @@ listings for directories.
 
 Example::
 
-    (r'^site_media/(?P&lt;path&gt;.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
+    (r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
 
 You can customize the index view by creating a template called
 ``static/directory_index``. That template gets two objects in its context:
@@ -100,7 +100,7 @@ Do this by wrapping an ``if DEBUG`` statement around the
 ``django.views.static.serve`` inclusion. Here's a full example URLconf::
 
     from django.conf.urls.defaults import *
-    from django.conf.settings import DEBUG
+    from django.conf import settings
 
     urlpatterns = patterns('',
         (r'^/articles/2003/$', 'news.views.special_case_2003'),
@@ -109,15 +109,15 @@ Do this by wrapping an ``if DEBUG`` statement around the
         (r'^/articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/(?P&lt;day&gt;\d+)/$', 'news.views.article_detail'),
     )
 
-    if DEBUG:
+    if settings.DEBUG:
         urlpatterns += patterns('',
             (r'^site_media/(?P&lt;path&gt;.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
         )
 
-This code is straightforward. It imports the `DEBUG setting`_ and checks its
-value. If it evaluates to ``True``, then ``site_media`` will be associated with
-the ``django.views.static.serve`` view. If not (``DEBUG == False``), then the
-view won't be made available.
+This code is straightforward. It imports the settings and checks the value of
+the ``DEBUG`` setting. If it evaluates to ``True``, then ``site_media`` will be
+associated with the ``django.views.static.serve`` view. If not
+(``DEBUG == False``), then the view won't be made available.
 
 Of course, the catch here is that you'll have to remember to set ``DEBUG=False``
 in your production settings file. But you should be doing that anyway.</diff>
      <filename>docs/static_files.txt</filename>
    </modified>
    <modified>
      <diff>@@ -93,7 +93,7 @@ This simple example, taken from `chicagocrime.org`_, describes a feed of the
 latest five news items::
 
     from django.contrib.syndication.feeds import Feed
-    from django.models.chicagocrime import newsitems
+    from chicagocrime.models import NewsItem
 
     class SiteNewsFeed(Feed):
         title = &quot;Chicagocrime.org site news&quot;
@@ -101,7 +101,7 @@ latest five news items::
         description = &quot;Updates on changes and additions to chicagocrime.org.&quot;
 
         def items(self):
-            return newsitems.get_list(order_by=('-pub_date',), limit=5)
+            return NewsItem.objects.order_by('-pub_date')[:5]
 
 Note:
 
@@ -120,10 +120,11 @@ One thing's left to do. In an RSS feed, each ``&lt;item&gt;`` has a ``&lt;title&gt;``,
 put into those elements.
 
     * To specify the contents of ``&lt;title&gt;`` and ``&lt;description&gt;``, create
-      `Django templates`_ called ``feeds/sitenews_title`` and
-      ``feeds/sitenews_description``, where ``sitenews`` is the ``slug``
-      specified in the URLconf for the given feed. The RSS system renders that
-      template for each item, passing it two template context variables:
+      `Django templates`_ called ``feeds/sitenews_title.html`` and
+      ``feeds/sitenews_description.html``, where ``sitenews`` is the ``slug``
+      specified in the URLconf for the given feed. Note the ``.html`` extension
+      is required. The RSS system renders that template for each item, passing
+      it two template context variables:
 
           * ``{{ obj }}`` -- The current object (one of whichever objects you
             returned in ``items()``).
@@ -175,7 +176,7 @@ An example makes this clear. Here's the code for these beat-specific feeds::
             # check that bits has only one member.
             if len(bits) != 1:
                 raise ObjectDoesNotExist
-            return beats.get_object(beat__exact=bits[0])
+            return Beat.objects.get(beat__exact=bits[0])
 
         def title(self, obj):
             return &quot;Chicagocrime.org: Crimes for beat %s&quot; % obj.beat
@@ -187,7 +188,7 @@ An example makes this clear. Here's the code for these beat-specific feeds::
             return &quot;Crimes recently reported in police beat %s&quot; % obj.beat
 
         def items(self, obj):
-            return crimes.get_list(beat__id__exact=obj.id, order_by=(('-crime_date'),), limit=30)
+            return Crime.objects.filter(beat__id__exact=obj.id).order_by('-crime_date')[:30]
 
 Here's the basic algorithm the RSS framework follows, given this class and a
 request to the URL ``/rss/beats/0613/``:
@@ -203,8 +204,8 @@ request to the URL ``/rss/beats/0613/``:
       the beat. Note that ``get_object()`` should raise
       ``django.core.exceptions.ObjectDoesNotExist`` if given invalid
       parameters. There's no ``try``/``except`` around the
-      ``beats.get_object()`` call, because it's not necessary; that function
-      raises ``BeatDoesNotExist`` on failure, and ``BeatDoesNotExist`` is a
+      ``Beat.objects.get()`` call, because it's not necessary; that function
+      raises ``Beat.DoesNotExist`` on failure, and ``Beat.DoesNotExist`` is a
       subclass of ``ObjectDoesNotExist``. Raising ``ObjectDoesNotExist`` in
       ``get_object()`` tells Django to produce a 404 error for that request.
     * To generate the feed's ``&lt;title&gt;``, ``&lt;link&gt;`` and ``&lt;description&gt;``,
@@ -292,7 +293,7 @@ URLconf to add the extra versions.
 Here's a full example::
 
     from django.contrib.syndication.feeds import Feed
-    from django.models.chicagocrime import newsitems
+    from chicagocrime.models import NewsItem
     from django.utils.feedgenerator import Atom1Feed
 
     class RssSiteNewsFeed(Feed):
@@ -301,7 +302,7 @@ Here's a full example::
         description = &quot;Updates on changes and additions to chicagocrime.org.&quot;
 
         def items(self):
-            return newsitems.get_list(order_by=('-pub_date',), limit=5)
+            return NewsItem.objects.order_by('-pub_date')[:5]
 
     class AtomSiteNewsFeed(RssSiteNewsFeed):
         feed_type = Atom1Feed
@@ -328,7 +329,6 @@ Feed class reference
 
 This example illustrates all possible attributes and methods for a ``Feed`` class::
 
-
     from django.contrib.syndication.feeds import Feed
     from django.utils import feedgenerator
 </diff>
      <filename>docs/syndication_feeds.txt</filename>
    </modified>
    <modified>
      <diff>@@ -13,9 +13,8 @@ or CheetahTemplate_, you should feel right at home with Django's templates.
 Templates
 =========
 
-A template is simply a text file. All Django templates, by convention, have
-&quot;.html&quot; extensions, but they can generate any text-based format (HTML, XML,
-CSV, etc.).
+A template is simply a text file. It can generate any text-based format (HTML,
+XML, CSV, etc.).
 
 A template contains **variables**, which get replaced with values when the
 template is evaluated, and **tags**, which control the logic of the template.
@@ -23,7 +22,7 @@ template is evaluated, and **tags**, which control the logic of the template.
 Below is a minimal template that illustrates a few basics. Each element will be
 explained later in this document.::
 
-    {% extends &quot;base_generic&quot; %}
+    {% extends &quot;base_generic.html&quot; %}
 
     {% block title %}{{ section.title }}{% endblock %}
 
@@ -48,6 +47,8 @@ explained later in this document.::
     JavaScript and CSV. You can use the template language for any text-based
     format.
 
+    Oh, and one more thing: Making humans edit XML is masochistic!
+
 Variables
 =========
 
@@ -70,32 +71,27 @@ Use a dot (``.``) to access attributes of a variable.
 In the above example, ``{{ section.title }}`` will be replaced with the
 ``title`` attribute of the ``section`` object.
 
-In Django 0.91, if you use a variable that doesn't exist, it will be silently
-ignored; the variable will be replaced by nothingness. In the Django
-development version, if a variable doesn't exist, the template system inserts
+If you use a variable that doesn't exist, the template system will insert
 the value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''``
 (the empty string) by default.
 
-If you use a variable that doesn't exist, it will be silently ignored. The
-variable will be replaced by nothingness.
-
 See `Using the built-in reference`_, below, for help on finding what variables
 are available in a given template.
 
-You can modify variables for display by using **filters**.
-
 Filters
 =======
 
+You can modify variables for display by using **filters**.
+
 Filters look like this: ``{{ name|lower }}``. This displays the value of the
 ``{{ name }}`` variable after being filtered through the ``lower`` filter,
 which converts text to lowercase. Use a pipe (``|``) to apply a filter.
 
-Filters can be &quot;chained.&quot; The output of one filter applied to the next:
-``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents
-and then converting line breaks to ``&lt;p&gt;`` tags.
+Filters can be &quot;chained.&quot; The output of one filter is applied to the next.
+``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents,
+then converting line breaks to ``&lt;p&gt;`` tags.
 
-Certain filters take arguments. A filter argument looks like this:
+Some filters take arguments. A filter argument looks like this:
 ``{{ bio|truncatewords:&quot;30&quot; }}``. This will display the first 30 words of the
 ``bio`` variable. Filter arguments always are in double quotes.
 
@@ -156,7 +152,7 @@ engine that a child template may override those portions of the template.
 
 A child template might look like this::
 
-    {% extends &quot;base&quot; %}
+    {% extends &quot;base.html&quot; %}
 
     {% block title %}My amazing blog{% endblock %}
 
@@ -169,12 +165,12 @@ A child template might look like this::
 
 The ``{% extends %}`` tag is the key here. It tells the template engine that
 this template &quot;extends&quot; another template. When the template system evaluates
-this template, first it locates the parent -- in this case, &quot;base&quot; (note the
-lack of an &quot;.html&quot; extension in the ``{% extends %}`` tag).
+this template, first it locates the parent -- in this case, &quot;base.html&quot;.
 
-At that point, the template engine will notice the three blocks in
-``base.html`` and replace those blocks with the contents of the child template.
-Depending on the value of ``blog_entries``, the output might look like::
+At that point, the template engine will notice the three ``{% block %}`` tags
+in ``base.html`` and replace those blocks with the contents of the child
+template. Depending on the value of ``blog_entries``, the output might look
+like::
 
     &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
         &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
@@ -205,29 +201,36 @@ Note that since the child template didn't define the ``sidebar`` block, the
 value from the parent template is used instead. Content within a ``{% block %}``
 tag in a parent template is always used as a fallback.
 
-Template inheritance isn't limited to a single level. Multi-level inheritance
-is possible and, indeed, quite useful.
+You can use as many levels of inheritance as needed. One common way of using
+inheritance is the following three-level approach:
+
+    * Create a ``base.html`` template that holds the main look-and-feel of your
+      site.
+    * Create a ``base_SECTIONNAME.html`` template for each &quot;section&quot; of your
+      site. For example, ``base_news.html``, ``base_sports.html``. These
+      templates all extend ``base.html`` and include section-specific
+      styles/design.
+    * Create individual templates for each type of page, such as a news
+      article or blog entry. These templates extend the appropriate section
+      template.
+
+This approach maximizes code reuse and makes it easy to add items to shared
+content areas, such as section-wide navigation.
 
 Here are some tips for working with inheritance:
 
     * If you use ``{% extends %}`` in a template, it must be the first template
-      tag in that template.
+      tag in that template. Template inheritance won't work, otherwise.
 
     * More ``{% block %}`` tags in your base templates are better. Remember,
       child templates don't have to define all parent blocks, so you can fill
       in reasonable defaults in a number of blocks, then only define the ones
-      you need later.
+      you need later. It's better to have more hooks than fewer hooks.
 
     * If you find yourself duplicating content in a number of templates, it
       probably means you should move that content to a ``{% block %}`` in a
       parent template.
 
-    * The recommended template layout is to use three levels: a single base
-      template for the entire site, a set of mid-level templates for each
-      section of the site, and then the individual templates for each view.
-      This maximizes code reuse and makes it easier to add items to shared
-      content areas (such as section-wide navigation).
-
     * If you need to get the content of the block from the parent template,
       the ``{{ block.super }}`` variable will do the trick. This is useful
       if you want to add to the contents of a parent block instead of
@@ -243,17 +246,11 @@ wouldn't know which one of the blocks' content to use.
 Using the built-in reference
 ============================
 
-Because Django can be used to develop any sort of site, the tags, filters and
-variables available are different depending on the application. To make it
-easy to figure out what's available in a given site, the admin interface has a
-complete reference of all the template goodies available to that site. To get
-that reference, go to your Django admin interface and append ``'doc'`` onto the
-admin URL. Example: ``http://127.0.0.1/admin/doc/``. In the Django development
-version, you'll see a &quot;Documentation&quot; link in the upper right of every
-admin-site page.
+Django's admin interface includes a complete reference of all template tags and
+filters available for a given site. To see it, go to your admin interface and
+click the &quot;Documentation&quot; link in the upper right of the page.
 
-The reference is integrated into the administration interface for your site(s)
-and is divided into 4 sections: tags, filters, models, and views.
+The reference is divided into 4 sections: tags, filters, models, and views.
 
 The **tags** and **filters** sections describe all the built-in tags (in fact,
 the tag and filter references below come directly from those pages) as well as
@@ -264,13 +261,13 @@ entry here, and clicking on a URL will show you:
 
     * The name of the view function that generates that view.
     * A short description of what the view does.
-    * The **context**, or a list of variables available in the view.
+    * The **context**, or a list of variables available in the view's template.
     * The name of the template or templates that are used for that view.
 
 Each view documentation page also has a bookmarklet that you can use to jump
 from any page to the documentation page for that view.
 
-Because Django generally revolves around database objects, the **models**
+Because Django-powered sites usually use database objects, the **models**
 section of the documentation page describes each type of object in the system
 along with all the fields available on that object.
 
@@ -304,9 +301,9 @@ available to the current template -- not any parent or child templates along
 the template-inheritance path.
 
 For example, if a template ``foo.html`` has ``{% load comments %}``, a child
-template (e.g., one that has ``{% extends foo %}`` will *not* have access to
-the comments template tags and filters. The child template is responsible for
-its own ``{% load comments %}``.
+template (e.g., one that has ``{% extends &quot;foo.html&quot; %}``) will *not* have
+access to the comments template tags and filters. The child template is
+responsible for its own ``{% load comments %}``.
 
 This is a feature for the sake of maintainability and sanity.
 
@@ -366,10 +363,10 @@ extends
 
 Signal that this template extends a parent template.
 
-This tag may be used in two ways: ``{% extends &quot;base&quot; %}`` (with quotes) uses
-the literal value &quot;base&quot; as the name of the parent template to extend, or ``{%
-extends variable %}`` uses the value of ``variable`` as the name of the parent
-template to extend.
+This tag may be used in two ways: ``{% extends &quot;base.html&quot; %}`` (with quotes)
+uses the literal value &quot;base.html&quot; as the name of the parent template to
+extend, or ``{% extends variable %}`` uses the value of ``variable`` as the
+name of the parent template to extend.
 
 See `Template inheritance`_ for more information.
 
@@ -489,7 +486,7 @@ ifchanged
 
 Check if a value has changed from the last iteration of a loop.
 
-The 'ifchanged' block tag is used within a loop. It checks its own rendered
+The ``ifchanged`` block tag is used within a loop. It checks its own rendered
 contents against its previous state and only displays its content if the value
 has changed::
 
@@ -533,9 +530,9 @@ Loads a template and renders it with the current context. This is a way of
 The template name can either be a variable or a hard-coded (quoted) string,
 in either single or double quotes.
 
-This example includes the contents of the template ``&quot;foo/bar&quot;``::
+This example includes the contents of the template ``&quot;foo/bar.html&quot;``::
 
-    {% include &quot;foo/bar&quot; %}
+    {% include &quot;foo/bar.html&quot; %}
 
 This example includes the contents of the template whose name is contained in
 the variable ``template_name``::
@@ -548,9 +545,9 @@ including it. This example produces the output ``&quot;Hello, John&quot;``:
     * Context: variable ``person`` is set to ``&quot;john&quot;``.
     * Template::
 
-        {% include &quot;name_snippet&quot; %}
+        {% include &quot;name_snippet.html&quot; %}
 
-    * The ``name_snippet`` template::
+    * The ``name_snippet.html`` template::
 
         Hello, {{ person }}
 
@@ -693,8 +690,6 @@ i.e.::
 spaceless
 ~~~~~~~~~
 
-**New in Django development version.**
-
 Normalizes whitespace between HTML tags to a single space. This includes tab
 characters and newlines.
 
@@ -769,7 +764,7 @@ to a maximum value, and then applies that ratio to a constant.
 
 For example::
 
-    &lt;img src='bar.gif' height='10' width='{% widthratio this_value max_value 100 %}' /&gt;
+    &lt;img src=&quot;bar.gif&quot; height=&quot;10&quot; width=&quot;{% widthratio this_value max_value 100 %}&quot; /&gt;
 
 Above, if ``this_value`` is 175 and ``max_value`` is 200, the the image in the
 above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5
@@ -844,13 +839,14 @@ Escapes a string's HTML. Specifically, it makes these replacements:
     * ``&quot;&amp;&quot;`` to ``&quot;&amp;amp;&quot;``
     * ``&lt;`` to ``&quot;&amp;lt;&quot;``
     * ``&gt;`` to ``&quot;&amp;gt;&quot;``
-    * ``'&quot;'`` (double quote) to ``&quot;&amp;quot;&quot;``
+    * ``'&quot;'`` (double quote) to ``'&amp;quot;'``
+    * ``&quot;'&quot;`` (single quote) to ``'&amp;#39;'``
 
 filesizeformat
 ~~~~~~~~~~~~~~
 
-Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
-bytes, etc).
+Format the value like a 'human-readable' file size (i.e. ``'13 KB'``,
+``'4.1 MB'``, ``'102 bytes'``, etc).
 
 first
 ~~~~~
@@ -898,12 +894,12 @@ Returns a boolean of whether the value's length is the argument.
 linebreaks
 ~~~~~~~~~~
 
-Converts newlines into &lt;p&gt; and &lt;br /&gt;s.
+Converts newlines into ``&lt;p&gt;`` and ``&lt;br /&gt;``s.
 
 linebreaksbr
 ~~~~~~~~~~~~
 
-Converts newlines into &lt;br /&gt;s.
+Converts newlines into ``&lt;br /&gt;``s.
 
 linenumbers
 ~~~~~~~~~~~
@@ -941,7 +937,11 @@ any string.
 pluralize
 ~~~~~~~~~
 
-Returns 's' if the value is not 1, for '1 vote' vs. '2 votes'.
+Returns ``'s'`` if the value is not 1.
+
+Example::
+
+    You have {{ num_messages }} message{{ num_messages|pluralize }}.
 
 pprint
 ~~~~~~</diff>
      <filename>docs/templates.txt</filename>
    </modified>
    <modified>
      <diff>@@ -55,13 +55,13 @@ Compiling a string
 ------------------
 
 The easiest way to create a ``Template`` object is by instantiating it
-directly. The class lives at ``django.core.template.Template``. The constructor
+directly. The class lives at ``django.template.Template``. The constructor
 takes one argument -- the raw template code::
 
-    &gt;&gt;&gt; from django.core.template import Template
+    &gt;&gt;&gt; from django.template import Template
     &gt;&gt;&gt; t = Template(&quot;My name is {{ my_name }}.&quot;)
     &gt;&gt;&gt; print t
-    &lt;django.core.template.Template instance&gt;
+    &lt;django.template.Template instance&gt;
 
 .. admonition:: Behind the scenes
 
@@ -77,12 +77,12 @@ Rendering a context
 
 Once you have a compiled ``Template`` object, you can render a context -- or
 multiple contexts -- with it. The ``Context`` class lives at
-``django.core.template.Context``, and the constructor takes one (optional)
+``django.template.Context``, and the constructor takes one (optional)
 argument: a dictionary mapping variable names to variable values. Call the
 ``Template`` object's ``render()`` method with the context to &quot;fill&quot; the
 template::
 
-    &gt;&gt;&gt; from django.core.template import Context, Template
+    &gt;&gt;&gt; from django.template import Context, Template
     &gt;&gt;&gt; t = Template(&quot;My name is {{ my_name }}.&quot;)
 
     &gt;&gt;&gt; c = Context({&quot;my_name&quot;: &quot;Adrian&quot;})
@@ -110,7 +110,7 @@ logic.
 
 Here are a few examples::
 
-    &gt;&gt;&gt; from django.core.template import Context, Template
+    &gt;&gt;&gt; from django.template import Context, Template
     &gt;&gt;&gt; t = Template(&quot;My name is {{ person.first_name }}.&quot;)
     &gt;&gt;&gt; d = {&quot;person&quot;: {&quot;first_name&quot;: &quot;Joe&quot;, &quot;last_name&quot;: &quot;Johnson&quot;}}
     &gt;&gt;&gt; t.render(Context(d))
@@ -139,10 +139,10 @@ Method lookups are slightly more complex than the other lookup types. Here are
 some things to keep in mind:
 
     * If, during the method lookup, a method raises an exception, the exception
-      will be propagated, unless the exception subclasses
-      ``django.core.template.SilentVariableFailure``. If the exception
-      subclasses ``SilentVariableFailure``, the variable will render as an
-      empty string. Example::
+      will be propagated, unless the exception has an attribute
+      ``silent_variable_failure`` whose value is ``True``. If the exception
+      *does* have a ``silent_variable_failure`` attribute, the variable will
+      render as an empty string. Example::
 
         &gt;&gt;&gt; t = Template(&quot;My name is {{ person.first_name }}.&quot;)
         &gt;&gt;&gt; class PersonClass3:
@@ -154,15 +154,21 @@ some things to keep in mind:
         ...
         AssertionError: foo
 
-        &gt;&gt;&gt; from django.core.template import SilentVariableFailure
-        &gt;&gt;&gt; class SilentAssertionError(SilentVariableFailure): pass
+        &gt;&gt;&gt; class SilentAssertionError(Exception):
+        ...     silent_variable_failure = True
         &gt;&gt;&gt; class PersonClass4:
         ...     def first_name(self):
-        ...         raise SilentAssertionError, &quot;foo&quot;
+        ...         raise SilentAssertionError
         &gt;&gt;&gt; p = PersonClass4()
         &gt;&gt;&gt; t.render(Context({&quot;person&quot;: p}))
         &quot;My name is .&quot;
 
+      Note that ``django.core.exceptions.ObjectDoesNotExist``, which is the
+      base class for all Django database API ``DoesNotExist`` exceptions, has
+      ``silent_variable_failure = True``. So if you're using Django templates
+      with Django model objects, any ``DoesNotExist`` exception will fail
+      silently.
+
     * A method call will only work if the method has no required arguments.
       Otherwise, the system will move to the next lookup type (list-index
       lookup).
@@ -203,9 +209,9 @@ This applies to any level of lookup::
     &gt;&gt;&gt; t.render(c)
     &quot;My name is Stan .&quot;
 
-In the Django development version, if a variable doesn't exist, the template
-system inserts the value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which
-is set to ``''`` (the empty string) by default.
+If a variable doesn't exist, the template system inserts the value of the
+``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
+string) by default.
 
 Playing with Context objects
 ----------------------------
@@ -227,7 +233,7 @@ dictionary syntax::
 
 A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it.
 If you ``pop()`` too much, it'll raise
-``django.core.template.ContextPopException``::
+``django.template.ContextPopException``::
 
     &gt;&gt;&gt; c = Context()
     &gt;&gt;&gt; c['foo'] = 'first level'
@@ -244,20 +250,20 @@ If you ``pop()`` too much, it'll raise
     &gt;&gt;&gt; c.pop()
     Traceback (most recent call last):
     ...
-    django.core.template.ContextPopException
+    django.template.ContextPopException
 
 Using a ``Context`` as a stack comes in handy in some custom template tags, as
 you'll see below.
 
-Subclassing Context: DjangoContext
-----------------------------------
+Subclassing Context: RequestContext
+-----------------------------------
 
 Django comes with a special ``Context`` class,
-``django.core.extensions.DjangoContext``, that acts slightly differently than
-the normal ``django.core.template.Context``. The first difference is that takes
+``django.template.RequestContext``, that acts slightly differently than
+the normal ``django.template.Context``. The first difference is that takes
 an `HttpRequest object`_ as its first argument. For example::
 
-    c = DjangoContext(request, {
+    c = RequestContext(request, {
         'foo': 'bar',
     }
 
@@ -277,16 +283,16 @@ variable to the context and a second processor adds a variable with the same
 name, the second will override the first. The default processors are explained
 below.
 
-Also, you can give ``DjangoContext`` a list of additional processors, using the
+Also, you can give ``RequestContext`` a list of additional processors, using the
 optional, third positional argument, ``processors``. In this example, the
-``DjangoContext`` instance gets a ``ip_address`` variable::
+``RequestContext`` instance gets a ``ip_address`` variable::
 
     def ip_address_processor(request):
         return {'ip_address': request.META['REMOTE_ADDR']}
 
     def some_view(request):
         # ...
-        return DjangoContext(request, {
+        return RequestContext(request, {
             'foo': 'bar',
         }, [ip_address_processor])
 
@@ -299,7 +305,7 @@ django.core.context_processors.auth
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
-``DjangoContext`` will contain these three variables:
+``RequestContext`` will contain these three variables:
 
     * ``user`` -- An ``auth.User`` instance representing the currently
       logged-in user (or an ``AnonymousUser`` instance, if the client isn't
@@ -317,7 +323,7 @@ django.core.context_processors.debug
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
-``DjangoContext`` will contain these two variables -- but only if your
+``RequestContext`` will contain these two variables -- but only if your
 ``DEBUG`` setting is set to ``True`` and the request's IP address
 (``request.META['REMOTE_ADDR']``) is in the ``INTERNAL_IPS`` setting:
 
@@ -331,7 +337,7 @@ django.core.context_processors.i18n
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
-``DjangoContext`` will contain these two variables:
+``RequestContext`` will contain these two variables:
 
     * ``LANGUAGES`` -- The value of the `LANGUAGES setting`_.
     * ``LANGUAGE_CODE`` -- ``request.LANGUAGE_CODE``, if it exists. Otherwise,
@@ -346,8 +352,6 @@ See the `internationalization docs`_ for more.
 django.core.context_processors.request
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-**New in Django development version**
-
 If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
 ``DjangoContext`` will contain a variable ``request``, which is the current
 `HttpRequest object`_. Note that this processor is not enabled by default;
@@ -357,15 +361,8 @@ Loading templates
 -----------------
 
 Generally, you'll store templates in files on your filesystem rather than using
-the low-level ``Template`` API yourself. Save templates in a file with an
-&quot;.html&quot; extension in a directory specified as a **template directory**.
-
-If you don't like the requirement that templates have an &quot;.html&quot; extension,
-change your ``TEMPLATE_FILE_EXTENSION`` setting. It's set to ``&quot;.html&quot;`` by
-default.
-
-Also, the .html extension doesn't mean templates can contain only HTML. They
-can contain whatever textual content you want.
+the low-level ``Template`` API yourself. Save templates in a directory
+specified as a **template directory**.
 
 The TEMPLATE_DIRS setting
 ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -380,7 +377,8 @@ that contain full paths to your template directory(ies). Example::
     )
 
 Your templates can go anywhere you want, as long as the directories and
-templates are readable by the Web server.
+templates are readable by the Web server. They can have any extension you want,
+such as ``.html`` or ``.txt``, or they can have no extension at all.
 
 Note that these paths should use Unix-style forward slashes, even on Windows.
 
@@ -389,23 +387,24 @@ The Python API
 
 Django has two ways to load templates from files:
 
-``django.core.template.loader.get_template(template_name)``
+``django.template.loader.get_template(template_name)``
     ``get_template`` returns the compiled template (a ``Template`` object) for
     the template with the given name. If the template doesn't exist, it raises
-    ``django.core.template.TemplateDoesNotExist``.
+    ``django.template.TemplateDoesNotExist``.
 
-``django.core.template.loader.select_template(template_name_list)``
+``django.template.loader.select_template(template_name_list)``
     ``select_template`` is just like ``get_template``, except it takes a list
     of template names. Of the list, it returns the first template that exists.
 
-For example, if you call ``get_template(&quot;story_detail&quot;)`` and have the above
-``TEMPLATE_DIRS`` setting, here are the files Django will look for, in order:
+For example, if you call ``get_template('story_detail.html')`` and have the
+above ``TEMPLATE_DIRS`` setting, here are the files Django will look for, in
+order:
 
     * ``/home/html/templates/lawrence.com/story_detail.html``
     * ``/home/html/templates/default/story_detail.html``
 
-If you call ``select_template([&quot;story_253_detail&quot;, &quot;story_detail&quot;])``, here's
-what Django will look for:
+If you call ``select_template(['story_253_detail.html', 'story_detail.html'])``,
+here's what Django will look for:
 
     * ``/home/html/templates/lawrence.com/story_253_detail.html``
     * ``/home/html/templates/default/story_253_detail.html``
@@ -416,10 +415,10 @@ When Django finds a template that exists, it stops looking.
 
 .. admonition:: Tip
 
-    You can use ``select_template`` for super-flexible &quot;templatability.&quot; For
+    You can use ``select_template()`` for super-flexible &quot;templatability.&quot; For
     example, if you've written a news story and want some stories to have
     custom templates, use something like
-    ``select_template([&quot;story_%s_detail&quot; % story.id, &quot;story_detail&quot;])``.
+    ``select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])``.
     That'll allow you to use a custom template for an individual story, with a
     fallback template for stories that don't have custom templates.
 
@@ -435,21 +434,30 @@ single directory gets messy.
 
 To load a template that's within a subdirectory, just use a slash, like so::
 
-    get_template(&quot;news/story_detail&quot;)
+    get_template('news/story_detail.html')
+
+Using the same ``TEMPLATE_DIRS`` setting from above, this example
+``get_template()`` call will attempt to load the following templates:
+
+    * ``/home/html/templates/lawrence.com/news/story_detail.html``
+    * ``/home/html/templates/default/news/story_detail.html``
 
 Loader types
 ~~~~~~~~~~~~
 
 By default, Django uses a filesystem-based template loader, but Django comes
-with a few other template loaders. They're disabled by default, but you can
-activate them by editing your ``TEMPLATE_LOADERS`` setting.
-``TEMPLATE_LOADERS`` should be a tuple of strings, where each string represents
-a template loader. Here are the built-in template loaders:
+with a few other template loaders, which know how to load templates from other
+sources.
+
+These other loaders are disabled by default, but you can activate them by
+editing your ``TEMPLATE_LOADERS`` setting. ``TEMPLATE_LOADERS`` should be a
+tuple of strings, where each string represents a template loader. Here are the
+template loaders that come with Django:
 
-``django.core.template.loaders.filesystem.load_template_source``
+``django.template.loaders.filesystem.load_template_source``
     Loads templates from the filesystem, according to ``TEMPLATE_DIRS``.
 
-``django.core.template.loaders.app_directories.load_template_source``
+``django.template.loaders.app_directories.load_template_source``
     Loads templates from Django apps on the filesystem. For each app in
     ``INSTALLED_APPS``, the loader looks for a ``templates`` subdirectory. If
     the directory exists, Django looks for templates in there.
@@ -461,7 +469,7 @@ a template loader. Here are the built-in template loaders:
 
         INSTALLED_APPS = ('myproject.polls', 'myproject.music')
 
-    ...then ``get_template(&quot;foo&quot;)`` will look for templates in these
+    ...then ``get_template('foo.html')`` will look for templates in these
     directories, in this order:
 
         * ``/path/to/myproject/polls/templates/foo.html``
@@ -471,7 +479,7 @@ a template loader. Here are the built-in template loaders:
     It caches a list of which ``INSTALLED_APPS`` packages have a ``templates``
     subdirectory.
 
-``django.core.template.loaders.eggs.load_template_source``
+``django.template.loaders.eggs.load_template_source``
     Just like ``app_directories`` above, but it loads templates from Python
     eggs rather than from the filesystem.
 
@@ -521,15 +529,15 @@ To be a valid tag library, the module contain a module-level variable named
 ``register`` that is a ``template.Library`` instance, in which all the tags and
 filters are registered. So, near the top of your module, put the following::
 
-    from django.core import template
+    from django import template
 
     register = template.Library()
 
 .. admonition:: Behind the scenes
 
     For a ton of examples, read the source code for Django's default filters
-    and tags. They're in ``django/core/template/defaultfilters.py`` and
-    ``django/core/template/defaulttags.py``, respectively.
+    and tags. They're in ``django/template/defaultfilters.py`` and
+    ``django/template/defaulttags.py``, respectively.
 
 Writing custom template filters
 -------------------------------
@@ -603,7 +611,7 @@ process: compiling and rendering. To define a custom template tag, you specify
 how the compilation works and how the rendering works.
 
 When Django compiles a template, it splits the raw template text into
-''nodes''. Each node is an instance of ``django.core.template.Node`` and has
+''nodes''. Each node is an instance of ``django.template.Node`` and has
 a ``render()`` method. A compiled template is, simply, a list of ``Node``
 objects. When you call ``render()`` on a compiled template object, the template
 calls ``render()`` on each ``Node`` in its node list, with the given context.
@@ -632,7 +640,7 @@ else. In our case, let's say the tag should be used like this::
 The parser for this function should grab the parameter and create a ``Node``
 object::
 
-    from django.core import template
+    from django import template
     def do_current_time(parser, token):
         try:
             # Splitting by None == splitting by spaces.
@@ -652,7 +660,7 @@ Notes:
       example, it's ``'current_time &quot;%Y-%M-%d %I:%M %p&quot;'``.
 
     * This function is responsible for raising
-      ``django.core.template.TemplateSyntaxError``, with helpful messages, for
+      ``django.template.TemplateSyntaxError``, with helpful messages, for
       any syntax error.
 
     * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable.
@@ -679,7 +687,7 @@ has a ``render()`` method.
 
 Continuing the above example, we need to define ``CurrentTimeNode``::
 
-    from django.core import template
+    from django import template
     import datetime
     class CurrentTimeNode(template.Node):
         def __init__(self, format_string):
@@ -817,7 +825,7 @@ Here's how the standard ``{% comment %}`` tag is implemented::
             return ''
 
 ``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It
-returns an instance of ``django.core.template.NodeList``, which is a list of
+returns an instance of ``django.template.NodeList``, which is a list of
 all ``Node`` objects that the parser encountered ''before'' it encountered
 any of the tags named in the tuple.
 
@@ -867,4 +875,4 @@ The only new concept here is the ``self.nodelist.render(context)`` in
 
 For more examples of complex rendering, see the source code for ``{% if %}``,
 ``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
-``django/core/template/defaulttags.py``.
+``django/template/defaulttags.py``.</diff>
      <filename>docs/templates_python.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,35 +2,41 @@
 Writing your first Django app, part 1
 =====================================
 
-By Adrian Holovaty &lt;holovaty@gmail.com&gt;
-
 Let's learn by example.
 
-Throughout this tutorial, we'll walk you through the creation of a simple Web
-poll application.
+Throughout this tutorial, we'll walk you through the creation of a basic
+blogging application.
 
 It'll consist of two parts:
 
-* A public site that lets people vote in polls and view poll results.
-* An admin site that lets you add, change and delete polls behind the scenes.
+    * A public site that lets people read your blog entries and submit
+      comments.
+    * An admin site that lets you add, change and delete entries and comments.
 
-We'll assume you have `Django installed`_ already.
+We'll assume you have `Django installed`_ already. You can tell Django is
+installed by running the Python interactive interpreter and typing
+``import django``. If that command runs successfully, with no errors, Django is
+installed.
 
 .. _`Django installed`: http://www.djangoproject.com/documentation/install/
 
-Initial setup
-=============
+Creating a project
+==================
 
 If this is your first time using Django, you'll have to take care of some
-initial setup.
+initial setup. Namely, you'll need to auto-generate some code that establishes
+a Django *project* -- a collection of settings for an instance of Django,
+including database configuration, Django-specific options and
+application-specific settings.
 
-Run the command ``django-admin.py startproject myproject``. That'll create a
-``myproject`` directory in your current directory.
+From the command line, ``cd`` into a directory where you'd like to store your
+code, then run the command ``django-admin.py startproject mysite``. This
+will create a ``mysite`` directory in your current directory.
 
 (``django-admin.py`` should be on your system path if you installed Django via
-its setup.py utility. If it's not on your path, you can find it in
+its ``setup.py`` utility. If it's not on your path, you can find it in
 ``site-packages/django/bin``; consider symlinking to it from some place
-on your path, such as /usr/local/bin.)
+on your path, such as ``/usr/local/bin``.)
 
 .. admonition:: Where should this code live?
 
@@ -44,11 +50,9 @@ on your path, such as /usr/local/bin.)
     Put your code in some directory **outside** of the document root, such as
     ``/home/mycode``.
 
-A project is a collection of settings for an instance of Django -- including
-database configuration, Django-specific options and application-specific
-settings. Let's look at what ``startproject`` created::
+Let's look at what ``startproject`` created::
 
-    myproject/
+    mysite/
         __init__.py
         manage.py
         settings.py
@@ -56,50 +60,62 @@ settings. Let's look at what ``startproject`` created::
 
 These files are:
 
+    * ``__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.)
     * ``manage.py``: A command-line utility that lets you interact with this
       Django project in various ways.
     * ``settings.py``: Settings/configuration for this Django project.
     * ``urls.py``: The URL declarations for this Django project; a &quot;table of
       contents&quot; of your Django-powered site.
 
+.. _more on packages: http://docs.python.org/tut/node8.html#packages
+
 The development server
 ----------------------
 
-Change into the ``myproject`` directory, if you haven't already, and run the
-command ``python manage.py runserver``. You'll see the following output on the
-command line::
+Let's verify this worked. Change into the ``mysite`` directory, if you
+haven't already, and run the command ``python manage.py runserver``. You'll see
+the following output on the command line::
 
     Validating models...
     0 errors found.
 
-    Starting server on port 8000 with settings module 'myproject.settings'.
-    Go to http://127.0.0.1:8000/ for Django.
+    Django version 0.92, using settings 'mysite.settings'
+    Development server is running at http://127.0.0.1:8000/
     Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
 
-(If you get an error about ``DATABASE_ENGINE``, edit your ``settings.py`` file
-to change the ``DATABASE_ENGINE`` setting to point to the correct database, and
-make sure you have the right database libraries installed -- such as PostgreSQL's
-psycopg or MySQL's MySQLdb.)
-
 You've started the Django development server, a lightweight, pure-Python Web
-server that builds on the BaseHTTPServer included in Python's standard library.
-We've included this with Django so you can develop things rapidly, without
-having to deal with configuring Apache until you're ready for production.
+server. We've included this with Django so you can develop things rapidly,
+without having to deal with configuring a production server -- such as
+Apache -- until you're ready for production.
+
+Now's a good time to note: DON'T use this server in anything resembling a
+production environment. It's intended only for use while developing.
 
-DON'T use this server in anything resembling a production environment. It's
-intended only for use while developing.
+Now that the server's running, visit http://127.0.0.1:8000/ with your Web
+browser. You'll see a &quot;Welcome to Django&quot; page, in pleasant, light-blue pastel.
+It worked!
 
 .. admonition:: Changing the port
 
     By default, the ``runserver`` command starts the development server on port
     8000. If you want to change the server's port, pass it as a command-line
-    argument::
+    argument. For instance, this command starts the server on port 8080::
 
         python manage.py runserver 8080
 
-Now that the server's running, visit http://127.0.0.1:8000/ with your Web
-browser. You'll see a &quot;Welcome to Django&quot; page, in pleasant, light-blue pastel.
-It worked!
+    Full docs for the development server are at `django-admin documentation`_.
+
+.. _django-admin documentation: http://www.djangoproject.com/documentation/django_admin/
+
+Your first page
+---------------
+
+Let's create our first Django-powered Web page, a classic &quot;hello world&quot; example.
+
+
+
 
 Database setup
 --------------
@@ -124,30 +140,52 @@ database's connection parameters:
     point. Do that with &quot;``CREATE DATABASE database_name;``&quot; within your
     database's interactive prompt.
 
-Run the following command to initialize your database with Django's core
-database tables::
+While you're editing ``settings.py``, take note of the ``INSTALLED_APPS``
+setting towards the bottom of the file. That variable holds the names of all
+Django applications that are activated in this Django instance. Apps can be
+used in multiple projects, and you can package and distribute them for use
+by others in their projects.
+
+By default, ``INSTALLED_APPS`` contains the following apps, all of which come
+with Django:
+
+    * ``django.contrib.auth`` -- An authentication system.
+    * ``django.contrib.contenttypes`` -- A framework for content types.
+    * ``django.contrib.sessions`` -- A session framework.
+    * ``django.contrib.sites`` -- A framework for managing multiple sites
+      with one Django installation.
+
+These applications are included by default as a convenience for the common case.
 
-    python manage.py init
+Each of these applications makes use of at least one database table, though,
+so we need to create the tables in the database before we can use them. To do
+that, run the following command::
 
-If you don't see any errors, it worked.
+    python manage.py syncdb
+
+The ``syncdb`` command looks at the ``INSTALLED_APPS`` setting and creates any
+necessary database tables according to the database settings in your
+``settings.py`` file. You'll see a message for each database table it creates,
+and you'll get a prompt asking you if you'd like to create a superuser account
+for the authentication system. Go ahead and do that.
 
 If you're interested, run the command-line client for your database and type
 ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
 display the tables Django created.
 
-.. admonition:: About those database tables
+.. admonition:: For the minimalists
 
-    The tables created by ``manage.py init`` are for sessions, authentication
-    and other features Django provides. The next release of Django will have
-    a &quot;lite&quot; version of the ``init`` command that won't install any database
-    tables if you don't want them.
+    Like we said above, the default applications are included for the common
+    case, but not everybody needs them. If you don't need any or all of them,
+    feel free to comment-out or delete the appropriate line(s) from
+    ``INSTALLED_APPS`` before running ``syncdb``. The ``syncdb`` command will
+    only create tables for apps in ``INSTALLED_APPS``.
 
 Creating models
 ===============
 
 Now that your environment -- a &quot;project&quot; -- is set up, you're set to start
-doing work. (You won't have to take care of that boring administrative stuff
-again.)
+doing work.
 
 Each application you write in Django consists of a Python package, somewhere
 on your `Python path`_, that follows a certain convention. Django comes with a
@@ -162,12 +200,12 @@ so you can focus on writing code rather than creating directories.
     configuration and apps for a particular Web site. A project can contain
     multiple apps. An app can be in multiple projects.
 
-In this tutorial, we'll create our poll app in the ``myproject`` directory,
+In this tutorial, we'll create our poll app in the ``mysite`` directory,
 for simplicity. As a consequence, the app will be coupled to the project --
-that is, Python code within the poll app will refer to ``myproject.polls``.
+that is, Python code within the poll app will refer to ``mysite.polls``.
 Later in this tutorial, we'll discuss decoupling your apps for distribution.
 
-To create your app, make sure you're in the ``myproject`` directory and type
+To create your app, make sure you're in the ``mysite`` directory and type
 this command::
 
     python manage.py startapp polls
@@ -176,9 +214,7 @@ That'll create a directory ``polls``, which is laid out like this::
 
     polls/
         __init__.py
-        models/
-            __init__.py
-            polls.py
+        models.py
         views.py
 
 This directory structure will house the poll application.
@@ -198,28 +234,28 @@ a question and a publication date. A choice has two fields: the text of the
 choice and a vote tally. Each choice is associated with a poll.
 
 These concepts are represented by simple Python classes. Edit the
-``polls/models/polls.py`` file so it looks like this::
+``polls/models.py`` file so it looks like this::
 
-    from django.core import meta
+    from django.db import models
 
-    class Poll(meta.Model):
-        question = meta.CharField(maxlength=200)
-        pub_date = meta.DateTimeField('date published')
+    class Poll(models.Model):
+        question = models.CharField(maxlength=200)
+        pub_date = models.DateTimeField('date published')
 
-    class Choice(meta.Model):
-        poll = meta.ForeignKey(Poll)
-        choice = meta.CharField(maxlength=200)
-        votes = meta.IntegerField()
+    class Choice(models.Model):
+        poll = models.ForeignKey(Poll)
+        choice = models.CharField(maxlength=200)
+        votes = models.IntegerField()
 
 The code is straightforward. Each model is represented by a class that
-subclasses ``django.core.meta.Model``. Each model has a number of class
+subclasses ``django.db.models.Model``. Each model has a number of class
 variables, each of which represents a database field in the model.
 
-Each field is represented by an instance of a ``meta.*Field`` class -- e.g.,
-``meta.CharField`` for character fields and ``meta.DateTimeField`` for
+Each field is represented by an instance of a ``models.*Field`` class -- e.g.,
+``models.CharField`` for character fields and ``models.DateTimeField`` for
 datetimes. This tells Django what type of data each field holds.
 
-The name of each ``meta.*Field`` instance (e.g. ``question`` or ``pub_date`` )
+The name of each ``models.*Field`` instance (e.g. ``question`` or ``pub_date`` )
 is the field's name, in machine-friendly format. You'll use this value in your
 Python code, and your database will use it as the column name.
 
@@ -230,11 +266,11 @@ the machine-readable name. In this example, we've only defined a human-readable
 name for ``Poll.pub_date``. For all other fields in this model, the field's
 machine-readable name will suffice as its human-readable name.
 
-Some ``meta.*Field`` classes have required elements. ``meta.CharField``, for
-example, requires that you give it a ``maxlength``. That's used not only in the
-database schema, but in validation, as we'll soon see.
+Some ``Field`` classes have required elements. ``CharField``, for example,
+requires that you give it a ``maxlength``. That's used not only in the database
+schema, but in validation, as we'll soon see.
 
-Finally, note a relationship is defined, using ``meta.ForeignKey``. That tells
+Finally, note a relationship is defined, using ``models.ForeignKey``. That tells
 Django each Choice is related to a single Poll. Django supports all the common
 database relationships: many-to-ones, many-to-manys and one-to-ones.
 
@@ -259,28 +295,29 @@ But first we need to tell our project that the ``polls`` app is installed.
     Django installation.
 
 Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting
-to include the string ``'myproject.polls'``. So it'll look like this::
+to include the string ``'mysite.polls'``. So it'll look like this::
 
     INSTALLED_APPS = (
-        'myproject.polls',
+        'django.contrib.auth',
+        'django.contrib.contenttypes',
+        'django.contrib.sessions',
+        'django.contrib.sites',
+        'mysite.polls'
     )
 
-(Don't forget the trailing comma, because of Python's rule about single-value
-tuples: Without a trailing comma, Python wouldn't know this was a tuple.)
-
-Now Django knows ``myproject`` includes the ``polls`` app. Let's run another command::
+Now Django knows ``mysite`` includes the ``polls`` app. Let's run another command::
 
     python manage.py sql polls
 
 You should see the following (the CREATE TABLE SQL statements for the polls app)::
 
     BEGIN;
-    CREATE TABLE &quot;polls_polls&quot; (
+    CREATE TABLE &quot;polls_poll&quot; (
         &quot;id&quot; serial NOT NULL PRIMARY KEY,
         &quot;question&quot; varchar(200) NOT NULL,
         &quot;pub_date&quot; timestamp with time zone NOT NULL
     );
-    CREATE TABLE &quot;polls_choices&quot; (
+    CREATE TABLE &quot;polls_choice&quot; (
         &quot;id&quot; serial NOT NULL PRIMARY KEY,
         &quot;poll_id&quot; integer NOT NULL REFERENCES &quot;polls_polls&quot; (&quot;id&quot;),
         &quot;choice&quot; varchar(200) NOT NULL,
@@ -291,12 +328,12 @@ You should see the following (the CREATE TABLE SQL statements for the polls app)
 Note the following:
 
     * Table names are automatically generated by combining the name of the app
-      (``polls``) with a plural version of the object name (polls and choices).
-      (You can override this behavior.)
+      (``polls``) and the lowercase name of the model -- ``poll`` and
+      ``choice``. (You can override this behavior.)
 
     * Primary keys (IDs) are added automatically. (You can override this, too.)
 
-    * Django appends ``&quot;_id&quot;`` to the foreign key field name, by convention.
+    * By convention, Django appends ``&quot;_id&quot;`` to the foreign key field name.
       Yes, you can override this, as well.
 
     * The foreign key relationship is made explicit by a ``REFERENCES`` statement.
@@ -306,12 +343,18 @@ Note the following:
       ``integer primary key`` (SQLite) are handled for you automatically. Same
       goes for quoting of field names -- e.g., using double quotes or single
       quotes. The author of this tutorial runs PostgreSQL, so the example
-      output is inPostgreSQL syntax.
+      output is in PostgreSQL syntax.
+
+    * The `sql` command doesn't actually run the SQL in your database - it just
+      prints it to the screen so that you can see what SQL Django thinks is required.
+      If you wanted to, you could copy and paste this SQL into your database prompt.
+      However, as we will see shortly, Django provides an easier way of committing
+      the SQL to the database.
 
 If you're interested, also run the following commands:
 
-    * ``python manage.py sqlinitialdata polls`` -- Outputs the initial-data
-      inserts required for Django's admin framework.
+    * ``python manage.py sqlinitialdata polls`` -- Outputs any initial data
+      required for Django's admin framework and your models.
 
     * ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP
       TABLE`` statements for this app, according to which tables already exist
@@ -320,20 +363,21 @@ If you're interested, also run the following commands:
     * ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
       statements for this app.
 
-    * ``python manage.py sqlall polls`` -- A combination of 'sql' and
-      'sqlinitialdata'.
+    * ``python manage.py sqlall polls`` -- A combination of all the SQL from
+      the 'sql', 'sqlinitialdata', and 'sqlindexes' commands.
 
 Looking at the output of those commands can help you understand what's actually
 happening under the hood.
 
-Now, run this command to create the database tables for the polls app
-automatically::
+Now, run ``syncdb`` again to create those model tables in your database::
 
-    python manage.py install polls
+    python manage.py syncdb
 
-Behind the scenes, all that command does is take the output of
-``python manage.py sqlall polls`` and execute it in the database pointed-to by
-your Django settings file.
+The ``syncdb`` command runs the sql from 'sqlall' on your database for all apps
+in ``INSTALLED_APPS`` that don't already exist in your database. This creates
+all the tables, initial data and indexes for any apps you have added to your
+project since the last time you ran syncdb. ``syncdb`` can be called as often
+as you like, and it will only ever create the tables that don't exist.
 
 Read the `django-admin.py documentation`_ for full information on what the
 ``manage.py`` utility can do.
@@ -352,10 +396,10 @@ We're using this instead of simply typing &quot;python&quot;, because ``manage.py`` sets
 up the project's environment for you. &quot;Setting up the environment&quot; involves two
 things:
 
-    * Putting ``myproject`` on ``sys.path``. For flexibility, several pieces of
+    * Putting ``mysite`` on ``sys.path``. For flexibility, several pieces of
       Django refer to projects in Python dotted-path notation (e.g.
-      ``'myproject.polls.models'``). In order for this to work, the
-      ``myproject`` package has to be on ``sys.path``.
+      ``'mysite.polls.models'``). In order for this to work, the
+      ``mysite`` package has to be on ``sys.path``.
 
       We've already seen one example of this: the ``INSTALLED_APPS`` setting is
       a list of packages in dotted-path notation.
@@ -366,25 +410,24 @@ things:
 .. admonition:: Bypassing manage.py
 
     If you'd rather not use ``manage.py``, no problem. Just make sure
-    ``myproject`` is at the root level on the Python path (i.e.,
-    ``import myproject`` works) and set the ``DJANGO_SETTINGS_MODULE``
-    environment variable to ``myproject.settings``.
+    ``mysite`` is at the root level on the Python path (i.e.,
+    ``import mysite`` works) and set the ``DJANGO_SETTINGS_MODULE``
+    environment variable to ``mysite.settings``.
 
     For more information on all of this, see the `django-admin.py documentation`_.
 
 Once you're in the shell, explore the database API::
 
-    # Modules are dynamically created within django.models.
-    # Their names are plural versions of the model class names.
-    &gt;&gt;&gt; from django.models.polls import polls, choices
+    # Import the model classes we just wrote.
+    &gt;&gt;&gt; from mysite.polls.models import Poll, Choice
 
     # No polls are in the system yet.
-    &gt;&gt;&gt; polls.get_list()
+    &gt;&gt;&gt; Poll.objects.all()
     []
 
     # Create a new Poll.
     &gt;&gt;&gt; from datetime import datetime
-    &gt;&gt;&gt; p = polls.Poll(question=&quot;What's up?&quot;, pub_date=datetime.now())
+    &gt;&gt;&gt; p = Poll(question=&quot;What's up?&quot;, pub_date=datetime.now())
 
     # Save the object into the database. You have to call save() explicitly.
     &gt;&gt;&gt; p.save()
@@ -406,107 +449,109 @@ Once you're in the shell, explore the database API::
     &gt;&gt;&gt; p.pub_date = datetime(2005, 4, 1, 0, 0)
     &gt;&gt;&gt; p.save()
 
-    # get_list() displays all the polls in the database.
-    &gt;&gt;&gt; polls.get_list()
+    # objects.all() displays all the polls in the database.
+    &gt;&gt;&gt; Poll.objects.all()
     [&lt;Poll object&gt;]
 
+
 Wait a minute. ``&lt;Poll object&gt;`` is, utterly, an unhelpful representation of
 this object. Let's fix that by editing the polls model
-(in the ``polls/models/polls.py`` file) and adding a ``__repr__()`` method to
+(in the ``polls/models.py`` file) and adding a ``__str__()`` method to
 both ``Poll`` and ``Choice``::
 
-    class Poll(meta.Model):
+    class Poll(models.Model):
         # ...
-        def __repr__(self):
+        def __str__(self):
             return self.question
 
-    class Choice(meta.Model):
+    class Choice(models.Model):
         # ...
-        def __repr__(self):
+        def __str__(self):
             return self.choice
 
-It's important to add ``__repr__()`` methods to your models, not only for your
+It's important to add ``__str__()`` methods to 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.
 
 Note these are normal Python methods. Let's add a custom method, just for
 demonstration::
 
-    class Poll(meta.Model):
+    import datetime
+    # ...
+    class Poll(models.Model):
         # ...
         def was_published_today(self):
             return self.pub_date.date() == datetime.date.today()
 
-Note ``import datetime`` wasn't necessary. Each model method has access to
-a handful of commonly-used variables for convenience, including the
-``datetime`` module from the Python standard library.
+Note the addition of ``import datetime`` to reference Python's standard
+``datetime`` module.
 
 Let's jump back into the Python interactive shell by running
 ``python manage.py shell`` again::
 
-    &gt;&gt;&gt; from django.models.polls import polls, choices
-    # Make sure our __repr__() addition worked.
-    &gt;&gt;&gt; polls.get_list()
+    &gt;&gt;&gt; from mysite.polls.models import Poll, Choice
+
+    # Make sure our __str__() addition worked.
+    &gt;&gt;&gt; Poll.objects.all()
     [What's up?]
 
     # Django provides a rich database lookup API that's entirely driven by
     # keyword arguments.
-    &gt;&gt;&gt; polls.get_object(id__exact=1)
-    What's up?
-    &gt;&gt;&gt; polls.get_object(question__startswith='What')
-    What's up?
+    &gt;&gt;&gt; Poll.objects.filter(id=1)
+    [What's up?]
+    &gt;&gt;&gt; Poll.objects.filter(question__startswith='What')
+    [What's up?]
 
     # Get the poll whose year is 2005. Of course, if you're going through this
     # tutorial in another year, change as appropriate.
-    &gt;&gt;&gt; polls.get_object(pub_date__year=2005)
+    &gt;&gt;&gt; Poll.objects.get(pub_date__year=2005)
     What's up?
 
-    &gt;&gt;&gt; polls.get_object(id__exact=2)
+    &gt;&gt;&gt; Poll.objects.get(id=2)
     Traceback (most recent call last):
         ...
-    PollDoesNotExist: Poll does not exist for {'id__exact': 2}
-    &gt;&gt;&gt; polls.get_list(question__startswith='What')
-    [What's up?]
+    DoesNotExist: Poll does not exist for {'id': 2}
 
     # Lookup by a primary key is the most common case, so Django provides a
     # shortcut for primary-key exact lookups.
-    # The following is identical to polls.get_object(id__exact=1).
-    &gt;&gt;&gt; polls.get_object(pk=1)
+    # The following is identical to Poll.objects.get(id=1).
+    &gt;&gt;&gt; Poll.objects.get(pk=1)
     What's up?
 
     # Make sure our custom method worked.
-    &gt;&gt;&gt; p = polls.get_object(pk=1)
+    &gt;&gt;&gt; p = Poll.objects.get(pk=1)
     &gt;&gt;&gt; p.was_published_today()
     False
 
-    # Give the Poll a couple of Choices. Each one of these method calls does an
-    # INSERT statement behind the scenes and returns the new Choice object.
-    &gt;&gt;&gt; p = polls.get_object(pk=1)
-    &gt;&gt;&gt; p.add_choice(choice='Not much', votes=0)
+    # Give the Poll a couple of Choices. The create call constructs a new
+    # choice object, does the INSERT statement, adds the choice to the set
+    # of available choices and returns the new Choice object.
+    &gt;&gt;&gt; p = Poll.objects.get(pk=1)
+    &gt;&gt;&gt; p.choice_set.create(choice='Not much', votes=0)
     Not much
-    &gt;&gt;&gt; p.add_choice(choice='The sky', votes=0)
+    &gt;&gt;&gt; p.choice_set.create(choice='The sky', votes=0)
     The sky
-    &gt;&gt;&gt; c = p.add_choice(choice='Just hacking again', votes=0)
+    &gt;&gt;&gt; c = p.choice_set.create(choice='Just hacking again', votes=0)
 
     # Choice objects have API access to their related Poll objects.
-    &gt;&gt;&gt; c.get_poll()
+    &gt;&gt;&gt; c.poll
     What's up?
 
     # And vice versa: Poll objects get access to Choice objects.
-    &gt;&gt;&gt; p.get_choice_list()
+    &gt;&gt;&gt; p.choice_set.all()
     [Not much, The sky, Just hacking again]
-    &gt;&gt;&gt; p.get_choice_count()
+    &gt;&gt;&gt; p.choice_set.count()
     3
 
     # The API automatically follows relationships as far as you need.
     # Use double underscores to separate relationships.
     # This works as many levels deep as you want. There's no limit.
     # Find all Choices for any poll whose pub_date is in 2005.
-    &gt;&gt;&gt; choices.get_list(poll__pub_date__year=2005)
+    &gt;&gt;&gt; Choice.objects.filter(poll__pub_date__year=2005)
     [Not much, The sky, Just hacking again]
 
     # Let's delete one of the choices. Use delete() for that.
-    &gt;&gt;&gt; c = p.get_choice(choice__startswith='Just hacking')
+    &gt;&gt;&gt; c = p.choice_set.filter(choice__startswith='Just hacking')
     &gt;&gt;&gt; c.delete()
 
 For full details on the database API, see our `Database API reference`_.</diff>
      <filename>docs/tutorial01.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,6 @@
 Writing your first Django app, part 2
 =====================================
 
-By Adrian Holovaty &lt;holovaty@gmail.com&gt;
-
 This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
 application and will focus on Django's automatically-generated admin site.
 
@@ -31,22 +29,13 @@ The Django admin site is not activated by default -- it's an opt-in thing. To
 activate the admin site for your installation, do these three things:
 
     * Add ``&quot;django.contrib.admin&quot;`` to your ``INSTALLED_APPS`` setting.
-    * Run the command ``python manage.py install admin``. This will create an
-      extra database table that the admin needs.
-    * Edit your ``myproject/urls.py`` file and uncomment the line below
+    * Run ``python manage.py syncdb``. Since you have added a new application
+      to ``INSTALLED_APPS``, the database tables need to be updated.
+    * Edit your ``mysite/urls.py`` file and uncomment the line below
       &quot;Uncomment this for admin:&quot;. This file is a URLconf; we'll dig into
       URLconfs in the next tutorial. For now, all you need to know is that it
       maps URL roots to applications.
 
-Create a user account
-=====================
-
-Run the following command to create a superuser account for your admin site::
-
-    python manage.py createsuperuser
-
-The script will prompt you for a username, e-mail address and password (twice).
-
 Start the development server
 ============================
 
@@ -82,26 +71,27 @@ Make the poll app modifiable in the admin
 But where's our poll app? It's not displayed on the admin index page.
 
 Just one thing to do: We need to specify in the ``Poll`` model that ``Poll``
-objects have an admin interface. Edit the ``myproject/polls/models/polls.py``
-file and make the following change to add an inner ``META`` class with an
-``admin`` attribute::
+objects have an admin interface. Edit the ``mysite/polls/models/polls.py``
+file and make the following change to add an inner ``Admin`` class::
 
-    class Poll(meta.Model):
+    class Poll(models.Model):
         # ...
-        class META:
-            admin = meta.Admin()
+        class Admin:
+            pass
 
-The ``class META`` contains all `non-field metadata`_ about this model.
+The ``class Admin`` will contain all the settings that control how this model
+appears in the Django admin.  All the settings are optional, however, so
+creating an empty class means &quot;give this object an admin interface using
+all the default options.&quot;
 
 Now reload the Django admin page to see your changes. Note that you don't have
-to restart the development server -- it auto-reloads code.
-
-.. _non-field metadata: http://www.djangoproject.com/documentation/model_api/#meta-options
+to restart the development server -- the server will auto-reloads your project,
+so any modifications code will be seen immediately in your browser.
 
 Explore the free admin functionality
 ====================================
 
-Now that ``Poll`` has the ``admin`` attribute, Django knows that it should be
+Now that ``Poll`` has the inner ``Admin`` class, Django knows that it should be
 displayed on the admin index page:
 
 .. image:: http://media.djangoproject.com/img/doc/tutorial/admin03t.png
@@ -125,7 +115,7 @@ Click the &quot;What's up?&quot; poll to edit it:
 Things to note here:
 
 * The form is automatically generated from the Poll model.
-* The different model field types (``meta.DateTimeField``, ``meta.CharField``)
+* The different model field types (``models.DateTimeField``, ``models.CharField``)
   correspond to the appropriate HTML input widget. Each type of field knows
   how to display itself in the Django admin.
 * Each ``DateTimeField`` gets free JavaScript shortcuts. Dates get a &quot;Today&quot;
@@ -157,13 +147,12 @@ Customize the admin form
 Take a few minutes to marvel at all the code you didn't have to write.
 
 Let's customize this a bit. We can reorder the fields by explicitly adding a
-``fields`` parameter to ``meta.Admin``::
+``fields`` parameter to ``Admin``::
 
-        admin = meta.Admin(
+        class Admin:
             fields = (
                 (None, {'fields': ('pub_date', 'question')}),
-            ),
-        )
+            )
 
 That made the &quot;Publication date&quot; show up first instead of second:
 
@@ -176,12 +165,11 @@ of fields, choosing an intuitive order is an important usability detail.
 And speaking of forms with dozens of fields, you might want to split the form
 up into fieldsets::
 
-        admin = meta.Admin(
+        class Admin:
             fields = (
                 (None, {'fields': ('question',)}),
                 ('Date information', {'fields': ('pub_date',)}),
-            ),
-        )
+            )
 
 The first element of each tuple in ``fields`` is the title of the fieldset.
 Here's what our form looks like now:
@@ -195,12 +183,11 @@ You can assign arbitrary HTML classes to each fieldset. Django provides a
 This is useful when you have a long form that contains a number of fields that
 aren't commonly used::
 
-        admin = meta.Admin(
+        class Admin:
             fields = (
                 (None, {'fields': ('question',)}),
                 ('Date information', {'fields': ('pub_date',), 'classes': 'collapse'}),
-            ),
-        )
+            )
 
 .. image:: http://media.djangoproject.com/img/doc/tutorial/admin09.png
    :alt: Fieldset is initially collapsed
@@ -214,13 +201,13 @@ the admin page doesn't display choices.
 Yet.
 
 There are two ways to solve this problem. The first is to give the ``Choice``
-model its own ``admin`` attribute, just as we did with ``Poll``. Here's what
+model its own inner ``Admin`` class, just as we did with ``Poll``. Here's what
 that would look like::
 
-    class Choice(meta.Model):
+    class Choice(models.Model):
         # ...
-        class META:
-            admin = meta.Admin()
+        class Admin:
+            pass
 
 Now &quot;Choices&quot; is an available option in the Django admin. The &quot;Add choice&quot; form
 looks like this:
@@ -242,18 +229,18 @@ But, really, this is an inefficient way of adding Choice objects to the system.
 It'd be better if you could add a bunch of Choices directly when you create the
 Poll object. Let's make that happen.
 
-Remove the ``admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)``
+Remove the ``Admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)``
 field like so::
 
-    poll = meta.ForeignKey(Poll, edit_inline=meta.STACKED, num_in_admin=3)
+    poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
 
 This tells Django: &quot;Choice objects are edited on the Poll admin page. By
 default, provide enough fields for 3 Choices.&quot;
 
 Then change the other fields in ``Choice`` to give them ``core=True``::
 
-    choice = meta.CharField(maxlength=200, core=True)
-    votes = meta.IntegerField(core=True)
+    choice = models.CharField(maxlength=200, core=True)
+    votes = models.IntegerField(core=True)
 
 This tells Django: &quot;When you edit a Choice on the Poll admin page, the 'choice'
 and 'votes' fields are required. The presence of at least one of them signifies
@@ -277,9 +264,9 @@ One small problem, though. It takes a lot of screen space to display all the
 fields for entering related Choice objects. For that reason, Django offers an
 alternate way of displaying inline related objects::
 
-    poll = meta.ForeignKey(Poll, edit_inline=meta.TABULAR, num_in_admin=3)
+    poll = models.ForeignKey(Poll, edit_inline=models.TABULAR, num_in_admin=3)
 
-With that ``edit_inline=meta.TABULAR`` (instead of ``meta.STACKED``), the
+With that ``edit_inline=models.TABULAR`` (instead of ``models.STACKED``), the
 related objects are displayed in a more compact, table-based format:
 
 .. image:: http://media.djangoproject.com/img/doc/tutorial/admin12.png
@@ -302,18 +289,16 @@ helpful if we could display individual fields. To do that, use the
 ``list_display`` option, which is a tuple of field names to display, as columns,
 on the change list page for the object::
 
-    class Poll(meta.Model):
+    class Poll(models.Model):
         # ...
-        class META:
-            admin = meta.Admin(
-                # ...
-                list_display = ('question', 'pub_date'),
-            )
+        class Admin:
+            # ...
+            list_display = ('question', 'pub_date')
 
 Just for good measure, let's also include the ``was_published_today`` custom
 method from Tutorial 1::
 
-    list_display = ('question', 'pub_date', 'was_published_today'),
+    list_display = ('question', 'pub_date', 'was_published_today')
 
 Now the poll change list page looks like this:
 
@@ -336,7 +321,7 @@ method a ``short_description`` attribute::
 Let's add another improvement to the Poll change list page: Filters. Add the
 following line to ``Poll.admin``::
 
-    list_filter = ['pub_date'],
+    list_filter = ['pub_date']
 
 That adds a &quot;Filter&quot; sidebar that lets people filter the change list by the
 ``pub_date`` field:
@@ -352,7 +337,7 @@ filter options for DateTimeFields: &quot;Any date,&quot; &quot;Today,&quot; &quot;Past 7 days,&quot;
 
 This is shaping up well. Let's add some search capability::
 
-    search_fields = ['question'],
+    search_fields = ['question']
 
 That adds a search box at the top of the change list. When somebody enters
 search terms, Django will search the ``question`` field. You can use as many
@@ -362,7 +347,7 @@ scenes, keep it reasonable, to keep your database happy.
 Finally, because Poll objects have dates, it'd be convenient to be able to
 drill down by date. Add this line::
 
-    date_hierarchy = 'pub_date',
+    date_hierarchy = 'pub_date'
 
 That adds hierarchical navigation, by date, to the top of the change list page.
 At top level, it displays all available years. Then it drills down to months
@@ -383,7 +368,7 @@ That's easy to change, though, using Django's template system. The Django admin
 is powered by Django itself, and its interfaces use Django's own template
 system. (How meta!)
 
-Open your settings file (``myproject/settings.py``, remember) and look at the
+Open your settings file (``mysite/settings.py``, remember) and look at the
 ``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem
 directories to check when loading Django templates. It's a search path.
 </diff>
      <filename>docs/tutorial02.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,6 @@
 Writing your first Django app, part 3
 =====================================
 
-By Adrian Holovaty &lt;holovaty@gmail.com&gt;
-
 This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll
 application and will focus on creating the public interface -- &quot;views.&quot;
 
@@ -62,44 +60,46 @@ arguments from the dictionary (an optional third item in the tuple).
 For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
 For more details on URLconfs, see the `URLconf documentation`_.
 
-When you ran ``python manage.py startproject myproject`` at the beginning of
-Tutorial 1, it created a default URLconf in ``myproject/urls.py``. It also
+When you ran ``python manage.py startproject mysite`` at the beginning of
+Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
 automatically set your ``ROOT_URLCONF`` setting to point at that file::
 
-    ROOT_URLCONF = 'myproject.urls'
+    ROOT_URLCONF = 'mysite.urls'
 
-Time for an example. Edit ``myproject/urls.py`` so it looks like this::
+Time for an example. Edit ``mysite/urls.py`` so it looks like this::
 
     from django.conf.urls.defaults import *
 
     urlpatterns = patterns('',
-        (r'^polls/$', 'myproject.polls.views.index'),
-        (r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
-        (r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
-        (r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
+        (r'^polls/$', 'mysite.polls.views.index'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/$', 'mysite.polls.views.detail'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/results/$', 'mysite.polls.views.results'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/vote/$', 'mysite.polls.views.vote'),
     )
 
 This is worth a review. When somebody requests a page from your Web site --
 say, &quot;/polls/23/&quot;, Django will load this Python module, because it's pointed to
 by the ``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/(\d+)/$'`` -- it loads the
-associated Python package/module: ``myproject.polls.views.detail``. That
-corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
+expression that matches -- ``r'^polls/(?P&lt;poll_id&gt;\d+)/$'`` -- it loads the
+associated Python package/module: ``mysite.polls.views.detail``. That
+corresponds to the function ``detail()`` in ``mysite/polls/views.py``.
 Finally, it calls that ``detail()`` function like so::
 
     detail(request=&lt;HttpRequest object&gt;, poll_id='23')
 
-The ``poll_id='23'`` part comes from ``(\d+)``. Using parenthesis around a
+The ``poll_id='23'`` part comes from ``(?P&lt;poll_id&gt;\d+)``. Using parenthesis around a
 pattern &quot;captures&quot; the text matched by that pattern and sends it as an argument
-to the view function.
+to the view function; the ``?P&lt;poll_id&gt;`` defines the name that will be used to
+identify the matched pattern; and \d+ is a regular experession to match a sequence of
+digits (i.e., a number).
 
 Because the URL patterns are regular expressions, there really is no limit on
 what you can do with them. And there's no need to add URL cruft such as
 ``.php`` -- unless you have a sick sense of humor, in which case you can do
 something like this::
 
-    (r'^polls/latest\.php$', 'myproject.polls.views.index'),
+    (r'^polls/latest\.php$', 'mysite.polls.views.index'),
 
 But, don't do that. It's silly.
 
@@ -135,20 +135,20 @@ You should get a pleasantly-colored error page with the following message::
 
     ViewDoesNotExist at /polls/
 
-    Tried index in module myproject.polls.views. Error was: 'module'
+    Tried index in module mysite.polls.views. Error was: 'module'
     object has no attribute 'index'
 
 This error happened because you haven't written a function ``index()`` in the
-module ``myproject/polls/views.py``.
+module ``mysite/polls/views.py``.
 
 Try &quot;/polls/23/&quot;, &quot;/polls/23/results/&quot; and &quot;/polls/23/vote/&quot;. The error
 messages tell you which view Django tried (and failed to find, because you
 haven't written any views yet).
 
-Time to write the first view. Open the file ``myproject/polls/views.py``
+Time to write the first view. Open the file ``mysite/polls/views.py``
 and put the following Python code in it::
 
-    from django.utils.httpwrappers import HttpResponse
+    from django.http import HttpResponse
 
     def index(request):
         return HttpResponse(&quot;Hello, world. You're at the poll index.&quot;)
@@ -185,11 +185,11 @@ in Tutorial 1. Here's one stab at the ``index()`` view, which displays the
 latest 5 poll questions in the system, separated by commas, according to
 publication date::
 
-    from django.models.polls import polls
-    from django.utils.httpwrappers import HttpResponse
+    from mysite.polls.models import Poll
+    from django.http import HttpResponse
 
     def index(request):
-        latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
+        latest_poll_list = Poll.objects.all().order_by('-pub_date')
         output = ', '.join([p.question for p in latest_poll_list])
         return HttpResponse(output)
 
@@ -197,13 +197,13 @@ There's a problem here, though: The page's design is hard-coded in the view. If
 you want to change the way the page looks, you'll have to edit this Python code.
 So let's use Django's template system to separate the design from Python::
 
-    from django.core.template import Context, loader
-    from django.models.polls import polls
-    from django.utils.httpwrappers import HttpResponse
+    from django.template import Context, loader
+    from mysite.polls.models import Poll
+    from django.http import HttpResponse
 
     def index(request):
-        latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
-        t = loader.get_template('polls/index')
+        latest_poll_list = Poll.objects.all().order_by('-pub_date')
+        t = loader.get_template('polls/index.html')
         c = Context({
             'latest_poll_list': latest_poll_list,
         })
@@ -227,9 +227,8 @@ find templates -- just as you did in the &quot;Customize the admin look and feel&quot;
 section of Tutorial 2.
 
 When you've done that, create a directory ``polls`` in your template directory.
-Within that, create a file called ``index.html``. Django requires that
-templates have &quot;.html&quot; extension. Note that our
-``loader.get_template('polls/index')`` code from above maps to
+Within that, create a file called ``index.html``. Note that our
+``loader.get_template('polls/index.html')`` code from above maps to
 &quot;[template_directory]/polls/index.html&quot; on the filesystem.
 
 Put the following code in that template::
@@ -254,12 +253,12 @@ It's a very common idiom to load a template, fill a context and return an
 ``HttpResponse`` object with the result of the rendered template. Django
 provides a shortcut. Here's the full ``index()`` view, rewritten::
 
-    from django.core.extensions import render_to_response
-    from django.models.polls import polls
+    from django.shortcuts import render_to_response
+    from mysite.polls.models import Poll
 
     def index(request):
-        latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
-        return render_to_response('polls/index', {'latest_poll_list': latest_poll_list})
+        latest_poll_list = Poll.objects.all().order_by('-pub_date')
+        return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
 
 Note that we no longer need to import ``loader``, ``Context`` or
 ``HttpResponse``.
@@ -274,15 +273,16 @@ Raising 404
 Now, let's tackle the poll detail view -- the page that displays the question
 for a given poll. Here's the view::
 
-    from django.core.exceptions import Http404
+    from django.http import Http404
+    # ...
     def detail(request, poll_id):
         try:
-            p = polls.get_object(pk=poll_id)
-        except polls.PollDoesNotExist:
+            p = Poll.objects.get(pk=poll_id)
+        except Poll.DoesNotExist:
             raise Http404
-        return render_to_response('polls/detail', {'poll': p})
+        return render_to_response('polls/detail.html', {'poll': p})
 
-The new concept here: The view raises the ``django.core.exceptions.Http404``
+The new concept here: The view raises the ``django.http.Http404``
 exception if a poll with the requested ID doesn't exist.
 
 A shortcut: get_object_or_404()
@@ -292,10 +292,11 @@ It's a very common idiom to use ``get_object()`` and raise ``Http404`` if the
 object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view,
 rewritten::
 
-    from django.core.extensions import get_object_or_404
+    from django.shortcuts import render_to_response, get_object_or_404
+    # ...
     def detail(request, poll_id):
-        p = get_object_or_404(polls, pk=poll_id)
-        return render_to_response('polls/detail', {'poll': p})
+        p = get_object_or_404(Poll, pk=poll_id)
+        return render_to_response('polls/detail.html', {'poll': p})
 
 The ``get_object_or_404()`` function takes a Django model module as its first
 argument and an arbitrary number of keyword arguments, which it passes to the
@@ -305,8 +306,8 @@ exist.
 .. admonition:: Philosophy
 
     Why do we use a helper function ``get_object_or_404()`` instead of
-    automatically catching the ``*DoesNotExist`` exceptions at a higher level,
-    or having the model API raise ``Http404`` instead of ``*DoesNotExist``?
+    automatically catching the ``DoesNotExist`` exceptions at a higher level,
+    or having the model API raise ``Http404`` instead of ``DoesNotExist``?
 
     Because that would couple the model layer to the view layer. One of the
     foremost design goals of Django is to maintain loose coupling.
@@ -359,7 +360,7 @@ what the template might look like::
 
     &lt;h1&gt;{{ poll.question }}&lt;/h1&gt;
     &lt;ul&gt;
-    {% for choice in poll.get_choice_list %}
+    {% for choice in poll.choice_set.all %}
         &lt;li&gt;{{ choice.choice }}&lt;/li&gt;
     {% endfor %}
     &lt;/ul&gt;
@@ -370,9 +371,9 @@ on the object ``poll``. Failing that, it tries attribute lookup -- which works,
 in this case. If attribute lookup had failed, it would've tried calling the
 method ``question()`` on the poll object.
 
-Method-calling happens in the ``{% for %}`` loop: ``poll.get_choice_list`` is
-interpreted as the Python code ``poll.get_choice_list()``, which returns a list
-of Choice objects and is suitable for iteration via the ``{% for %}`` tag.
+Method-calling happens in the ``{% for %}`` loop: ``poll.choice_set.all`` is
+interpreted as the Python code ``poll.choice_set.all()``, which returns an
+iterable of Choice objects and is suitable for use in the ``{% for %}`` tag.
 
 See the `template guide`_ for full details on how templates work.
 
@@ -385,19 +386,19 @@ Take some time to play around with the views and template system. As you edit
 the URLconf, you may notice there's a fair bit of redundancy in it::
 
     urlpatterns = patterns('',
-        (r'^polls/$', 'myproject.polls.views.index'),
-        (r'^polls/(?P&lt;poll_id&gt;\d+)/$', 'myproject.polls.views.detail'),
-        (r'^polls/(?P&lt;poll_id&gt;\d+)/results/$', 'myproject.polls.views.results'),
-        (r'^polls/(?P&lt;poll_id&gt;\d+)/vote/$', 'myproject.polls.views.vote'),
+        (r'^polls/$', 'mysite.polls.views.index'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/$', 'mysite.polls.views.detail'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/results/$', 'mysite.polls.views.results'),
+        (r'^polls/(?P&lt;poll_id&gt;\d+)/vote/$', 'mysite.polls.views.vote'),
     )
 
-Namely, ``myproject.polls.views`` is in every callback.
+Namely, ``mysite.polls.views`` is in every callback.
 
 Because this is a common case, the URLconf framework provides a shortcut for
 common prefixes. You can factor out the common prefixes and add them as the
 first argument to ``patterns()``, like so::
 
-    urlpatterns = patterns('myproject.polls.views',
+    urlpatterns = patterns('mysite.polls.views',
         (r'^polls/$', 'index'),
         (r'^polls/(?P&lt;poll_id&gt;\d+)/$', 'detail'),
         (r'^polls/(?P&lt;poll_id&gt;\d+)/results/$', 'results'),
@@ -419,15 +420,15 @@ Our poll app is pretty decoupled at this point, thanks to the strict directory
 structure that ``python manage.py startapp`` created, but one part of it is
 coupled to the Django settings: The URLconf.
 
-We've been editing the URLs in ``myproject/urls.py``, but the URL design of an
+We've been editing the URLs in ``mysite/urls.py``, but the URL design of an
 app is specific to the app, not to the Django installation -- so let's move the
 URLs within the app directory.
 
-Copy the file ``myproject/urls.py`` to ``myproject/polls/urls.py``. Then,
-change ``myproject/urls.py`` to remove the poll-specific URLs and insert an
+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
 ``include()``::
 
-    (r'^polls/', include('myproject.polls.urls')),
+    (r'^polls/', include('mysite.polls.urls')),
 
 ``include()``, simply, references another URLconf. Note that the regular
 expression doesn't have a ``$`` (end-of-string match character) but has the
@@ -439,14 +440,14 @@ Here's what happens if a user goes to &quot;/polls/34/&quot; in this system:
 
 * Django will find the match at ``'^polls/'``
 * It will strip off the matching text (``&quot;polls/&quot;``) and send the remaining
-  text -- ``&quot;34/&quot;`` -- to the 'myproject.polls.urls' urlconf for
+  text -- ``&quot;34/&quot;`` -- to the 'mysite.polls.urls' urlconf for
   further processing.
 
 Now that we've decoupled that, we need to decouple the
-'myproject.polls.urls' urlconf by removing the leading &quot;polls/&quot; from each
+'mysite.polls.urls' urlconf by removing the leading &quot;polls/&quot; from each
 line::
 
-    urlpatterns = patterns('myproject.polls.views',
+    urlpatterns = patterns('mysite.polls.views',
         (r'^$', 'index'),
         (r'^(?P&lt;poll_id&gt;\d+)/$', 'detail'),
         (r'^(?P&lt;poll_id&gt;\d+)/results/$', 'results'),</diff>
      <filename>docs/tutorial03.txt</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,6 @@
 Writing your first Django app, part 4
 =====================================
 
-By Adrian Holovaty &lt;holovaty@gmail.com&gt;
-
 This tutorial begins where `Tutorial 3`_ left off. We're continuing the Web-poll
 application and will focus on simple form processing and cutting down our code.
 
@@ -18,7 +16,7 @@ template contains an HTML ``&lt;form&gt;`` element::
     {% if error_message %}&lt;p&gt;&lt;strong&gt;{{ error_message }}&lt;/strong&gt;&lt;/p&gt;{% endif %}
 
     &lt;form action=&quot;/polls/{{ poll.id }}/vote/&quot; method=&quot;post&quot;&gt;
-    {% for choice in poll.get_choice_list %}
+    {% for choice in poll.choice_set.all %}
         &lt;input type=&quot;radio&quot; name=&quot;choice&quot; id=&quot;choice{{ forloop.counter }}&quot; value=&quot;{{ choice.id }}&quot; /&gt;
         &lt;label for=&quot;choice{{ forloop.counter }}&quot;&gt;{{ choice.choice }}&lt;/label&gt;&lt;br /&gt;
     {% endfor %}
@@ -41,24 +39,24 @@ A quick rundown:
       Django; it's just good Web development practice.
 
 Now, let's create a Django view that handles the submitted data and does
-something with it. Remember, in `Tutorial 3`_, we create a URLconf that
-included this line::
-
-    (r'^polls/(?P&lt;poll_id&gt;\d+)/vote/$', 'myproject.polls.views.vote'),
+something with it. Remember, in `Tutorial 3`_, we created a URLconf for the
+polls application that includes this line::
 
-So let's create a ``vote()`` function in ``myproject/polls/views.py``::
+    (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'mysite.polls.views.vote'),
 
-    from django.core.extensions import get_object_or_404, render_to_response
-    from django.models.polls import choices, polls
-    from django.utils.httpwrappers import HttpResponseRedirect
+So let's create a ``vote()`` function in ``mysite/polls/views.py``::
 
+    from django.shortcuts import get_object_or_404, render_to_response
+    from django.http import HttpResponseRedirect
+    from mysite.polls.models import Choice, Poll
+    # ...
     def vote(request, poll_id):
-        p = get_object_or_404(polls, pk=poll_id)
+        p = get_object_or_404(Poll, pk=poll_id)
         try:
-            selected_choice = p.get_choice(pk=request.POST['choice'])
-        except (KeyError, choices.ChoiceDoesNotExist):
+            selected_choice = p.choice_set.get(pk=request.POST['choice'])
+        except (KeyError, Choice.DoesNotExist):
             # Redisplay the poll voting form.
-            return render_to_response('polls/detail', {
+            return render_to_response('polls/detail.html', {
                 'poll': p,
                 'error_message': &quot;You didn't select a choice.&quot;,
             })
@@ -102,8 +100,8 @@ After somebody votes in a poll, the ``vote()`` view redirects to the results
 page for the poll. Let's write that view::
 
     def results(request, poll_id):
-        p = get_object_or_404(polls, pk=poll_id)
-        return render_to_response('polls/results', {'poll': p})
+        p = get_object_or_404(Poll, pk=poll_id)
+        return render_to_response('polls/results.html', {'poll': p})
 
 This is almost exactly the same as the ``detail()`` view from `Tutorial 3`_.
 The only difference is the template name. We'll fix this redundancy later.
@@ -113,7 +111,7 @@ Now, create a ``results.html`` template::
     &lt;h1&gt;{{ poll.question }}&lt;/h1&gt;
 
     &lt;ul&gt;
-    {% for choice in poll.get_choice_list %}
+    {% for choice in poll.choice_set.all %}
         &lt;li&gt;{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}&lt;/li&gt;
     {% endfor %}
     &lt;/ul&gt;
@@ -153,12 +151,12 @@ conversion.
 
     You should know basic math before you start using a calculator.
 
-First, open the polls.py URLconf. It looks like this, according to the tutorial
-so far::
+First, open the polls/urls.py URLconf. It looks like this, according to the
+tutorial so far::
 
     from django.conf.urls.defaults import *
 
-    urlpatterns = patterns('myproject.polls.views',
+    urlpatterns = patterns('mysite.polls.views',
         (r'^$', 'index'),
         (r'^(?P&lt;poll_id&gt;\d+)/$', 'detail'),
         (r'^(?P&lt;poll_id&gt;\d+)/results/$', 'results'),
@@ -168,56 +166,62 @@ so far::
 Change it like so::
 
     from django.conf.urls.defaults import *
+    from mysite.polls.models import Poll
 
     info_dict = {
-        'app_label': 'polls',
-        'module_name': 'polls',
+        'queryset': Poll.objects.all(),
     }
 
     urlpatterns = patterns('',
         (r'^$', 'django.views.generic.list_detail.object_list', info_dict),
         (r'^(?P&lt;object_id&gt;\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict),
-        (r'^(?P&lt;object_id&gt;\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results')),
-        (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'myproject.polls.views.vote'),
+        (r'^(?P&lt;object_id&gt;\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html')),
+        (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'mysite.polls.views.vote'),
     )
 
 We're using two generic views here: ``object_list`` and ``object_detail``.
 Respectively, those two views abstract the concepts of &quot;display a list of
 objects&quot; and &quot;display a detail page for a particular type of object.&quot;
 
-    * Each generic view needs to know which ``app_label`` and ``module_name``
-      it's acting on. Thus, we've defined ``info_dict``, a dictionary that's
-      passed to each of the generic views via the third parameter to the URL
-      tuples.
+    * Each generic view needs to know what data it will be acting upon. This
+      data is provided in a dictionary. The ``queryset`` key in this dictionary
+      points to the list of objects to be manipulated by the generic view.
 
-    * The ``object_detail`` generic view expects that the ID value captured
-      from the URL is called ``&quot;object_id&quot;``, so we've changed ``poll_id`` to
+    * The ``object_detail`` generic view expects the ID value captured
+      from the URL to be called ``&quot;object_id&quot;``, so we've changed ``poll_id`` to
       ``object_id`` for the generic views.
 
 By default, the ``object_detail`` generic view uses a template called
-``&lt;app_label&gt;/&lt;module_name&gt;_detail``. In our case, it'll use the template
-``&quot;polls/polls_detail&quot;``. Thus, rename your ``polls/detail.html`` template to
-``polls/polls_detail.html``, and change the ``render_to_response()`` line in
+``&lt;app name&gt;/&lt;module name&gt;_detail.html``. In our case, it'll use the template
+``&quot;polls/poll_detail.html&quot;``. Thus, rename your ``polls/detail.html`` template to
+``polls/poll_detail.html``, and change the ``render_to_response()`` line in
 ``vote()``.
 
 Similarly, the ``object_list`` generic view uses a template called
-``&lt;app_label&gt;/&lt;module_name&gt;_list``. Thus, rename ``polls/index.html`` to
-``polls/polls_list.html``.
+``&lt;app name&gt;/&lt;module name&gt;_list.html``. Thus, rename ``poll/index.html`` to
+``polls/poll_list.html``.
 
 Because we have more than one entry in the URLconf that uses ``object_detail``
 for the polls app, we manually specify a template name for the results view:
-``template_name='polls/results'``. Otherwise, both views would use the same
+``template_name='polls/results.html'``. Otherwise, both views would use the same
 template. Note that we use ``dict()`` to return an altered dictionary in place.
 
-The generic views pass ``object`` and ``object_list`` to their templates, so
-change your templates so that ``latest_poll_list`` becomes ``object_list`` and
-``poll`` becomes ``object``.
+In previous versions of the tutorial, the templates have been provided with a context
+that contains the ``poll` and ``latest_poll_list`` context variables. However,
+the generic views provide the variables ``object`` and ``object_list`` as context.
+Therefore, you need to change your templates to match the new context variables.
+Go through your templates, and modify any reference to ``latest_poll_list`` to
+``object_list``, and change any reference to ``poll`` to ``object``.
+
+You can now delete the ``index()``, ``detail()`` and ``results()`` views
+from ``polls/views.py``. We don't need them anymore -- they have been replaced
+by generic views.
 
-In the ``vote()`` view, change the template call from ``polls/detail`` to
-``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
+The ``vote()`` view is still required. However, it must be modified to match
+the new templates and context variables. Change the template call from ``polls/detail``
+to ``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
 
-Finally, you can delete the ``index()``, ``detail()`` and ``results()`` views
-from ``polls/views.py``. We don't need them anymore.
+Run the server, and use your new polling app based on generic views.
 
 For full details on generic views, see the `generic views documentation`_.
 </diff>
      <filename>docs/tutorial04.txt</filename>
    </modified>
    <modified>
      <diff>@@ -32,18 +32,18 @@ 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. The system 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: ``&quot;mydjangoapps.urls&quot;``.
-    2. The system 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. The system runs through each URL pattern, in order, and stops at the
-       first one that matches the requested URL.
+    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: ``&quot;mydjangoapps.urls&quot;``.
+    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 a
-       `request object`_ and any values captured in the regex as function
-       arguments.
+       `request object`_ as its first argument and any values captured in the
+       regex as remaining arguments.
 
 .. _settings file: http://www.djangoproject.com/documentation/settings/
 .. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
@@ -64,7 +64,7 @@ Here's a sample URLconf::
 
 Notes:
 
-    * ``from django.conf.urls.defaults import *`` makes the ``patterns``
+    * ``from django.conf.urls.defaults import *`` makes the ``patterns()``
       function available.
 
     * To capture a value from the URL, just put parenthesis around it.
@@ -72,11 +72,11 @@ Notes:
     * There's no need to add a leading slash, because every URL has that. For
       example, it's ``^articles``, not ``^/articles``.
 
-    * The ``&quot;r&quot;`` in front of each regular expression string is optional but
+    * The ``'r'`` in front of each regular expression string is optional but
       recommended. It tells Python that a string is &quot;raw&quot; -- that nothing in
       the string should be escaped. See `Dive Into Python's explanation`_.
 
-Examples:
+Example requests:
 
     * A request to ``/articles/2005/03/`` would match the third entry in the
       list. Django would call the function
@@ -121,8 +121,8 @@ Here's the above example URLconf, rewritten to use named groups::
     )
 
 This accomplishes exactly the same thing as the previous example, with one
-subtle difference: The captured values are passed as keyword arguments rather
-than positional arguments. For example:
+subtle difference: The captured values are passed to view functions as keyword
+arguments rather than positional arguments. For example:
 
     * A request to ``/articles/2005/03/`` would call the function
       ``news.views.month_archive(request, year='2005', month='03')``, instead
@@ -134,7 +134,7 @@ than positional arguments. For example:
 In practice, this means your URLconfs are slightly more explicit and less prone
 to argument-order bugs -- and you can reorder the arguments in your views'
 function definitions. Of course, these benefits come at the cost of brevity;
-some folks find the named-group syntax ugly and too verbose.
+some developers find the named-group syntax ugly and too verbose.
 
 The matching/grouping algorithm
 -------------------------------
@@ -160,6 +160,10 @@ will look for ``/myapp/``.
 In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look
 for ``/myapp/``.
 
+The URLconf doesn't look at the request method. In other words, all request
+methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same
+function for the same URL.
+
 Syntax of the urlpatterns variable
 ==================================
 
@@ -183,8 +187,8 @@ The remaining arguments should be tuples in this format::
 
     (regular expression, Python callback function [, optional dictionary])
 
-...where ``dictionary_of_extra_arguments`` is optional. (See
-&quot;Passing extra options to view functions&quot; below.)
+...where ``optional dictionary`` is optional. (See
+_`Passing extra options to view functions` below.)
 
 handler404
 ----------
@@ -209,7 +213,7 @@ include
 -------
 
 A function that takes a full Python import path to another URLconf that should
-be &quot;included&quot; in this place. See &quot;Including other URLconfs&quot; below.
+be &quot;included&quot; in this place. See _`Including other URLconfs` below.
 
 Notes on capturing text in URLs
 ===============================
@@ -259,12 +263,12 @@ Here's the example URLconf from the `Django overview`_::
     from django.conf.urls.defaults import *
 
     urlpatterns = patterns('',
-        (r'^articles/(?P&lt;year&gt;\d{4})/$', 'myproject.news.views.year_archive'),
-        (r'^articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/$', 'myproject.news.views.month_archive'),
-        (r'^articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/(?P&lt;day&gt;\d+)/$', 'myproject.news.views.article_detail'),
+        (r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'),
+        (r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'),
+        (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'),
     )
 
-In this example, each view has a common prefix -- ``&quot;myproject.news.views&quot;``.
+In this example, each view has a common prefix -- ``'myproject.news.views'``.
 Instead of typing that out for each entry in ``urlpatterns``, you can use the
 first argument to the ``patterns()`` function to specify a prefix to apply to
 each view function.
@@ -274,9 +278,9 @@ With this in mind, the above example can be written more concisely as::
     from django.conf.urls.defaults import *
 
     urlpatterns = patterns('myproject.news.views',
-        (r'^articles/(?P&lt;year&gt;\d{4})/$', 'year_archive'),
-        (r'^articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/$', 'month_archive'),
-        (r'^articles/(?P&lt;year&gt;\d{4})/(?P&lt;month&gt;\d{2})/(?P&lt;day&gt;\d+)/$', 'article_detail'),
+        (r'^articles/(\d{4})/$', 'year_archive'),
+        (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
+        (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
     )
 
 Note that you don't put a trailing dot (``&quot;.&quot;``) in the prefix. Django puts
@@ -299,7 +303,6 @@ number of other URLconfs::
         (r'^weblog/',        include('django_website.apps.blog.urls.blog')),
         (r'^documentation/', include('django_website.apps.docs.urls.docs')),
         (r'^comments/',      include('django.contrib.comments.urls.comments')),
-        (r'^rss/',           include('django.conf.urls.rss')),
     )
 
 Note that the regular expressions in this example don't have a ``$``</diff>
      <filename>docs/url_dispatch.txt</filename>
    </modified>
    <modified>
      <diff>@@ -19,21 +19,26 @@ setup(
                         'locale/cy/LC_MESSAGES/*',
                         'locale/da/LC_MESSAGES/*',
                         'locale/de/LC_MESSAGES/*',
+                        'locale/el/LC_MESSAGES/*',
                         'locale/en/LC_MESSAGES/*',
                         'locale/es/LC_MESSAGES/*',
                         'locale/fr/LC_MESSAGES/*',
                         'locale/gl/LC_MESSAGES/*',
+                        'locale/he/LC_MESSAGES/*',
                         'locale/is/LC_MESSAGES/*',
                         'locale/it/LC_MESSAGES/*',
                         'locale/ja/LC_MESSAGES/*',
                         'locale/nl/LC_MESSAGES/*',
                         'locale/no/LC_MESSAGES/*',
+                        'locale/pl/LC_MESSAGES/*',
                         'locale/pt_BR/LC_MESSAGES/*',
                         'locale/ro/LC_MESSAGES/*',
                         'locale/ru/LC_MESSAGES/*',
                         'locale/sk/LC_MESSAGES/*',
+                        'locale/sl/LC_MESSAGES/*',
                         'locale/sr/LC_MESSAGES/*',
                         'locale/sv/LC_MESSAGES/*',
+                        'locale/uk/LC_MESSAGES/*',
                         'locale/zh_CN/LC_MESSAGES/*',
                         'locale/zh_TW/LC_MESSAGES/*'],
         'django.contrib.admin': ['templates/admin/*.html',</diff>
      <filename>setup.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,16 @@
-&quot;&quot;&quot;
+r&quot;&quot;&quot;
 &gt;&gt;&gt; format(my_birthday, '')
 ''
 &gt;&gt;&gt; format(my_birthday, 'a')
 'p.m.'
 &gt;&gt;&gt; format(my_birthday, 'A')
 'PM'
+&gt;&gt;&gt; format(my_birthday, 'd')
+'08'
 &gt;&gt;&gt; format(my_birthday, 'j')
-'7'
+'8'
 &gt;&gt;&gt; format(my_birthday, 'l')
-'Saturday'
+'Sunday'
 &gt;&gt;&gt; format(my_birthday, 'L')
 'False'
 &gt;&gt;&gt; format(my_birthday, 'm')
@@ -24,7 +26,7 @@
 &gt;&gt;&gt; format(my_birthday, 'P')
 '10 p.m.'
 &gt;&gt;&gt; format(my_birthday, 'r')
-'Sat, 7 Jul 1979 22:00:00 +0100'
+'Sun, 8 Jul 1979 22:00:00 +0100'
 &gt;&gt;&gt; format(my_birthday, 's')
 '00'
 &gt;&gt;&gt; format(my_birthday, 'S')
@@ -34,9 +36,9 @@
 &gt;&gt;&gt; format(my_birthday, 'T')
 'CET'
 &gt;&gt;&gt; format(my_birthday, 'U')
-'300445200'
+'300531600'
 &gt;&gt;&gt; format(my_birthday, 'w')
-'6'
+'0'
 &gt;&gt;&gt; format(my_birthday, 'W')
 '27'
 &gt;&gt;&gt; format(my_birthday, 'y')
@@ -44,7 +46,7 @@
 &gt;&gt;&gt; format(my_birthday, 'Y')
 '1979'
 &gt;&gt;&gt; format(my_birthday, 'z')
-'188'
+'189'
 &gt;&gt;&gt; format(my_birthday, 'Z')
 '3600'
 
@@ -57,8 +59,11 @@
 &gt;&gt;&gt; format(wintertime, 'O')
 '+0100'
 
-&gt;&gt;&gt; format(my_birthday, 'Y z \\C\\E\\T')
-'1979 188 CET'
+&gt;&gt;&gt; format(my_birthday, r'Y z \C\E\T')
+'1979 189 CET'
+
+&gt;&gt;&gt; format(my_birthday, r'jS o\f F')
+'8th of July'
 &quot;&quot;&quot;
 
 from django.utils import dateformat, translation
@@ -70,6 +75,6 @@ translation.activate('en-us')
 
 time.tzset()
 
-my_birthday = datetime.datetime(1979, 7, 7, 22, 00)
+my_birthday = datetime.datetime(1979, 7, 8, 22, 00)
 summertime = datetime.datetime(2005, 10, 30, 1, 00)
 wintertime = datetime.datetime(2005, 10, 30, 4, 00)</diff>
      <filename>tests/othertests/dateformat.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
-# Unit tests for django.core.db.typecasts
+# Unit tests for typecast functions in django.db.backends.util
 
-from django.core.db import typecasts
+from django.db.backends import util as typecasts
 import datetime
 
 TEST_CASES = {</diff>
      <filename>tests/othertests/db_typecasts.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-&quot;&quot;&quot;
+r&quot;&quot;&quot;
 &gt;&gt;&gt; floatformat(7.7)
 '7.7'
 &gt;&gt;&gt; floatformat(7.0)
@@ -12,8 +12,8 @@
 &gt;&gt;&gt; floatformat(0.0)
 '0'
 
-&gt;&gt;&gt; addslashes('&quot;double quotes&quot; and \\'single quotes\\'')
-'\\\\&quot;double quotes\\\\&quot; and \\\\\\'single quotes\\\\\\''
+&gt;&gt;&gt; addslashes('&quot;double quotes&quot; and \'single quotes\'')
+'\\&quot;double quotes\\&quot; and \\\'single quotes\\\''
 
 &gt;&gt;&gt; capfirst('hello world')
 'Hello world'
@@ -21,17 +21,17 @@
 &gt;&gt;&gt; fix_ampersands('Jack &amp; Jill &amp; Jeroboam')
 'Jack &amp;amp; Jill &amp;amp; Jeroboam'
 
-&gt;&gt;&gt; linenumbers('line 1\\nline 2')
-'1. line 1\\n2. line 2'
+&gt;&gt;&gt; linenumbers('line 1\nline 2')
+'1. line 1\n2. line 2'
 
-&gt;&gt;&gt; linenumbers('\\n'.join(['x'] * 10))
-'01. x\\n02. x\\n03. x\\n04. x\\n05. x\\n06. x\\n07. x\\n08. x\\n09. x\\n10. x'
+&gt;&gt;&gt; linenumbers('\n'.join(['x'] * 10))
+'01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x'
 
 &gt;&gt;&gt; lower('TEST')
 'test'
 
-&gt;&gt;&gt; lower(u'\\xcb') # uppercase E umlaut
-u'\\xeb'
+&gt;&gt;&gt; lower(u'\xcb') # uppercase E umlaut
+u'\xeb'
 
 &gt;&gt;&gt; make_list('abc')
 ['a', 'b', 'c']
@@ -48,7 +48,7 @@ u'\\xeb'
 &gt;&gt;&gt; stringformat(1, 'z')
 ''
 
-&gt;&gt;&gt; title('a nice title, isn\\'t it?')
+&gt;&gt;&gt; title('a nice title, isn\'t it?')
 &quot;A Nice Title, Isn't It?&quot;
 
 
@@ -68,8 +68,8 @@ u'\\xeb'
 &gt;&gt;&gt; upper('Mixed case input')
 'MIXED CASE INPUT'
 
-&gt;&gt;&gt; upper(u'\\xeb') # lowercase e umlaut
-u'\\xcb'
+&gt;&gt;&gt; upper(u'\xeb') # lowercase e umlaut
+u'\xcb'
 
 
 &gt;&gt;&gt; urlencode('jack &amp; jill')
@@ -91,8 +91,8 @@ u'\\xcb'
 &gt;&gt;&gt; wordcount('lots of words')
 3
 
-&gt;&gt;&gt; wordwrap('this is a long paragraph of text that really needs to be wrapped I\\'m afraid', 14)
-&quot;this is a long\\nparagraph of\\ntext that\\nreally needs\\nto be wrapped\\nI'm afraid&quot;
+&gt;&gt;&gt; wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
+&quot;this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid&quot;
 
 &gt;&gt;&gt; ljust('test', 10)
 'test      '
@@ -124,7 +124,7 @@ u'\\xcb'
 &gt;&gt;&gt; linebreaks('line 1')
 '&lt;p&gt;line 1&lt;/p&gt;'
 
-&gt;&gt;&gt; linebreaks('line 1\\nline 2')
+&gt;&gt;&gt; linebreaks('line 1\nline 2')
 '&lt;p&gt;line 1&lt;br /&gt;line 2&lt;/p&gt;'
 
 &gt;&gt;&gt; removetags('some &lt;b&gt;html&lt;/b&gt; with &lt;script&gt;alert(&quot;You smell&quot;)&lt;/script&gt; disallowed &lt;img /&gt; tags', 'script img')
@@ -133,19 +133,15 @@ u'\\xcb'
 &gt;&gt;&gt; striptags('some &lt;b&gt;html&lt;/b&gt; with &lt;script&gt;alert(&quot;You smell&quot;)&lt;/script&gt; disallowed &lt;img /&gt; tags')
 'some html with alert(&quot;You smell&quot;) disallowed  tags'
 
-&gt;&gt;&gt; dictsort([{'age': 23, 'name': 'Barbara-Ann'},\
-              {'age': 63, 'name': 'Ra Ra Rasputin'},\
-              {'name': 'Jonny B Goode', 'age': 18}], 'age')
-[{'age': 18, 'name': 'Jonny B Goode'},\
- {'age': 23, 'name': 'Barbara-Ann'},\
- {'age': 63, 'name': 'Ra Ra Rasputin'}]
+&gt;&gt;&gt; dictsort([{'age': 23, 'name': 'Barbara-Ann'},
+...           {'age': 63, 'name': 'Ra Ra Rasputin'},
+...           {'name': 'Jonny B Goode', 'age': 18}], 'age')
+[{'age': 18, 'name': 'Jonny B Goode'}, {'age': 23, 'name': 'Barbara-Ann'}, {'age': 63, 'name': 'Ra Ra Rasputin'}]
 
-&gt;&gt;&gt; dictsortreversed([{'age': 23, 'name': 'Barbara-Ann'},\
-              {'age': 63, 'name': 'Ra Ra Rasputin'},\
-              {'name': 'Jonny B Goode', 'age': 18}], 'age')
-[{'age': 63, 'name': 'Ra Ra Rasputin'},\
- {'age': 23, 'name': 'Barbara-Ann'},\
- {'age': 18, 'name': 'Jonny B Goode'}]
+&gt;&gt;&gt; dictsortreversed([{'age': 23, 'name': 'Barbara-Ann'},
+...           {'age': 63, 'name': 'Ra Ra Rasputin'},
+...           {'name': 'Jonny B Goode', 'age': 18}], 'age')
+[{'age': 63, 'name': 'Ra Ra Rasputin'}, {'age': 23, 'name': 'Barbara-Ann'}, {'age': 18, 'name': 'Jonny B Goode'}]
 
 &gt;&gt;&gt; first([0,1,2])
 0
@@ -196,13 +192,13 @@ False
 'aceg'
 
 &gt;&gt;&gt; unordered_list(['item 1', []])
-'\\t&lt;li&gt;item 1&lt;/li&gt;'
+'\t&lt;li&gt;item 1&lt;/li&gt;'
 
 &gt;&gt;&gt; unordered_list(['item 1', [['item 1.1', []]]])
-'\\t&lt;li&gt;item 1\\n\\t&lt;ul&gt;\\n\\t\\t&lt;li&gt;item 1.1&lt;/li&gt;\\n\\t&lt;/ul&gt;\\n\\t&lt;/li&gt;'
+'\t&lt;li&gt;item 1\n\t&lt;ul&gt;\n\t\t&lt;li&gt;item 1.1&lt;/li&gt;\n\t&lt;/ul&gt;\n\t&lt;/li&gt;'
 
 &gt;&gt;&gt; unordered_list(['item 1', [['item 1.1', []], ['item 1.2', []]]])
-'\\t&lt;li&gt;item 1\\n\\t&lt;ul&gt;\\n\\t\\t&lt;li&gt;item 1.1&lt;/li&gt;\\n\\t\\t&lt;li&gt;item 1.2&lt;/li&gt;\\n\\t&lt;/ul&gt;\\n\\t&lt;/li&gt;'
+'\t&lt;li&gt;item 1\n\t&lt;ul&gt;\n\t\t&lt;li&gt;item 1.1&lt;/li&gt;\n\t\t&lt;li&gt;item 1.2&lt;/li&gt;\n\t&lt;/ul&gt;\n\t&lt;/li&gt;'
 
 &gt;&gt;&gt; add('1', '2')
 3
@@ -228,6 +224,8 @@ False
 # real testing of date() is in dateformat.py
 &gt;&gt;&gt; date(datetime.datetime(2005, 12, 29), &quot;d F Y&quot;)
 '29 December 2005'
+&gt;&gt;&gt; date(datetime.datetime(2005, 12, 29), r'jS o\f F')
+'29th of December'
 
 # real testing of time() is done in dateformat.py
 &gt;&gt;&gt; time(datetime.time(13), &quot;h&quot;)
@@ -322,7 +320,7 @@ False
 
 &quot;&quot;&quot;
 
-from django.core.template.defaultfilters import *
+from django.template.defaultfilters import *
 import datetime
 
 if __name__ == '__main__':</diff>
      <filename>tests/othertests/defaultfilters.py</filename>
    </modified>
    <modified>
      <diff>@@ -351,7 +351,7 @@ AttributeError: This QueryDict instance is immutable
 
 &quot;&quot;&quot;
 
-from django.utils.httpwrappers import QueryDict
+from django.http import QueryDict
 
 if __name__ == &quot;__main__&quot;:
     import doctest</diff>
      <filename>tests/othertests/httpwrappers.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 # Quick tests for the markup templatetags (django.contrib.markup)
 
-from django.core.template import Template, Context, add_to_builtins
+from django.template import Template, Context, add_to_builtins
 
 add_to_builtins('django.contrib.markup.templatetags.markup')
 </diff>
      <filename>tests/othertests/markup.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,10 @@
 from django.conf import settings
 
-# Turn TEMPLATE_DEBUG off, because tests assume that.
-settings.TEMPLATE_DEBUG = False
 
-from django.core import template
-from django.core.template import loader
+from django import template
+from django.template import loader
 from django.utils.translation import activate, deactivate, install
+from datetime import datetime
 import traceback
 
 #################################
@@ -32,6 +31,12 @@ template.libraries['django.templatetags.testtags'] = register
 # Helper objects for template tests #
 #####################################
 
+class SomeException(Exception):
+    silent_variable_failure = True
+
+class SomeOtherException(Exception):
+    pass
+
 class SomeClass:
     def __init__(self):
         self.otherclass = OtherClass()
@@ -42,6 +47,12 @@ class SomeClass:
     def method2(self, o):
         return o
 
+    def method3(self):
+        raise SomeException
+
+    def method4(self):
+        raise SomeOtherException
+
 class OtherClass:
     def method(self):
         return &quot;OtherClass.method&quot;
@@ -133,12 +144,20 @@ TEMPLATE_TESTS = {
     'basic-syntax31': (r'{{ var|default_if_none:var2 }}', {&quot;var&quot;: None, &quot;var2&quot;: &quot;happy&quot;}, 'happy'),
 
     # Default argument testing
-    'basic-syntax32' : (r'{{ var|yesno:&quot;yup,nup,mup&quot; }} {{ var|yesno }}', {&quot;var&quot;: True}, 'yup yes'),
+    'basic-syntax32': (r'{{ var|yesno:&quot;yup,nup,mup&quot; }} {{ var|yesno }}', {&quot;var&quot;: True}, 'yup yes'),
 
-    ### IF TAG ################################################################
-    'if-tag01': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {&quot;foo&quot;: True}, &quot;yes&quot;),
-    'if-tag02': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {&quot;foo&quot;: False}, &quot;no&quot;),
-    'if-tag03': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {}, &quot;no&quot;),
+    # Fail silently for methods that raise an exception with a &quot;silent_variable_failure&quot; attribute
+    'basic-syntax33': (r'1{{ var.method3 }}2', {&quot;var&quot;: SomeClass()}, &quot;12&quot;),
+
+    # In methods that raise an exception without a &quot;silent_variable_attribute&quot; set to True,
+    # the exception propogates
+    'basic-syntax34': (r'1{{ var.method4 }}2', {&quot;var&quot;: SomeClass()}, SomeOtherException),
+
+    # Escaped backslash in argument
+    'basic-syntax35': (r'{{ var|default_if_none:&quot;foo\bar&quot; }}', {&quot;var&quot;: None}, r'foo\bar'),
+
+    # Escaped backslash using known escape char
+    'basic-syntax35': (r'{{ var|default_if_none:&quot;foo\now&quot; }}', {&quot;var&quot;: None}, r'foo\now'),
 
     ### COMMENT TAG ###########################################################
     'comment-tag01': (&quot;{% comment %}this is hidden{% endcomment %}hello&quot;, {}, &quot;hello&quot;),
@@ -149,6 +168,45 @@ TEMPLATE_TESTS = {
     'comment-tag04': (&quot;foo{% comment %} {% endblock %} {% endcomment %}&quot;, {}, &quot;foo&quot;),
     'comment-tag05': (&quot;foo{% comment %} {% somerandomtag %} {% endcomment %}&quot;, {}, &quot;foo&quot;),
 
+    ### CYCLE TAG #############################################################
+    #'cycleXX': ('', {}, ''),
+    'cycle01': ('{% cycle a, %}', {}, 'a'),
+    'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),
+    'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),
+    'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),
+    'cycle05': ('{% cycle %}', {}, template.TemplateSyntaxError),
+    'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
+    'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
+
+    ### EXCEPTIONS ############################################################
+
+    # Raise exception for invalid template name
+    'exception01': (&quot;{% extends 'nonexistent' %}&quot;, {}, template.TemplateSyntaxError),
+
+    # Raise exception for invalid template name (in variable)
+    'exception02': (&quot;{% extends nonexistent %}&quot;, {}, template.TemplateSyntaxError),
+
+    # Raise exception for extra {% extends %} tags
+    'exception03': (&quot;{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}&quot;, {}, template.TemplateSyntaxError),
+
+    # Raise exception for custom tags used in child with {% load %} tag in parent, not in child
+    'exception04': (&quot;{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}&quot;, {}, template.TemplateSyntaxError),
+
+    ### FILTER TAG ############################################################
+    #'filterXX': ('', {}, ''),
+    'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
+    'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
+    'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
+
+    ### FIRSTOF TAG ###########################################################
+    #'firstofXX': ('', {}, ''),
+    'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
+    'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),
+    'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),
+    'firstof04': ('{% firstof a b c %}', {'a':0,'b':0,'c':3}, '3'),
+    'firstof05': ('{% firstof a b c %}', {'a':1,'b':2,'c':3}, '1'),
+    'firstof06': ('{% firstof %}', {}, template.TemplateSyntaxError),
+
     ### FOR TAG ###############################################################
     'for-tag01': (&quot;{% for val in values %}{{ val }}{% endfor %}&quot;, {&quot;values&quot;: [1, 2, 3]}, &quot;123&quot;),
     'for-tag02': (&quot;{% for val in values reversed %}{{ val }}{% endfor %}&quot;, {&quot;values&quot;: [1, 2, 3]}, &quot;321&quot;),
@@ -157,6 +215,17 @@ TEMPLATE_TESTS = {
     'for-tag-vars03': (&quot;{% for val in values %}{{ forloop.revcounter }}{% endfor %}&quot;, {&quot;values&quot;: [6, 6, 6]}, &quot;321&quot;),
     'for-tag-vars04': (&quot;{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}&quot;, {&quot;values&quot;: [6, 6, 6]}, &quot;210&quot;),
 
+    ### IF TAG ################################################################
+    'if-tag01': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {&quot;foo&quot;: True}, &quot;yes&quot;),
+    'if-tag02': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {&quot;foo&quot;: False}, &quot;no&quot;),
+    'if-tag03': (&quot;{% if foo %}yes{% else %}no{% endif %}&quot;, {}, &quot;no&quot;),
+
+    ### IFCHANGED TAG #########################################################
+    #'ifchangedXX': ('', {}, ''),
+    'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
+    'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
+    'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
+
     ### IFEQUAL TAG ###########################################################
     'ifequal01': (&quot;{% ifequal a b %}yes{% endifequal %}&quot;, {&quot;a&quot;: 1, &quot;b&quot;: 2}, &quot;&quot;),
     'ifequal02': (&quot;{% ifequal a b %}yes{% endifequal %}&quot;, {&quot;a&quot;: 1, &quot;b&quot;: 1}, &quot;yes&quot;),
@@ -169,20 +238,6 @@ TEMPLATE_TESTS = {
     'ifequal09': ('{% ifequal a &quot;test&quot; %}yes{% else %}no{% endifequal %}', {}, &quot;no&quot;),
     'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, &quot;yes&quot;),
 
-    # Integers
-    'ifequal11': ('{% ifequal a 1 %}yes{% else %}no{% endifequal %}', {}, &quot;no&quot;),
-    'ifequal12': ('{% ifequal a 1 %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: 1}, &quot;yes&quot;),
-    'ifequal13': ('{% ifequal a 1 %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: &quot;1&quot;}, &quot;no&quot;),
-    'ifequal14': ('{% ifequal a &quot;1&quot; %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: 1}, &quot;no&quot;),
-    'ifequal15': ('{% ifequal a &quot;1&quot; %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: &quot;1&quot;}, &quot;yes&quot;),
-
-    # Floats
-    'ifequal16': ('{% ifequal a 1.2 %}yes{% else %}no{% endifequal %}', {}, &quot;no&quot;),
-    'ifequal17': ('{% ifequal a 1.2 %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: 1.2}, &quot;yes&quot;),
-    'ifequal18': ('{% ifequal a 1.2 %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: &quot;1.2&quot;}, &quot;no&quot;),
-    'ifequal19': ('{% ifequal a &quot;1.2&quot; %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: 1.2}, &quot;no&quot;),
-    'ifequal20': ('{% ifequal a &quot;1.2&quot; %}yes{% else %}no{% endifequal %}', {&quot;a&quot;: &quot;1.2&quot;}, &quot;yes&quot;),
-
     ### IFNOTEQUAL TAG ########################################################
     'ifnotequal01': (&quot;{% ifnotequal a b %}yes{% endifnotequal %}&quot;, {&quot;a&quot;: 1, &quot;b&quot;: 2}, &quot;yes&quot;),
     'ifnotequal02': (&quot;{% ifnotequal a b %}yes{% endifnotequal %}&quot;, {&quot;a&quot;: 1, &quot;b&quot;: 1}, &quot;&quot;),
@@ -266,37 +321,7 @@ TEMPLATE_TESTS = {
     # Three-level inheritance with {{ block.super }} from parent and grandparent
     'inheritance23': (&quot;{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}&quot;, {}, '1_ab3_'),
 
-    ### EXCEPTIONS ############################################################
-
-    # Raise exception for invalid template name
-    'exception01': (&quot;{% extends 'nonexistent' %}&quot;, {}, template.TemplateSyntaxError),
-
-    # Raise exception for invalid template name (in variable)
-    'exception02': (&quot;{% extends nonexistent %}&quot;, {}, template.TemplateSyntaxError),
-
-    # Raise exception for extra {% extends %} tags
-    'exception03': (&quot;{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}&quot;, {}, template.TemplateSyntaxError),
-
-    # Raise exception for custom tags used in child with {% load %} tag in parent, not in child
-    'exception04': (&quot;{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}&quot;, {}, template.TemplateSyntaxError),
-
-    'multiline01': (&quot;&quot;&quot;
-                    Hello,
-                    boys.
-                    How
-                    are
-                    you
-                    gentlemen.
-                    &quot;&quot;&quot;,
-                    {},
-                    &quot;&quot;&quot;
-                    Hello,
-                    boys.
-                    How
-                    are
-                    you
-                    gentlemen.
-                    &quot;&quot;&quot;),
+    ### I18N ##################################################################
 
     # {% spaceless %} tag
     'spaceless01': (&quot;{% spaceless %} &lt;b&gt;    &lt;i&gt; text &lt;/i&gt;    &lt;/b&gt; {% endspaceless %}&quot;, {}, &quot;&lt;b&gt; &lt;i&gt; text &lt;/i&gt; &lt;/b&gt;&quot;),
@@ -341,6 +366,89 @@ TEMPLATE_TESTS = {
 
     # translation of a constant string
     'i18n13': ('{{ _(&quot;Page not found&quot;) }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
+
+    ### MULTILINE #############################################################
+
+    'multiline01': (&quot;&quot;&quot;
+                    Hello,
+                    boys.
+                    How
+                    are
+                    you
+                    gentlemen.
+                    &quot;&quot;&quot;,
+                    {},
+                    &quot;&quot;&quot;
+                    Hello,
+                    boys.
+                    How
+                    are
+                    you
+                    gentlemen.
+                    &quot;&quot;&quot;),
+
+    ### REGROUP TAG ###########################################################
+    #'regroupXX': ('', {}, ''),
+    'regroup01': ('{% regroup data by bar as grouped %}' + \
+                  '{% for group in grouped %}' + \
+                  '{{ group.grouper }}:' + \
+                  '{% for item in group.list %}' + \
+                  '{{ item.foo }}' + \
+                  '{% endfor %},' + \
+                  '{% endfor %}',
+                  {'data': [ {'foo':'c', 'bar':1},
+                             {'foo':'d', 'bar':1},
+                             {'foo':'a', 'bar':2},
+                             {'foo':'b', 'bar':2},
+                             {'foo':'x', 'bar':3}  ]},
+                  '1:cd,2:ab,3:x,'),
+
+    # Test for silent failure when target variable isn't found
+    'regroup02': ('{% regroup data by bar as grouped %}' + \
+                  '{% for group in grouped %}' + \
+                  '{{ group.grouper }}:' + \
+                  '{% for item in group.list %}' + \
+                  '{{ item.foo }}' + \
+                  '{% endfor %},' + \
+                  '{% endfor %}',
+                  {}, ''),
+
+    ### TEMPLATETAG TAG #######################################################
+    #'templatetagXX': ('', {}, ''),
+    'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
+    'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
+    'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),
+    'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),
+    'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),
+    'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),
+
+    ### WIDTHRATIO TAG ########################################################
+    #'widthratioXX': ('', {}, ''),
+    'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
+    'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),
+    'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),
+    'widthratio04': ('{% widthratio a b 100 %}', {'a':50,'b':100}, '50'),
+    'widthratio05': ('{% widthratio a b 100 %}', {'a':100,'b':100}, '100'),
+
+    # 62.5 should round to 63
+    'widthratio06': ('{% widthratio a b 100 %}', {'a':50,'b':80}, '63'),
+
+    # 71.4 should round to 71
+    'widthratio07': ('{% widthratio a b 100 %}', {'a':50,'b':70}, '71'),
+
+    # Raise exception if we don't have 3 args, last one an integer
+    'widthratio08': ('{% widthratio %}', {}, template.TemplateSyntaxError),
+    'widthratio09': ('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError),
+    'widthratio10': ('{% widthratio a b 100.0 %}', {'a':50,'b':100}, template.TemplateSyntaxError),
+    
+    ### NOW TAG ########################################################
+    # Simple case
+    'now01' : ('{% now &quot;j n Y&quot;%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),
+    
+    # Check parsing of escaped and special characters
+    'now02' : ('{% now &quot;j &quot;n&quot; Y&quot;%}', {}, template.TemplateSyntaxError),
+#    'now03' : ('{% now &quot;j \&quot;n\&quot; Y&quot;%}', {}, str(datetime.now().day) + '&quot;' + str(datetime.now().month) + '&quot;' + str(datetime.now().year)),
+#    'now04' : ('{% now &quot;j \nn\n Y&quot;%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
 }
 
 def test_template_loader(template_name, template_dirs=None):
@@ -358,6 +466,9 @@ def run_tests(verbosity=0, standalone=False):
     failed_tests = []
     tests = TEMPLATE_TESTS.items()
     tests.sort()
+
+    # Turn TEMPLATE_DEBUG off, because tests assume that.
+    old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
     for name, vals in tests:
         install()
         if 'LANGUAGE_CODE' in vals[1]:
@@ -387,6 +498,8 @@ def run_tests(verbosity=0, standalone=False):
             failed_tests.append(name)
     loader.template_source_loaders = old_template_loaders
     deactivate()
+    settings.TEMPLATE_DEBUG = old_td
+
     if failed_tests and not standalone:
         msg = &quot;Template tests %s failed.&quot; % failed_tests
         if not verbosity:</diff>
      <filename>tests/othertests/templates.py</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ import os, re, sys, time, traceback
 # and Django aims to work with Python 2.3+.
 import doctest
 
-APP_NAME = 'testapp'
+MODEL_TESTS_DIR_NAME = 'modeltests'
 OTHER_TESTS_DIR = &quot;othertests&quot;
 TEST_DATABASE_NAME = 'django_test_db'
 
@@ -18,10 +18,10 @@ def log_error(model_name, title, description):
         'description': description,
     })
 
-MODEL_DIR = os.path.join(os.path.dirname(__file__), APP_NAME, 'models')
+MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
 
 def get_test_models():
-    return [f[:-3] for f in os.listdir(MODEL_DIR) if f.endswith('.py') and not f.startswith('__init__')]
+    return [f for f in os.listdir(MODEL_TEST_DIR) if not f.startswith('__init__') and not f.startswith('.')]
 
 class DjangoDoctestRunner(doctest.DocTestRunner):
     def __init__(self, verbosity_level, *args, **kwargs):
@@ -39,9 +39,13 @@ class DjangoDoctestRunner(doctest.DocTestRunner):
             &quot;Code: %r\nLine: %s\nExpected: %r\nGot: %r&quot; % (example.source.strip(), example.lineno, example.want, got))
 
     def report_unexpected_exception(self, out, test, example, exc_info):
+        from django.db import transaction
         tb = ''.join(traceback.format_exception(*exc_info)[1:])
         log_error(test.name, &quot;API test raised an exception&quot;,
             &quot;Code: %r\nLine: %s\nException: %s&quot; % (example.source.strip(), example.lineno, tb))
+        # Rollback, in case of database errors. Otherwise they'd have
+        # side effects on other tests.
+        transaction.rollback_unless_managed()
 
 normalize_long_ints = lambda s: re.sub(r'(?&lt;![\w])(\d+)L(?![\w])', '\\1', s)
 
@@ -68,14 +72,27 @@ class TestRunner:
 
     def run_tests(self):
         from django.conf import settings
-        from django.core.db import db
-        from django.core import management, meta
 
-        # Manually set INSTALLED_APPS to point to the test app.
-        settings.INSTALLED_APPS = (APP_NAME,)
+        # Manually set INSTALLED_APPS to point to the test models.
+        settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()]
+
+        # Manually set DEBUG = False.
+        settings.DEBUG = False
+
+        from django.db import connection
+        from django.core import management
+        import django.db.models
 
         # Determine which models we're going to test.
         test_models = get_test_models()
+        if 'othertests' in self.which_tests:
+            self.which_tests.remove('othertests')
+            run_othertests = True
+            if not self.which_tests:
+                test_models = []
+        else:
+            run_othertests = not self.which_tests
+
         if self.which_tests:
             # Only run the specified tests.
             bad_models = [m for m in self.which_tests if m not in test_models]
@@ -96,9 +113,9 @@ class TestRunner:
             # Create the test database and connect to it. We need autocommit()
             # because PostgreSQL doesn't allow CREATE DATABASE statements
             # within transactions.
-            cursor = db.cursor()
+            cursor = connection.cursor()
             try:
-                db.connection.autocommit(1)
+                connection.connection.autocommit(1)
             except AttributeError:
                 pass
             self.output(1, &quot;Creating test database&quot;)
@@ -113,43 +130,62 @@ class TestRunner:
                 else:
                     print &quot;Tests cancelled.&quot;
                     return
-        db.close()
+        connection.close()
         old_database_name = settings.DATABASE_NAME
         settings.DATABASE_NAME = TEST_DATABASE_NAME
 
         # Initialize the test database.
-        cursor = db.cursor()
-        self.output(1, &quot;Initializing test database&quot;)
-        management.init()
+        cursor = connection.cursor()
 
         # Run the tests for each test model.
         self.output(1, &quot;Running app tests&quot;)
         for model_name in test_models:
             self.output(1, &quot;%s model: Importing&quot; % model_name)
             try:
-                mod = meta.get_app(model_name)
+                # TODO: Abstract this into a meta.get_app() replacement?
+                mod = __import__(MODEL_TESTS_DIR_NAME + '.' + model_name + '.models', '', '', [''])
             except Exception, e:
                 log_error(model_name, &quot;Error while importing&quot;, ''.join(traceback.format_exception(*sys.exc_info())[1:]))
                 continue
-            self.output(1, &quot;%s model: Installing&quot; % model_name)
-            management.install(mod)
-
-            # Run the API tests.
-            p = doctest.DocTestParser()
-            test_namespace = dict([(m._meta.module_name, getattr(mod, m._meta.module_name)) for m in mod._MODELS])
-            dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None)
-            # Manually set verbose=False, because &quot;-v&quot; command-line parameter
-            # has side effects on doctest TestRunner class.
-            runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
-            self.output(1, &quot;%s model: Running tests&quot; % model_name)
-            try:
+
+            if not getattr(mod, 'error_log', None):
+                # Model is not marked as an invalid model
+                self.output(1, &quot;%s model: Installing&quot; % model_name)
+                management.install(mod)
+
+                # Run the API tests.
+                p = doctest.DocTestParser()
+                test_namespace = dict([(m._meta.object_name, m) \
+                                        for m in django.db.models.get_models(mod)])
+                dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None)
+                # Manually set verbose=False, because &quot;-v&quot; command-line parameter
+                # has side effects on doctest TestRunner class.
+                runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
+                self.output(1, &quot;%s model: Running tests&quot; % model_name)
                 runner.run(dtest, clear_globs=True, out=sys.stdout.write)
-            finally:
-                # Rollback, in case of database errors. Otherwise they'd have
-                # side effects on other tests.
-                db.rollback()
+            else:
+                # Check that model known to be invalid is invalid for the right reasons.
+                self.output(1, &quot;%s model: Validating&quot; % model_name)
+
+                from cStringIO import StringIO
+                s = StringIO()
+                count = management.get_validation_errors(s, mod)
+                s.seek(0)
+                error_log = s.read()
+                actual = error_log.split('\n')
+                expected = mod.error_log.split('\n')
+
+                unexpected = [err for err in actual if err not in expected]
+                missing = [err for err in expected if err not in actual]
+
+                if unexpected or missing:
+                    unexpected_log = '\n'.join(unexpected)
+                    missing_log = '\n'.join(missing)
+                    log_error(model_name,
+                        &quot;Validator found %d validation errors, %d expected&quot; % (count, len(expected) - 1),
+                        &quot;Missing errors:\n%s\n\nUnexpected errors:\n%s&quot; % (missing_log, unexpected_log))
 
-        if not self.which_tests:
+        if run_othertests:
             # Run the non-model tests in the other tests dir
             self.output(1, &quot;Running other tests&quot;)
             other_tests_dir = os.path.join(os.path.dirname(__file__), OTHER_TESTS_DIR)
@@ -180,12 +216,12 @@ class TestRunner:
         # to do so, because it's not allowed to delete a database while being
         # connected to it.
         if settings.DATABASE_ENGINE != &quot;sqlite3&quot;:
-            db.close()
+            connection.close()
             settings.DATABASE_NAME = old_database_name
-            cursor = db.cursor()
+            cursor = connection.cursor()
             self.output(1, &quot;Deleting test database&quot;)
             try:
-                db.connection.autocommit(1)
+                connection.connection.autocommit(1)
             except AttributeError:
                 pass
             else:</diff>
      <filename>tests/runtests.py</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>django/conf/app_template/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/conf/app_template/models/app_name.py</filename>
    </removed>
    <removed>
      <filename>django/conf/settings.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/admin/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/admin/models/admin.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/admin/urls/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/admin/urls/admin.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/comments/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/comments/models/comments.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/flatpages/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/flatpages/models/flatpages.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/redirects/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/contrib/redirects/models/redirects.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/backends/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/backends/ado_mssql.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/backends/mysql.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/backends/postgresql.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/backends/sqlite3.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/base.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/dicthelpers.py</filename>
    </removed>
    <removed>
      <filename>django/core/db/typecasts.py</filename>
    </removed>
    <removed>
      <filename>django/core/extensions.py</filename>
    </removed>
    <removed>
      <filename>django/core/formfields.py</filename>
    </removed>
    <removed>
      <filename>django/core/meta/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/core/meta/fields.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/defaultfilters.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/defaulttags.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loader.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loader_tags.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loaders/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loaders/app_directories.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loaders/eggs.py</filename>
    </removed>
    <removed>
      <filename>django/core/template/loaders/filesystem.py</filename>
    </removed>
    <removed>
      <filename>django/middleware/sessions.py</filename>
    </removed>
    <removed>
      <filename>django/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/models/auth.py</filename>
    </removed>
    <removed>
      <filename>django/models/core.py</filename>
    </removed>
    <removed>
      <filename>django/parts/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/parts/auth/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/parts/auth/anonymoususers.py</filename>
    </removed>
    <removed>
      <filename>django/parts/auth/formfields.py</filename>
    </removed>
    <removed>
      <filename>django/parts/media/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/parts/media/photos.py</filename>
    </removed>
    <removed>
      <filename>django/utils/httpwrappers.py</filename>
    </removed>
    <removed>
      <filename>django/views/auth/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/views/auth/login.py</filename>
    </removed>
    <removed>
      <filename>django/views/decorators/auth.py</filename>
    </removed>
    <removed>
      <filename>django/views/registration/__init__.py</filename>
    </removed>
    <removed>
      <filename>django/views/registration/passwords.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/__init__.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/__init__.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/basic.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/custom_columns.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/custom_methods.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/custom_pk.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/get_latest.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/lookup.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/m2m_intermediary.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/m2m_multiple.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/m2o_recursive.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/m2o_recursive2.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/many_to_many.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/many_to_one.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/many_to_one_null.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/one_to_one.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/or_lookups.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/ordering.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/repr.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/reserved_names.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/save_delete_hooks.py</filename>
    </removed>
    <removed>
      <filename>tests/testapp/models/subclassing.py</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>1e4b6b3eaeb8e291619fe81148e4542f03b85e75</id>
    </parent>
  </parents>
  <author>
    <name>adrian</name>
    <email>adrian@bcc190cf-cafb-0310-a4f2-bffc1f526a37</email>
  </author>
  <url>http://github.com/django/django/commit/0b99a8691de067a6e2569d30a7e342de94d33a9a</url>
  <id>0b99a8691de067a6e2569d30a7e342de94d33a9a</id>
  <committed-date>2006-05-01T18:31:56-07:00</committed-date>
  <authored-date>2006-05-01T18:31:56-07:00</authored-date>
  <message>MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2809 bcc190cf-cafb-0310-a4f2-bffc1f526a37</message>
  <tree>d3b32e84cd66573b3833ddf662af020f8ef2f7a8</tree>
  <committer>
    <name>adrian</name>
    <email>adrian@bcc190cf-cafb-0310-a4f2-bffc1f526a37</email>
  </committer>
</commit>
