= 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 [1166], 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 want to use flatfiles ==== * Execute the following SQL: {{{ 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'); }}} * If you're using PostgreSQL, execute this additional SQL: {{{ 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. * Add {{{"django.contrib.flatpages"}}} to your {{{INSTALLED_APPS}}}. * Add {{{"django.contrib.flatpages.middleware.FlatpageFallbackMiddleware"}}} to your {{{MIDDLEWARE_CLASSES}}}. ==== If you want to use redirects ==== * Execute the following SQL: {{{ ALTER TABLE redirects RENAME TO django_redirects; 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 additional 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); }}} * Add {{{"django.contrib.redirects"}}} to your {{{INSTALLED_APPS}}}. * Add {{{"django.contrib.redirects.middleware.RedirectFallbackMiddleware"}}} to your {{{MIDDLEWARE_CLASSES}}}. == Refactored RSS framework == As of [1194], Django's RSS framework was refactored. This change should not affect most Django users, because the RSS framework was completely undocumented. The only users affected are people who reverse-engineered the framework, and WorldOnline. See the new [http://www.djangoproject.com/documentation/syndication/ syndication docs]. For completeness, here's what changed: * Created {{{django/contrib/syndication}}}. * Removed {{{django/conf/urls/rss.py}}}. The syndication system doesn't require its own URLconf anymore. * Moved {{{django/views/rss/rss.py}}} to {{{django/contrib/syndication/views.py}}} and refactored it so that {{{feed()}}} takes {{{url}}} and {{{feed_dict}}} instead of {{{slug}}} and {{{param}}}. * Renamed {{{DefaultRssFeed}}} to {{{DefaultFeed}}} in {{{django/utils/feedgenerator.py}}}. * RSS feeds are now specified as subclasses of {{{django.contrib.syndication.feeds.Feed}}} instead of {{{django.core.rss.FeedConfiguration}}}. Syntax is completely different. * RSS feeds are now registered in URLconfs rather than in "magic" settings modules whose names end with "_rss". * Templates for RSS titles and descriptions now live in a {{{feeds}}} directory, not an {{{rss}}} directory. == Changed field name and length for auth.User password_md5 field == As of an upcoming change, the {{{password_md5}}} field in the {{{auth.User}}} model, which is used for authentication in the Django admin, was renamed to {{{password}}}, and its length was changed from 32 to 128 to accomodate longer hashes and password metadata, such as which hash algorithm to use. This affects everybody who uses the Django authentication system -- including users of the Django admin. Execute the following SQL to restore auth functionality: {{{ BEGIN; ALTER TABLE auth_users ADD COLUMN password varchar(128); UPDATE auth_users SET password = password_md5; ALTER TABLE auth_users ALTER COLUMN password SET NOT NULL; ALTER TABLE auth_users DROP COLUMN password_md5; COMMIT; }}}