<?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.)
+
