Skip to content

Instantly share code, notes, and snippets.

@berinhard
Forked from imagescape/UpgradeDjango.md
Last active December 18, 2015 12:38
Show Gist options
  • Save berinhard/5783728 to your computer and use it in GitHub Desktop.
Save berinhard/5783728 to your computer and use it in GitHub Desktop.

Upgrade Django from 1.1 to 1.5.1. This highlights some of the issues that one may encounter when updating Django. It's not possible to cover every case, but this should provide a good general starting point.

Change to DATABASES variable in settings.py.

Django now supports multiple databases and changes are needed to how the database connections are defined.

CSRF Protection change.

Django refactored the Cross Site Request Forgery detection code. As a result, one must explicitly add a template tag to every Django form in the site and change the csrf middleware. This can be quite time-consuming if the application as a lot of forms. Third party modules will also need to be checked for compatibility.

Solution:

  • The {% csrf_token %} template tag is needed for all Django forms in the application.

  • Need to remove the old the CSRF middleware class/s and add the new one: django.middleware.csrf.CsrfViewMiddleware

      MIDDLEWARE_CLASSES = (
          'django.contrib.csrf.middleware.CsrfMiddleware,
          'django.contrib.csrf.middleware.CsrfViewMiddleware'
          'django.contrib.csrf.middleware.CsrfResponseMiddleware'
          'django.middleware.csrf.CsrfViewMiddleware',
      )
      

Javascript based CSRF Token for POSTed data.

A Javascript snippet must be added to the site to protect Javascript POST data from cross site scripting attacks.

Solution:

  • The Javascript snippet should be added to support POSTs through js
  • Need to add to the global site template

Change to admin url syntax and removal of admin.site.root.

Solution:

  • In the urls.py which includes the admin urls, make the following change:
    From:  (r'^admin/(.*)', admin.site.root),
    To:      (r'^admin/', include(admin.site.urls)),
  • Any code using admin.site.root needs to be refactored

Logging framework changes.

Django implemented tighter integration with the Python logging module. The change requires that one add skeleton configuration in the settings.py. In Django 1.5, the absence of this skeleton configuration generates errors when DEBUG is False.

  • Changed in Django 1.3
  • Unsure when required by
    Manifestation: 
    File "/usr/local/lib/python2.7/logging/config.py", line 503, in configure
       raise ValueError("dictionary doesn't specify a version")

Remove function-based generic views.

Django replaced function-based generic views with class-based views. As of Django 1.5, they have deprecated the old function based views. If these function-based generic views are used, some coding work will need to be done.

Source: https://docs.djangoproject.com/en/dev/releases/1.3/#function-based-generic-views

  • Changed in Django 1.3
  • Change Required by Django 1.5
  • Generic function-based views have been deprecated. Need to convert to class-based
  • Search for the following views and re-implement.
    django.views.generic.create_update
    django.views.generic.date_based
    django.views.generic.list_detail
    django.views.generic.simple

URL template tag syntax change.

Effective in Django 1.5, syntax for the { % url %} template tag has changed. Now, all url names used in a url template tag must be enclosed in quotes. This is to allow variables to be passed in as url names.

Source: https://docs.djangoproject.com/en/dev/releases/1.3/#changes-to-url-and-ssi

  • Changed in Django 1.3
  • Change Required by Django 1.5

Solutions: One needs to search for instances of the url tags and place quotes around them. This can be quite time consuming depending on how many urls there are.

    Example: 
    From:  {% url my_favorite_view arg1 arg2 %}
    To:      {% url 'my_favorite_view' arg1 arg2 %}

Implement Django static media configuration.

This is an optional update. Django now has a built-in static media (non-changing images, css, js) process. Using the collect static command, static files are copied to the specified web-server-accessible directory.

Source: https://docs.djangoproject.com/en/dev/releases/1.3/#extended-static-files-handling

  • Changed in Django 1.3
  • Use is not required, but strongly recommended

Solution: There are a lot of steps needed to configure, and the Django docs cover the subject in detail. However, some of the basic steps include the following:

  • May need to make changes to nginx/apache to support new location
  • Set the STATICFILES_DIRS, STATICFILES_FINDERS, STATIC_ROOT, and STATIC_URL variables in settings.py
  • Need to add " django.contrib.staticfiles" to INSTALLED_APPS in settings.py
  • Add static media context processor in settings.py
    TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.media",
    +  'django.core.context_processors.static',
  • Go through the application's codebase and replace the URL prefix for all the static media with {{ STATIC_URL }}. Note: this requires that each view is passed the RequestContext (more on this later)
  • As an alternative to the {{ STATIC_URL }}, one may use the staticfiles template tag. This does not have the RequestContext dependency.
    For Example:
    {{ STATIC_URL }}
    or
    {% staticfiles %}
    {% static "relative/path/to/static/file.css" %}

