bgneal@4
|
1 Upgrading to Django 1.4
|
bgneal@4
|
2 #######################
|
bgneal@4
|
3
|
bgneal@4
|
4 :date: 2012-04-15 14:50
|
bgneal@4
|
5 :tags: Django
|
bgneal@4
|
6 :slug: upgrading-to-django-1.4
|
bgneal@4
|
7 :author: Brian Neal
|
bgneal@4
|
8
|
bgneal@4
|
9 `Django 1.4`_ came out recently, and I took a few hours to upgrade my first site
|
bgneal@4
|
10 yesterday. I thought it would be useful for my own reference to write down what
|
bgneal@4
|
11 I did. I hope it will be useful to others. I'd love to read what you had to do,
|
bgneal@4
|
12 so if you went through this process and blogged about it, please leave a
|
bgneal@4
|
13 comment. Please keep in mind these aren't hard and fast steps or a recipe to
|
bgneal@4
|
14 follow, as my sites are probably nothing like yours and may use different
|
bgneal@4
|
15 features of Django.
|
bgneal@4
|
16
|
bgneal@4
|
17 Preparation
|
bgneal@4
|
18 -----------
|
bgneal@4
|
19
|
bgneal@4
|
20 The first thing I did was to read very carefully the `Django 1.4 release
|
bgneal@4
|
21 notes`_. The Django team does a great job of documenting what has changed, so it
|
bgneal@4
|
22 is well worth your time to read the release notes. It is also a good idea to at
|
bgneal@4
|
23 least skim the `Django Deprecation Timeline`_. After reading these, you should
|
bgneal@4
|
24 make a list of the things you want to change, add, or remove.
|
bgneal@4
|
25
|
bgneal@4
|
26 Tips
|
bgneal@4
|
27 ----
|
bgneal@4
|
28
|
bgneal@4
|
29 After deciding what areas you want or need to change in your code, these tips
|
bgneal@4
|
30 may be useful to help you implement the changes.
|
bgneal@4
|
31
|
bgneal@4
|
32 #. **Run with warnings turned on**. Use this command to run the development
|
bgneal@4
|
33 server: ``$ python -Wall manage.py runserver``. Django makes use of `Python's
|
bgneal@4
|
34 warning system`_ to flag features that are deprecated. By running Python with
|
bgneal@4
|
35 the ``-Wall`` switch, you'll see these warnings in the development server
|
bgneal@4
|
36 output.
|
bgneal@4
|
37
|
bgneal@4
|
38 #. **Use the debugger to track down warnings**. Not sure where a pesky warning
|
bgneal@4
|
39 is coming from? Just open the Django source code in your editor and put a
|
bgneal@4
|
40 ``import pdb; pdb.set_trace()`` line right above or below the warning. You
|
bgneal@4
|
41 can then use the debugger's ``w`` command to get a stack trace and find out
|
bgneal@4
|
42 exactly what code is leading to the warning. In my case I kept getting a few
|
bgneal@4
|
43 warnings with no idea where they were coming from. I used this technique to
|
bgneal@4
|
44 verify the warnings were coming from third party code and not my own. For
|
bgneal@4
|
45 more information on using the debugger (and you really **should** know how to
|
bgneal@4
|
46 use this invaluable tool), see the `Pdb documentation`_.
|
bgneal@4
|
47
|
bgneal@4
|
48 My upgrade experience
|
bgneal@4
|
49 ---------------------
|
bgneal@4
|
50
|
bgneal@4
|
51 Here is a list of things that I did during my port. Again, you may not need to
|
bgneal@4
|
52 do these, and the next site I upgrade may have a different list. All of these
|
bgneal@4
|
53 changes (except for the first) are described in the `Django 1.4 release notes`_.
|
bgneal@4
|
54
|
bgneal@4
|
55 #. **Upgrade my Django debug toolbar**. As of this writing, the Django debug
|
bgneal@4
|
56 toolbar I got from PyPI was not compatible with Django 1.4. I simply
|
bgneal@4
|
57 uninstalled it and grabbed the development version from GitHub with
|
bgneal@4
|
58 ``pip install git+https://github.com/django-debug-toolbar/django-debug-toolbar.git``.
|
bgneal@4
|
59
|
bgneal@4
|
60 #. **Remove the ADMIN_MEDIA_PREFIX setting**. The admin application in
|
bgneal@4
|
61 Django 1.4 now relies on the ``staticfiles`` application (introduced in
|
bgneal@4
|
62 Django 1.3) to handle the serving of static assets.
|
bgneal@4
|
63
|
bgneal@4
|
64 #. **Remove use of the {% admin_media_prefix %} template tag**. Related to the
|
bgneal@4
|
65 above, this tag is now deprecated. I had a custom admin view that used this
|
bgneal@4
|
66 template tag, and I simply replaced it with ``{{ STATIC_URL }}/admin``.
|
bgneal@4
|
67
|
bgneal@4
|
68 #. **Remove verify_exists on URLFields**. The ``verify_exists`` option to
|
bgneal@4
|
69 the ``URLField`` has been removed for performance and security reasons. I had
|
bgneal@4
|
70 always set this to ``False``; now I just had to remove it altogether.
|
bgneal@4
|
71
|
bgneal@4
|
72 #. **Add the require_debug_false filter to logging settings**. As explained in
|
bgneal@4
|
73 the release notes, this change prevents admin error emails from being sent
|
bgneal@4
|
74 while in ``DEBUG`` mode.
|
bgneal@4
|
75
|
bgneal@4
|
76 #. **django.conf.urls.defaults is deprecated**. I changed my imports in all
|
bgneal@4
|
77 ``urls.py`` files to use ``django.conf.urls`` instead of
|
bgneal@4
|
78 ``django.conf.urls.defaults`` to access ``include()``, ``patterns()``, and
|
bgneal@4
|
79 ``url()``. The Django team had recently moved these functions and updated the
|
bgneal@4
|
80 docs and tutorial to stop using the frowned upon ``from
|
bgneal@4
|
81 django.conf.urls.defaults import *``.
|
bgneal@4
|
82
|
bgneal@4
|
83 #. **Enable the new clickjacking protection**. A nice new feature is some new
|
bgneal@4
|
84 middleware that adds the ``X-Frame-Options`` header to all response headers.
|
bgneal@4
|
85 This provides clickjacking_ protection in modern browsers.
|
bgneal@4
|
86
|
bgneal@4
|
87 #. **Add an admin password reset feature**. By adding a few new lines to your
|
bgneal@4
|
88 ``urlconf`` you get a nifty new password reset feature for your admin.
|
bgneal@4
|
89
|
bgneal@4
|
90 #. **Update to the new manage.py**. This was the biggest change with the most
|
bgneal@4
|
91 impact. The Django team has finally removed a long standing wart with its
|
bgneal@4
|
92 ``manage.py`` utility. Previously, ``manage.py`` used to play games with your
|
bgneal@4
|
93 ``PYTHONPATH`` which led to confusion when migrating to production. It could
|
bgneal@4
|
94 also lead to having your settings imported twice. See the next section in
|
bgneal@4
|
95 this blog entry for more on what I did here.
|
bgneal@4
|
96
|
bgneal@4
|
97 Reorganizing for the new manage.py
|
bgneal@4
|
98 ----------------------------------
|
bgneal@4
|
99
|
bgneal@4
|
100 The change with the largest impact for me was reorganizing my directory
|
bgneal@4
|
101 structure for the new ``manage.py`` command. Before this change, I had organized
|
bgneal@4
|
102 my directory structure like this:
|
bgneal@4
|
103
|
bgneal@4
|
104 ::
|
bgneal@4
|
105
|
bgneal@4
|
106 mysite/
|
bgneal@4
|
107 media/
|
bgneal@4
|
108 static/
|
bgneal@4
|
109 mysite/
|
bgneal@4
|
110 myapp1/
|
bgneal@4
|
111 __init__.py
|
bgneal@4
|
112 models.py
|
bgneal@4
|
113 views.py
|
bgneal@4
|
114 urls.py
|
bgneal@4
|
115 myapp2/
|
bgneal@4
|
116 __init__.py
|
bgneal@4
|
117 models.py
|
bgneal@4
|
118 views.py
|
bgneal@4
|
119 urls.py
|
bgneal@4
|
120 settings/
|
bgneal@4
|
121 __init__.py
|
bgneal@4
|
122 base.py
|
bgneal@4
|
123 local.py
|
bgneal@4
|
124 production.py
|
bgneal@4
|
125 test.py
|
bgneal@4
|
126 apache/
|
bgneal@4
|
127 myproject.wsgi
|
bgneal@4
|
128 logs/
|
bgneal@4
|
129 templates/
|
bgneal@4
|
130 manage.py
|
bgneal@4
|
131 urls.py
|
bgneal@4
|
132 LICENSE
|
bgneal@4
|
133 fabfile.py
|
bgneal@4
|
134 requirements.txt
|
bgneal@4
|
135
|
bgneal@4
|
136 After replacing the contents of my old ``manage.py`` with the new content, I
|
bgneal@4
|
137 then reorganized my directory structure to this:
|
bgneal@4
|
138
|
bgneal@4
|
139 ::
|
bgneal@4
|
140
|
bgneal@4
|
141 mysite/
|
bgneal@4
|
142 media/
|
bgneal@4
|
143 static/
|
bgneal@4
|
144 myapp1/
|
bgneal@4
|
145 __init__.py
|
bgneal@4
|
146 models.py
|
bgneal@4
|
147 views.py
|
bgneal@4
|
148 urls.py
|
bgneal@4
|
149 myapp2/
|
bgneal@4
|
150 __init__.py
|
bgneal@4
|
151 models.py
|
bgneal@4
|
152 views.py
|
bgneal@4
|
153 urls.py
|
bgneal@4
|
154 myproject/
|
bgneal@4
|
155 settings/
|
bgneal@4
|
156 __init__.py
|
bgneal@4
|
157 base.py
|
bgneal@4
|
158 local.py
|
bgneal@4
|
159 production.py
|
bgneal@4
|
160 test.py
|
bgneal@4
|
161 apache/
|
bgneal@4
|
162 myproject.wsgi
|
bgneal@4
|
163 logs/
|
bgneal@4
|
164 templates/
|
bgneal@4
|
165 urls.py
|
bgneal@4
|
166 LICENSE
|
bgneal@4
|
167 fabfile.py
|
bgneal@4
|
168 manage.py
|
bgneal@4
|
169 requirements.txt
|
bgneal@4
|
170
|
bgneal@4
|
171 It is a subtle change, but I like it. It now makes it clear that my project is
|
bgneal@4
|
172 just an application itself, consisting of the top-level ``urls.py``, settings,
|
bgneal@4
|
173 templates and logs. The ``manage.py`` file is now at the top level directory
|
bgneal@4
|
174 also, which seems right.
|
bgneal@4
|
175
|
bgneal@4
|
176 I had always made my imports as ``from app.models import MyModel`` instead of
|
bgneal@4
|
177 ``from myproject.app.models``, so I didn't have to update any imports.
|
bgneal@4
|
178
|
bgneal@4
|
179 Since I use the "settings as a package" scheme, I did have to update the imports
|
bgneal@4
|
180 in my settings files. For example, in my ``local.py`` I had to change ``from
|
bgneal@4
|
181 settings.base import *`` to ``myproject.settings.base import *``.
|
bgneal@4
|
182
|
bgneal@4
|
183 What I didn't do
|
bgneal@4
|
184 ----------------
|
bgneal@4
|
185
|
bgneal@4
|
186 Django 1.4's largest new feature is probably its support for timezones. I
|
bgneal@4
|
187 decided for this project not to take advantage of that. It would require a lot
|
bgneal@4
|
188 of changes, and it isn't really worth it for this small site. I may use it on
|
bgneal@4
|
189 the next site I convert to Django 1.4, and I will definitely be using it on new
|
bgneal@4
|
190 projects.
|
bgneal@4
|
191
|
bgneal@4
|
192 Conclusion
|
bgneal@4
|
193 ----------
|
bgneal@4
|
194
|
bgneal@4
|
195 The upgrade process went smoother and quicker than I thought thanks to the
|
bgneal@4
|
196 excellent release notes and the Django team's use of Python warnings to flag
|
bgneal@4
|
197 deprecated features.
|
bgneal@4
|
198
|
bgneal@4
|
199
|
bgneal@4
|
200 .. _Django 1.4: https://www.djangoproject.com/weblog/2012/mar/23/14/
|
bgneal@4
|
201 .. _Django 1.4 release notes: https://docs.djangoproject.com/en/1.4/releases/1.4/
|
bgneal@4
|
202 .. _Django Deprecation Timeline: https://docs.djangoproject.com/en/1.4/internals/deprecation/
|
bgneal@4
|
203 .. _Python's warning system: http://docs.python.org/library/warnings.html
|
bgneal@4
|
204 .. _Pdb documentation: http://docs.python.org/library/pdb.html
|
bgneal@4
|
205 .. _clickjacking: http://en.wikipedia.org/wiki/Clickjacking
|