= 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 ____, Django's model syntax has changed. If you're using models that use old (pre-____) syntax, you'll need to convert them according to the following instructions. === What changed === * Fields are now attributes of the model class, rather than members of a {{{fields}}} list. * Meta information (anything that's NOT a field, such as {{{ordering}}}, {{{admin}}}, {{{unique_together}}}, etc.) now goes in an inner class, called {{{META}}} (note the all caps). This class doesn't have a parent class. * Each field is required to have an explicit name -- even {{{ForeignKey}}}s, {{{ManyToManyField}}}s and {{{OneToOneFields}}}. This solves the problem of "How do I refer to my field from within admin.fields?" * {{{rel_name}}} is no longer used for {{{ForeignKey}}}s. If your model has more than one {{{ForeignKey}}} to the same foreign model, differentiate the fields using the field name, not {{{rel_name}}}. See [http://www.djangoproject.com/documentation/models/m2o_recursive2/ Relating a model to another model more than once] for an example. * {{{rel_name}}} is no longer used for {{{ManyToManyField}}}s. If your model has more than one {{{ManyToManyField}}} to the same foreign model, differentiate the fields using the field name, not {{{rel_name}}}. Also, give both of the {{{ManyToManyField}}}s a {{{singular}}} attribute, which defines the name of the related object in singular format. (This is an obscure case, but it's included here for completeness.) === Examples === Old syntax example: {{{ #!python class Foo(meta.Model): fields = ( meta.CharField('first_name', maxlength=30), meta.CharField('last_name', maxlength=30), meta.ForeignKey(Bar), meta.ManyToManyField(Sites), ) ordering = ('-bar_id',) admin = meta.Admin( fields = ( (None, {'fields': ('first_name', 'last_name', 'bar_id', 'sites')}), ), ) }}} New syntax example: {{{ #!python class Foo(meta.Model): first_name = meta.CharField('first_name', maxlength=30) last_name = meta.CharField('last_name', maxlength=30) bar = meta.ForeignKey(Bar) sites = meta.ManyToManyField(Sites) class META: ordering = ('-bar',) admin = meta.Admin( fields = ( (None, {'fields': ('first_name', 'last_name', 'bar', 'sites')}), ), ) }}} Notes: * {{{bar}}} and {{{sites}}} now have explicit names, and {{{admin.fields}}} was changed to use {{{bar}}} instead of {{{bar_id}}}. * {{{ordering}}} was also changed to use the explicit name {{{bar}}} instead of {{{bar_id}}}. * Don't forget to remove the commas after each {{{Field}}}, because they're class attributes instead of list elements now.