Change to TEMPLATE_LOADERS setting in settings.py.

As of Django 1.2, the template loaders settings has changed to load class-based template loaders. This will break in Django 1.4 if not changed.

Source: https://docs.djangoproject.com/en/dev/releases/1.4/#django-core-template-loaders

Change Detail: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders

  • Changed in Django 1.2
  • Change Required by Django 1.4
  • Need to change the TEMPLATE_LOADERS variable to new setting in settings.py

Solution: Replace as follows. See Change Detail link.

    Replace      :    django.core.template_loaders.*
    With            :    django.template.loader.*
    Example:
    TEMPLATE_LOADERS = (
    -    'django.template.loaders.filesystem.load_template_source',
    -    'django.template.loaders.app_directories.load_template_source',
    +    'django.template.loaders.filesystem.Loader',
    +    'django.template.loaders.app_directories.Loader'    

Change the auth template context processor.

As of 1.2, the context processor for auth has been moved out of Django core into contrib.

Source: http://stackoverflow.com/questions/7470179/module-django-core-context-processors-does-not-define-a-auth-callable-reques

  • Changed in Django 1.2
  • Change Required by Django 1.4
    Manifestation:
    This results in error messages such as: "Module 
    "django.core.context_processors" does not define a "auth"   
    callable request processor"

Solution:

  • For the TEMPLATE_CONTEXT_PROCESSORS variable in settings.py, change the Auth context processor as follows:
    TEMPLATE_CONTEXT_PROCESSORS = (
    -  "django.core.context_processors.auth",
    +  "django.contrib.auth.context_processors.auth",

Enable messaging framework.

When enabling the new CSRF protection, Django required that the messaging middleware be installed. Once the messaging middleware was installed, the CSRF middleware stopped complaining. However, there are a few other steps to fully enable the messaging framework.

Change Detail: https://docs.djangoproject.com/en/1.5/ref/contrib/messages/

  • Changed in Django 1.2

Solution:

  • Add the new middleware to MIDDLEWARE_CLASSES 'django.contrib.messages.middleware.MessageMiddleware',
  • Add the new middleware to TEMPLATE_CONTEXT_PROCESSORS 'django.contrib.messages.context_processors.messages'.
  • Add the module to INSTALLED_APPS 'django.contrib.messages'

Django Default project structure refactor / manage.py change.

In order to make Django more Pythonic, the location of manage.py was changed in Django 1.4.

  • Changed in Django 1.4;
  • Change Required by Django 1.6

Source: https://docs.djangoproject.com/en/dev/releases/1.4/#updated-default-project-layout-and-manage-py

Interesting discussion about the reasoning behind this change: https://groups.google.com/forum/?fromgroups=#!topic/django-developers/RLcKN_9zKYs

Solution: need to support new project layout, utilizing new manage.py and moving location. See above link.

  • The location of manage.py should be moved one directory above its previous location.
  • The contents of manage.py have changed. See the associated link.

Feeds import update.

Django feeds has been implemented by a slight module name change.

Source: https://github.com/kgrodzicki/django-news-system/issues/1

  • Changed in Django 1.2
  • Change Required by Django 1.4
    Manifestation:
    from django.contrib.syndication.feeds import Feed
    "ImportError: No module named feeds"

Solution: check for old Feed import. Replace as follows.

    Replace: from django.contrib.syndication.feeds import Feed
    With:    from django.contrib.syndication.views import Feed

Source: http://stackoverflow.com/questions/6642829/how-to-resolve-could-not-import-django-contrib-syndication-views-feed-error-in

    Manifestation:
    Could not import django.contrib.syndication.views.feed

Solution: check to make sure that the old imports are not being used. If the view string "django.contrib.syndication.views.feed" string is provided in urls.py it needs to replaced with the following django.contrib.syndication.views.Feed

    Example:
    urlpatterns += patterns('',
    -  (r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed', ….
    +  (r'^feeds/(?P.*)/$','django.contrib.syndication.views.Feed', ….

Filterspecs replaced.

The previously undocumented Django FilterSpecs module has been removed and replaced with a new ListFilter module. FilterSpecs were used to customize the list filter options in the admin interface. The new ListFilter module is an improved approach and is similar to the original FilterSpecs. Code that uses FilterSpecs will need to be re-coded.

Source: https://docs.djangoproject.com/en/dev/releases/1.4/#list-filters-in-admin-interface

  • Changed in Django 1.4
  • Change Required by Django 1.5
    Manifestation:
    from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
    Exception Type: ImportError at /
    Exception Value: No module named filterspecs

Solution: this requires a coding effort and is different for each application. See the link above for the API documentation.

Change datetimes now() to be timezone aware.

Django 1.4 introduced timezone support. Django now contains a new now() method which is timezone aware.

Source: https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#time-zones-migration-guide

  • Changed in Django 1.4
  • Use is not required, but strongly recommended

Solution: check for old import . Replace calls to the following module as follows.

    Replace: from datetime.datetime.now()
    With:    from django.utils.timezone.now()

Install Python 2.4 or greater for Django 1.2. Django 1.2+ requires at least Python 2.4

Source: https://docs.djangoproject.com/en/dev/releases/1.3/#python-compatibility

  • Changed in Django 1.2
  • Change Required by Django 1.2
  • As a consequence, the virtualenv needs to be re-built or re-initialized.
  • Compiled binaries will need to rebuild

Install Python 2.5 or greater for Django 1.4. Django 1.4+ requires at least Python 2.5

Source: https://docs.djangoproject.com/en/dev/releases/1.4/#python-compatibility

  • Changed in Django 1.4
  • Change Required by Django 1.4
  • As a consequence, the virtualenv needs to be re-built or re-initialized.
  • Compiled binaries will need to rebuild.

Install Python 2.6 or greater for Django 1.5.

Django 1.5+ requires at least Python 2.6

Source: https://docs.djangoproject.com/en/dev/releases/1.5/#python-compatibility

  • Changed in Django 1.5
  • Change Required by Django 1.5
  • As a consequence, the virtualenv needs to be re-built or re-initialized.
  • Compiled binaries will need to rebuild

Adjust imports for the simplejson Python module.

As of Django 1.5, simplejson is no longer included.

  • Change Required by Django 1.5

Source: https://docs.djangoproject.com/en/dev/releases/1.5/#system-version-of-simplejson-no-longer-used

    Manifestation: 
    calls to django.utils.simplejson will raise an ImportError 

Solution:

  • As Django requires Python 2.6 and 2.6 contains the json library, the any imports using simplejson can simply be replaced. Make sure simplejson imports are not in the codebase. Use "import json" instead.

Localflavor has been removed from Django core.

Separate packages are utilized for localflavor and must be installed and the import paths changed.

Source: https://docs.djangoproject.com/en/dev/releases/1.5/#django-contrib-localflavor

Change Detail: https://docs.djangoproject.com/en/dev/topics/localflavor/#how-to-migrate

  • Changed in Django 1.5
  • Change Required by Django 1.6

Solution:

  • Check for forms and modules using django.contrib.localflavor fields and install external app according to the links above

URLField verify_exists parameter no longer supported.

Due to a security issue, Django no longer checks to see if urls exist for urls entered into a URLField. The verify_exists keyword argument has been deprecated.

Source: https://www.djangoproject.com/weblog/2011/sep/09/security-releases-issued/

  • Changed in Django 1.2.6 and 1.3.1
  • Change Required by Django 1.5
  • verify_exists has been removed from URLField in Django 1.5. -
  • Throws an exception if present

Solution:

  • Do greps and make code replacement
    For Example:
    From:  website = models.URLField(verify_exists=False, blank=True)
    To:       website = models.URLField(blank=True)

Changed location of the various url utility modules.

As of Django 1.5, the location of a variety of url utility modules are no longer available from django.http. They can be used in django.utils.http. Most notable, impacted methods include, urlquote and urlencode.

  • Changed in Django 1.0 or before
  • Change Required by Django 1.5

Solution:

  • Update the imports as follows
    From:  from django.http import urlencode
    To:      from django.utils.http import urlencode

RequestContext class needed for static files and for CSRF protection.

Old views that do not pass in a RequestContext to the render_to_response shortcut will experience problems with CSRF {% csrf_token %} protection and using the {{ STATIC_URL }} context variables. These views

Solution:

  • These views should be updated to pass in the RequestContext if possible.
  • As an alternative, Django 1.3+ shortcuts offer a render() method that may be used in place of render_to_response() and will automatically pass in the request context.

Change detail: https://docs.djangoproject.com/en/1.5/topics/http/shortcuts/#render

    For example: 
    From:
        return render_to_response(template, {})
    To:
        from django.template import RequestContext
        return render_to_response(template, {},     
              context_instance=RequestContext(request))

Template tag admin_media_prefix removed.

As of 1.5, the template library adminmedia containing admin_media_prefix is no longer available.

  • Changed in Django 1.4
  • Change Required by Django 1.5

This template tag was located in django.contrib.admin.templatetags.adminmedia

Source: https://docs.djangoproject.com/en/1.5/releases/1.5/#miscellaneous

Change detail: http://stackoverflow.com/questions/13624458/appropriate-way-to-handle-deprecated-adminmedia-templatetag-and-admin-media

Solution:

  • This must be removed from template code and possible replaced with STATIC_URL from Django staticfiles. See the Stackoverflow link for a good example.

Change to method get_hosts().

As of 1.5, django.http.get_host has been changed. Instead of importing this method and passing the request upon calling the method, it is now a method on the request object. New request.get_host() syntax available since Django 1.0 or before

  • Change Required by Django 1.5

Solution: [kstateome/django-cas#15 https://github.com/kstateome/django-cas/commit/b92610a615c3b950d5bc3c939d171f8a59b899a5][20]

Make the following change

-    host = get_host(request)
+    host = request.get_host()

ALLOWED_HOSTS setting required.

As of Django 1.5, the ALLOWED_HOSTS setting is required in settings.py. This first was introduced in Django 1.4.4 but was set to ["*"] by default. In 1.5, the default value has been removed and needs to be set.

  • Changed in Django 1.4.4
  • Change Required by Django 1.5
    Manifestation: "Server Error (500)" when DEBUG=False

The md5 module has been depreciated

Python 2.5 has moved the md5 module.

  • Changed in python 2.5
Manifestation: 
    DeprecationWarning: the md5 module is deprecated; use hashlib instead
      import md5

Solution: (backwards compatible)

    try:
        from hashlib import md5
    except ImportError:
        import md5

Field.get_db_prep_value(), Field.get_db_prep_lookup(), and Field.get_db_prep_save() function signature changed.

The methods Field.get_db_prep_value(), Field.get_db_prep_lookup(), and Field.get_db_prep_save() in module django.db.models.fields.init.py changed to take additional arguments to support multiple database. If you override this method, you will need to pass in these additional arguments.

  • Changed in Django 1.2
  • Change Required by Django 1.2
Manifestation: 

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File "/iscape/sites/mysite2/proj/mysite/mysite/vendors/form_designer/views.py", line 88, in detail
    result = process_form(request, form_definition)

  File "/iscape/sites/mysite2/proj/mysite/mysite/vendors/form_designer/views.py", line 58, in process_form
    form_definition.log(form)

  File "/iscape/sites/mysite2/proj/mysite/mysite/vendors/form_designer/models.py", line 79, in log
    FormLog(form_definition=self, data=self.get_form_data(form)).save()

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/base.py", line 546, in save
    force_update=force_update, update_fields=update_fields)

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/base.py", line 650, in save_base
    result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/manager.py", line 215, in _insert
    return insert_query(self.model, objs, fields, **kwargs)

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/query.py", line 1661, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 936, in execute_sql
    for sql, params in self.as_sql():

  File "/iscape/sites/mysite2/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 894, in as_sql
    for obj in self.query.objs

TypeError: get_db_prep_save() got an unexpected keyword argument 'connection'

    Example: 
    From:
        def get_db_prep_value(self, value):
    To:
        def get_db_prep_value(self, value, connection, prepared=False):

    Example: 
    From:
        def get_db_prep_save(self, value):
    To:
        def get_db_prep_save(self, value, connection):

    Example: 
    From:
        def get_db_prep_lookup(self, lookup_type, value):
    To:
        def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):

ModelAdmin.change_view() function signature changed.

The methods ModelAdmin.change_view(), in module django.contrib.admin.options.py changed to take one additional argument to support multiple database. If you override this method, you will need to pass in this additional arguments.

  • Changed in Django 1.4
  • Change Required by Django 1.4
    Example: 
    From:
        def change_view(self, request, object_id, extra_context=None):
            ...
            return super(YourModelAdmin, self).change_view(request, object_id, extra_context)
    To:
        def change_view(self, request, object_id, form_url='', extra_context=None):
            ...
            return super(YourModelAdmin, self).change_view(request, object_id, form_url, extra_context)

[20]: kstateome/django-cas#15 https://github.com/kstateome/django-cas/commit/b92610a615c3b950d5bc3c939d171f8a59b899a5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment