= Backwards-incompatible changes = As Django is still in pre-1.0 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 1.0, we'll be strongly committed to backward compatibility. This page lists all backwards-incompatible changes to Django since the 0.95 release. For changes prior to 0.95, see the OlderBackwardsIncompatibleChanges page. == Table of Contents == Changes made after Django [source:/django/tags/releases/0.95 0.95]: * August 2, 2006: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Databaseconstraintnameschanged Database constraint names changed] * August 11, 2006: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Backslashescapingchanged Backslash escaping changed] * September 27, 2006: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#RemovedENABLE_PSYCOsetting Removed ENABLE_PSYCO setting] * March 14, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#EnforcingMySQLdbversion Enforcing MySQLdb version] Changes made after Django [source:/django/tags/releases/0.96 0.96]: * March 31, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Changedspacelesstemplatetagtoremoveallspaces Changed 'spaceless' template tag to remove all spaces] * April 8, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Renamedlocalflavor.usatolocalflavor.us Renamed `localflavour.usa` to `localflavor.us`] * April 9, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#RemovedLazyDate Removed `LazyDate`] * April 20, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#MySQLIntrospectionChange MySQL Introspection change] * April 25, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#LOGIN_URLisnowasetting Login URL is now a setting] * May 5, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#TestClientloginmethodchanged Test Client `login()` method changed] * May 8, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Genericrelationshavemoved Generic relations have moved] * May 14, 2007: [http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Newformsform-specificclean_methodsnamechange Newforms: form-specific clean_*() methods name change] == Database constraint names changed == As of [3512], the format of the constraint names Django generates for foreign key references changed slightly. These names are only used sometimes, when it is not possible to put the reference directly on the affected column, so this is not always visible. The effect of this change is that {{{manage.py reset app_name}}} and similar commands may generate SQL with invalid constraint names and thus generate an error when run against the database (the database server will complain about the constraint not existing). To fix this, you will need to tweak the output of {{{manage.py sqlreset app_name}}} to match the correct constraint names and pass the results to the database server manually. == Backslash escaping changed == As of [3552], the Django database API now escapes backslashes given as query parameters. If you have any database API code that match backslashes, and it was working before (despite the broken escaping), you'll have to change your code to "unescape" the slashes one level. For example, this used to work: {{{ #!python # Code that matches a single backslash MyModel.objects.filter(text__contains='\\\\') }}} But it should be rewritten as this: {{{ #!python # Code that matches a single backslash MyModel.objects.filter(text__contains='\\') }}} == Removed ENABLE_PSYCO setting == As of [3877], the {{{ENABLE_PSYCO}}} setting no longer exists. If your settings file includes {{{ENABLE_PSYCO}}}, nothing will break per se, but it just won't do anything. If you want to use [http://psyco.sourceforge.net/ Psyco] with Django, write some [wiki:PsycoMiddleware custom middleware that activates Psyco]. == Enforcing MySQLdb version == As of [4724], Django raises an error if you try to use the MySQL backend with a {{{MySQLdb}}} (MySQL Python module) version earlier than 1.2.1p2. There were significant, production-related bugs in earlier versions, so we have upgraded the minimum requirement. In [4767], we added a {{{mysql_old}}} backend, which is identical to the {{{mysql}}} backend prior to the change in [4724]. You can use this backend if upgrading the {{{MySQLdb}}} module is not immediately possible. However, the {{{mysql_old}}} backend is deprecated, and we will not continue developing it. == Changed 'spaceless' template tag to remove all spaces == As of [4885], the {{{spaceless}}} template tag removes *all* spaces between HTML tags instead of preserving a single space. For example, for this template code: {{{ {% spaceless %}
{% endspaceless %} }}} The old output was this: {{{ }}} The new output is this: {{{ }}} As always, {{{spaceless}}} only affects space *between* HTML tags, not space within HTML tags or space in plain text. == Renamed `localflavor.usa` to `localflavor.us` == As of [4954], `localflavor.usa` has been renamed `localflavor.us`. This change was made to match the naming scheme of other local flavors. == Removed `LazyDate` == The `LazyDate` helper class was removed in [4985]. Default field values and query arguments can both be callable objects, so instances of `LazyDate` can be replaced with a reference to a callable that evaluates to the current date (i.e., `datetime.now`). For example, the following model using `LazyDate`: {{{ class Article(models.Model): title = models.CharField(maxlength=100) published = models.DateField(default=LazyDate()) }}} can be redefined as: {{{ from datetime import datetime class Article(models.Model): title = models.CharField(maxlength=100) published = models.DateField(default=datetime.now) }}} Note that the new model definition refers to the name of the `datetime.now()` function, but doesn't actually call the function. The call to `datetime.now()` is deferred until the value is actually required (i.e., when the model is saved). == MySQL Introspection Change == In [5042] a small change was made in the `mysql` backend in how it interpreted `CHAR(n)` columns in the database. They are now mapped to Django's !CharField class, rather than the previous !TextField. See ticket #4048 for details. This will only be apparent if you introspect a database table using 0.96 and again using [5042] or later: you will have slightly different Django models generated if there are any `CHAR(n)` columns. However, no real code changes should be necessary. == LOGIN_URL is now a setting == In [5072], we moved the LOGIN_URL constant from django.contrib.auth into the settings module. This was part of a broader change to make these URLs (including logout and post-login redirect) configurable. Code that previously read {{{ #!python from django.contrib.auth import LOGIN_URL }}} should be changed to refer to `settings.LOGIN_URL` instead. == Test Client `login()` method changed == The implementation of `django.test.Client.login()` operated as a wrapper around a series of GET and POST calls accessing a nominated login URL. This approach was fragile, and tightly bound to specific templates and login mechanims. In [5152], we changed the implementation of the `login()` method on the test Client. `login()` now accepts a list of credentials, and exercises these credentials directly on the cookies and Session objects of a site, without accessing or using a login page. This breaks the dependence on specific template formatting, and enables the login mechanism to work with any authentication backend, and any login decorator. Existing uses of `login()`, e.g.: {{{ c = Client() c.login('/path/to/login','myuser','mypassword') }}} should be modified to read: {{{ c = Client() c.login(username='myuser', password='mypassword') }}} The keyword arguments `username` and `password` *must* be given explicitly. If an alternate authentication scheme is in use, the credentials required by that scheme can be provided instead of `username` and `password`. == Generic relations have moved == In [5172], the various generic relation classes (!GenericForeignKey and !GenericRelation) have moved into the django.contrib.contenttypes module. This is because they will not work if contenttypes is not an installed app. Making the import path reflect the dependency should help remind people of this. Code using generic relations should change from saying things like {{{ #!python generic_field = models.GenericRelation(SomeOtherModel) }}} to using {{{ #!python from django.contrib.contenttypes import generic ... generic_field = generic.GenericRelation(SomeOtherModel) }}} No database changes or other model changes are required. == Newforms: form-specific clean_*() methods name change == If you have any form-specific cleaning methods in a newforms.Form subclass, they need to be renamed, as of [5231]. Change code that looks like this {{{ #!/python class SomeForm(Form) some_field = ... ... def clean_some_field(self): ... }}} to this {{{ #!/python class SomeForm(Form) some_field = ... ... def do_clean_some_field(self): ... }}} (the prefix of the function changes from {{{clean_}}} to {{{do_clean_}}}). The need for this change is demonstrated by the test in [5231]. Prior to that commit, the test would fail.