July 29, 2009

Welcome to Django 1.1!

Django 1.1 includes a number of nifty new features, lots of bug fixes, and an easy upgrade path from Django 1.0.

Backwards-incompatible changes in 1.1¶

Django has a policy of API stability. This means that, in general, code you develop against Django 1.0 should continue to work against 1.1 unchanged. However, we do sometimes make backwards-incompatible changes if they’re necessary to resolve bugs, and there are a handful of such (minor) changes between Django 1.0 and Django 1.1.

Before upgrading to Django 1.1 you should double-check that the following changes don’t impact you, and upgrade your code if they do.

Changes to constraint names¶ Django 1.1 modifies the method used to generate database constraint names so that names are consistent regardless of machine word size. This change is backwards incompatible for some users. If you are using a 32-bit platform, you’re off the hook; you’ll observe no differences as a result of this change. However, users on 64-bit platforms may experience some problems using the reset management command. Prior to this change, 64-bit platforms would generate a 64-bit, 16 character digest in the constraint name; for example: ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_5e8f10c132091d1e FOREIGN KEY ... Following this change, all platforms, regardless of word size, will generate a 32-bit, 8 character digest in the constraint name; for example: ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_32091d1e FOREIGN KEY ... As a result of this change, you will not be able to use the reset management command on any table made by a 64-bit machine. This is because the new generated name will not match the historically generated name; as a result, the SQL constructed by the reset command will be invalid. If you need to reset an application that was created with 64-bit constraints, you will need to manually drop the old constraint prior to invoking reset .

Test cases are now run in a transaction¶ Django 1.1 runs tests inside a transaction, allowing better test performance (see test performance improvements for details). This change is slightly backwards incompatible if existing tests need to test transactional behavior, if they rely on invalid assumptions about the test environment, or if they require a specific test case ordering. For these cases, TransactionTestCase can be used instead. This is a just a quick fix to get around test case errors revealed by the new rollback approach; in the long-term tests should be rewritten to correct the test case.

Removed SetRemoteAddrFromForwardedFor middleware¶ For convenience, Django 1.0 included an optional middleware class – django.middleware.http.SetRemoteAddrFromForwardedFor – which updated the value of REMOTE_ADDR based on the HTTP X-Forwarded-For header commonly set by some proxy configurations. It has been demonstrated that this mechanism cannot be made reliable enough for general-purpose use, and that (despite documentation to the contrary) its inclusion in Django may lead application developers to assume that the value of REMOTE_ADDR is “safe” or in some way reliable as a source of authentication. While not directly a security issue, we’ve decided to remove this middleware with the Django 1.1 release. It has been replaced with a class that does nothing other than raise a DeprecationWarning . If you’ve been relying on this middleware, the easiest upgrade path is: Examine the code as it existed before it was removed.

Verify that it works correctly with your upstream proxy, modifying it to support your particular proxy (if necessary).

Introduce your modified version of SetRemoteAddrFromForwardedFor as a piece of middleware in your own project.

Names of uploaded files are available later¶ In Django 1.0, files uploaded and stored in a model’s FileField were saved to disk before the model was saved to the database. This meant that the actual file name assigned to the file was available before saving. For example, it was available in a model’s pre-save signal handler. In Django 1.1 the file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.

Changes to how model formsets are saved¶ In Django 1.1, BaseModelFormSet now calls ModelForm.save() . This is backwards-incompatible if you were modifying self.initial in a model formset’s __init__ , or if you relied on the internal _total_form_count or _initial_form_count attributes of BaseFormSet. Those attributes are now public methods.

Fixed the join filter’s escaping behavior¶ The join filter no longer escapes the literal value that is passed in for the connector. This is backwards incompatible for the special situation of the literal string containing one of the five special HTML characters. Thus, if you were writing {{ foo|join:"&" }} , you now have to write {{ foo|join:"&" }} . The previous behavior was a bug and contrary to what was documented and expected.