annotate content/Coding/014-upgrading-django1.4.rst @ 4:7ce6393e6d30

Adding converted blog posts from old blog.
author Brian Neal <bgneal@gmail.com>
date Thu, 30 Jan 2014 21:45:03 -0600
parents
children
rev   line source
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