= Backwards-incompatible changes = As Django is still in pre-release mode, we haven't yet committed to maintaining backwards compatibility in any APIs. Although we're keeping such changes to a minimum, Django developers should be acutely aware of these changes. Of course, once we reach our first official release, we'll be strongly committed to backward compatibility. This page lists all backwards-incompatible changes to Django so far. == Moved mod_python handler == As of [169], using {{{django.core.handler}}} as a mod_python handler is deprecated. Use {{{django.core.handlers.modpython}}} instead. We will be removing {{{django.core.handler}}} for Django's first release. == Changed ordering syntax == As of [292], syntax used for {{{order_by}}} (in the database API) and {{{ordering}}} (in models) has changed. Example of old ordering syntax: {{{order_by=[('foo', 'ASC'), ('bar', 'DESC')]}}} Example of new ordering syntax: {{{order_by=['foo', '-bar']}}} The old syntax is deprecated, and we'll stop supporting it for Django's first release. == Refactored meta.py == As of [378], {{{django/core/meta.py}}} has been converted to a package, {{{django/core/meta/}}}. If you're using a version of Django from before [378], make sure to delete {{{django/core/meta.pyc}}} and {{{django/core/meta.pyo}}}, if they exist. The existence of those files doesn't pose any known problems, but it's best to clean things up. == Changed edit_inline and edit_inline_type behavior == As of [440], using {{{edit_inline_type}}} in your models is deprecated, in favor of a less-redundant approach that uses {{{edit_inline}}} itself. Example of old syntax: {{{edit_inline=True, edit_inline_type=meta.TABULAR}}} Example of new syntax: {{{edit_inline=meta.TABULAR}}} We'll stop supporting the old syntax for Django's first release. == Changed admin log to store primary keys as TEXT fields, not INTEGER fields == As of [469], the {{{object_id}}} field in {{{django.models.auth.LogEntry}}} is a {{{TextField}}} instead of an {{{IntegerField}}}. We made this change to accomodate non-integer primary keys. If you're using a Django database installation from before [469] and you want to use non-integer primary keys on an object you edit in the admin site, you'll need to do an {{{ALTER TABLE}}} in your database. In PostgreSQL: {{{ BEGIN; ALTER TABLE auth_admin_log RENAME object_id TO object_id_old; ALTER TABLE auth_admin_log ADD COLUMN object_id TEXT; UPDATE auth_admin_log SET object_id = object_id_old; ALTER TABLE auth_admin_log DROP COLUMN object_id_old; COMMIT; }}} In MySQL: {{{ ALTER TABLE auth_admin_log MODIFY object_id TEXT; }}} == Added support for anonymous sessions == As of [518], Django has support for anonymous sessions. If you're using a Django database installation from before [518] and you want to use the Django admin, anonymous sessions or auth-based sessions, you'll need to make a few updates to your database and settings files. === Change your settings files === Add {{{"django.middleware.sessions.SessionMiddleware"}}} to the {{{MIDDLEWARE_CLASSES}}} tuple in your admin settings file. Make sure it appears before {{{"django.middleware.admin.AdminUserRequired"}}}. (The middleware classes are applied in order, and the admin middleware requires that the session middleware come first.) If you want session support any other (i.e., non-admin) Django installation, change the {{{MIDDLEWARE_CLASSES}}} setting accordingly. The order (i.e., whether it comes before or after the other installed middleware classes) doesn't matter. === Create the core_sessions database table === In PostgreSQL, use this: {{{ CREATE TABLE core_sessions ( session_key varchar(40) NOT NULL PRIMARY KEY, session_data text NOT NULL, expire_date timestamp with time zone NOT NULL ); INSERT INTO content_types (name, package, python_module_name) VALUES ('session', 'core', 'sessions'); }}} In MySQL and SQLite, use this: {{{ CREATE TABLE core_sessions ( session_key varchar(40) NOT NULL PRIMARY KEY, session_data text NOT NULL, expire_date datetime NOT NULL ); INSERT INTO content_types (name, package, python_module_name) VALUES ('session', 'core', 'sessions'); }}} === Remove old, unneeded things === Execute this SQL in your database: {{{ DROP TABLE auth_sessions; DELETE FROM content_types WHERE package = 'auth' AND python_module_name = 'sessions'; }}} Edit your settings file(s) to remove {{{AUTH_SESSION_COOKIE}}} and {{{REGISTRATION_COOKIE_DOMAIN}}}, if they exist. == Changed model syntax == As of [549], Django's model syntax has changed. If you're using models that use old (pre-[549]) syntax, you'll need to convert them according to the instructions on ModelSyntaxChangeInstructions. == Moved template loader module == As of [867], {{{django.core.template_loader}}} is deprecated. Use {{{django.core.template.loader}}} instead. == Refactored the admin app not to require its own settings file == As of [948], the admin has been refactored, to make things simpler and tighter -- both conceptually and in code layout. === What changed === * The admin no longer requires its own settings file. The "main" site and admin site can run on the same Django installation. * All the admin code moved to {{{django/contrib/admin}}}. * The admin requires {{{"django.contrib.admin"}}} in {{{INSTALLED_APPS}}}, and it requires the {{{app_directories}}} [http://www.djangoproject.com/documentation/templates_python/#loader-types template loader]. * The admin database table isn't installed unless you explicitly have the admin installed ({{{django-admin.py install admin}}}). * Renamed the admin log database table to give it a {{{"django"}}} prefix. === How to update your code === If you're using a Django installation from before this changeset, do the following to restore your admin site: * Execute this SQL command: {{{ALTER TABLE auth_admin_log RENAME TO django_admin_log;}}} * If you're using an SQLite version older than 3.2.0 (no ALTER TABLE support), execute these SQL commands (following [http://www.sqlite.org/faq.html#q13 this pattern]): {{{ BEGIN TRANSACTION; CREATE TEMPORARY TABLE auth_backup ( id integer NOT NULL PRIMARY KEY, action_time datetime NOT NULL, user_id integer NOT NULL REFERENCES auth_users (id), content_type_id integer NULL REFERENCES content_types (id), object_id text NULL, object_repr varchar(200) NOT NULL, action_flag smallint unsigned NOT NULL, change_message text NOT NULL ); INSERT INTO auth_backup SELECT id, action_time, user_id, content_type_id, object_id, object_repr, action_flag, change_message FROM auth_admin_log; DROP TABLE auth_admin_log; CREATE TABLE django_admin_log ( id integer NOT NULL PRIMARY KEY, action_time datetime NOT NULL, user_id integer NOT NULL REFERENCES auth_users (id), content_type_id integer NULL REFERENCES content_types (id), object_id text NULL, object_repr varchar(200) NOT NULL, action_flag smallint unsigned NOT NULL, change_message text NOT NULL ); INSERT INTO django_admin_log SELECT id, action_time, user_id, content_type_id, object_id, object_repr, action_flag, change_message FROM auth_backup; DROP TABLE auth_backup; COMMIT; }}} * If you're using PostgreSQL, execute these SQL commands: {{{ ALTER TABLE auth_admin_log_id_seq RENAME TO django_admin_log_id_seq; ALTER TABLE django_admin_log ALTER COLUMN id DROP DEFAULT; ALTER TABLE django_admin_log ALTER COLUMN id SET DEFAULT nextval('public.django_admin_log_id_seq'::text); }}} * Edit your Django settings file (probably called {{{settings/main.py}}}) to make the following changes: * Add {{{"django.contrib.admin"}}} to {{{INSTALLED_APPS}}}. Order doesn't matter; it can be the first, last, whatever. * Remove {{{"django.middleware.admin.AdminUserRequired"}}} from {{{MIDDLEWARE_CLASSES}}}, if it's in there. * Add {{{"django.middleware.sessions.SessionMiddleware"}}} to {{{MIDDLEWARE_CLASSES}}}, if it's not already in there. * If you've created any custom admin templates, add the appropriate line from the admin {{{TEMPLATE_DIRS}}} setting to your "main" {{{TEMPLATE_DIRS}}}. * (Note that Django looks for "404.html" and "500.html" templates in your {{{TEMPLATE_DIRS}}}. Make sure you have these templates available.) * If you've created any custom admin templates, note that the template inheritance structure has changed. All admin templates are now within an {{{admin}}} subdirectory of the template directory. The following admin templates are directly affected by this change: * 404 --> admin/404 * 500 --> admin/500 * base --> admin/base * base_site --> admin/base_site * admin_object_history --> admin/object_history * delete_confirmation_generic --> admin/delete_confirmation * index --> admin/index * login --> admin/login * template_validator --> admin/template_validator * Add {{{"django.core.template.loaders.app_directories.load_template_source"}}} to {{{TEMPLATE_LOADERS}}}, after {{{"django.core.template.loaders.filesystem.load_template_source"}}}. If you don't have the {{{TEMPLATE_LOADERS}}} setting, set it to this: {{{ TEMPLATE_LOADERS = ( 'django.core.template.loaders.filesystem.load_template_source', 'django.core.template.loaders.app_directories.load_template_source', ) }}} * Remove your admin settings file (probably called {{{settings/admin.py}}}) and admin URLconf (probably called {{{settings/urls/admin.py}}}). * Delete {{{django/templatetags/*.pyc}}} and {{{django/templatetags/*.pyo}}}, just to be safe. * Edit your main URLconf (probably called {{{settings/urls/main.py}}}) and add this line: {{{ (r'^admin/', include('django.contrib.admin.urls.admin')), }}} Change that {{{"admin"}}} to whatever URL you were using for the admin site. If you use external mapping to files and directories (e.g., using mod_rewrite), do the following: * Make sure you're not redirecting {{{/admin}}} to another instance of Django with different settings (e.g., using settings/admin.py). * If you had a mapping of admin media files, make sure that it points to new directory, which is {{{/your/path/to/django/contrib/admin/media}}}. The following steps are optional but will tighten your code up. All assume your project is called {{{myproject}}}. * Move {{{myproject/settings/urls/main.py}}} to {{{myproject/urls.py}}}. * Delete {{{myproject/settings/urls/admin.py}}} (unless you had custom things in it, of course). * Move {{{myproject/settings/main.py}}} to {{{myproject/settings.py}}}. * Edit {{{myproject/settings.py}}} to change {{{ROOT_URLCONF}}} from {{{"myproject.settings.urls.main"}}} to {{{"myproject.urls"}}}. * If you use {{{myproject/settings/main_rss.py}}} to describe your RSS feeds, move it to {{{myproject/settings_rss.py}}}. * Change {{{DJANGO_SETTINGS_MODULE}}} in Apache configuration from {{{"myproject.settings.main"}}} to {{{"myproject.settings"}}}. * Having done all this, delete the directory {{{myproject/settings}}}. == Separated flatpages and redirects into standalone, optional apps == As of ____, flatpages and redirects, previously installed by default, are now optional add-ons. Now they must be installed manually. === What changed === * The flatpages and redirects database files are no longer installed by default. * Renamed all references to "flatfiles" -- a previous name for flatpages -- to "flatpages", to be unambiguous. * Renamed the flatpages and redirects database tables. * Moved all flatpages and redirects logic from throughout the Django code to {{{django.contrib}}}. * To use flatpages and redirects, you now need to specify them in {{{INSTALLED_APPS}}} -- use {{{"django.contrib.flatpages"}}} and {{{"django.contrib.redirects"}}}. === How to update your code === If you're using a Django installation from before this changeset, do the following to restore flatpages and redirects functionality: ==== If you don't want to use flatfiles ==== * Execute the following SQL: {{{ DROP TABLE flatfiles; DROP TABLE flatfiles_sites; DELETE FROM auth_permissions WHERE package = 'core' AND codename IN ('add_flatfile', 'change_flatfile', 'delete_flatfile'); DELETE FROM content_types WHERE package = 'core' AND python_module_name = 'flatfiles'; }}} ==== If you don't want to use redirects ==== * Execute the following SQL: {{{ DROP TABLE redirects; DELETE FROM auth_permissions WHERE package = 'core' AND codename IN ('add_redirect', 'change_redirect', 'delete_redirect'); DELETE FROM content_types WHERE package = 'core' AND python_module_name = 'redirects'; }}} ==== If you do want to use flatfiles and redirects ==== * Execute the following SQL: {{{ ALTER TABLE redirects RENAME TO django_redirects; ALTER TABLE flatfiles RENAME TO django_flatpages; ALTER TABLE flatfiles_sites RENAME TO django_flatpages_sites; ALTER TABLE django_flatpages_sites RENAME flatfile_id TO flatpage_id; INSERT INTO packages (label, name) VALUES ('flatpages', 'flatpages'); UPDATE content_types SET package = 'flatpages', python_module_name = 'flatpages' WHERE package = 'core' AND python_module_name = 'flatfiles'; UPDATE auth_permissions SET package = 'flatpages' WHERE package = 'core' AND codename IN ('add_flatfile', 'change_flatfile', 'delete_flatfile'); INSERT INTO packages (label, name) VALUES ('redirects', 'redirects'); UPDATE content_types SET package = 'redirects', python_module_name = 'redirects' WHERE package = 'core' AND python_module_name = 'redirects'; UPDATE auth_permissions SET package = 'redirects' WHERE package = 'core' AND codename IN ('add_redirect', 'change_redirect', 'delete_redirect'); }}} * If you're using PostgreSQL, execute this SQL: {{{ ALTER TABLE redirects_id_seq RENAME TO django_redirects_id_seq; ALTER TABLE django_redirects ALTER COLUMN id DROP DEFAULT; ALTER TABLE django_redirects ALTER COLUMN id SET DEFAULT nextval('public.django_redirects_id_seq'::text); ALTER TABLE flatfiles_id_seq RENAME TO django_flatpages_id_seq; ALTER TABLE django_flatpages ALTER COLUMN id DROP DEFAULT; ALTER TABLE django_flatpages ALTER COLUMN id SET DEFAULT nextval('public.django_flatpages_id_seq'::text); }}} * If you have a {{{flatfiles/default.html}}} template, rename it to {{{flatpages/default.html}}}. * In every one of your flatpage templates, change the variable {{{flatfile}}} to {{{flatpage}}}. * If you use the URLconf {{{django.conf.urls.flatfiles}}}, now point to {{{django.contrib.flatpages.urls}}}. * If you have a {{{USE_FLAT_PAGES}}} setting, remove it.