Porting Django Apps to Python3

By Kamil Gałuszka S4F Team
7.11.2013 PySilesia

Joke Starter

class _UnexpectedSuccess(Exception):

try: ... # Some great logic here. ...except _UnexpectedSuccess: print("This works ! :) ")

Why Django 1.6? 

  • True Python 3 support ( YAY! ) !
  • Persistent database connection ! ( You used PgBouncer right? )
  • GeoDjango form widgets ( no need of 3rd party floppyforms )
  • Sessions are now JSON serializable 

PS. This release is dedicated to Malcolm Tredinnick. His work won't be forgotten by Django community.

Sad part...

Work by Andrew Godwin (Pull Request #376)
sponsored by crowdfunding on Kickstarter with 

will land in Django 1.7.

We have to wait more...

Python 3 

Start with this... (by Lennart Regebro. Yeah it's free)

There are six awesome tools ;)

from six import with_metaclass

class Meta(type):

class Base(object):

class MyClass(with_metaclass(Meta, Base)):

# Conditionals if needed (last resort)
if six.PY2:     print("YAY! I'm very old python 2")

if six.PY3:     print("I'm new sexy Python 3.3 !")

Fact #1
Unicode is the King

from __future__ import unicode_literals

u'This is bad although it will work on python 3.3'
'This is much better'
b'This is when you explicitly need byte strings'

Question #0. Do you write tests?

Offtopic #Unicode 7.0 did you known...

Fact #1 Unicode is the King

from django.utils.encoding import *      # using asterix is BAD idea ;]
# old utils for strings and unicodesmart_strsmart_unicodeforce_unicode
# new utils for stringssmart_bytessmart_textsmart_text

Fact #1
Unicode is the King. Be kind and use decorators.

from django.utils.encoding import python_2_unicode_compatible
class AbstractBaseUser(models.Model):
    username = models.CharField(_('username'), max_length=128)
    password = models.CharField(_('password'), max_length=128)    last_login = models.DateTimeField(_('last login'), default=timezone.now)

    is_active = True

    REQUIRED_FIELDS = []    def __str__(self): # we rename only __unicode__ to __str__         return self.username

Fact #2
Iterator is your new  friend 

def _iterkeys(self):    for k, v in self._iteritems():
        yield k

def _itervalues(self):
    for k, v in self._iteritems():
        yield v

if six.PY3:
    items = _iteritems
    keys = _iterkeys
    values = _itervalues
    iteritems = _iteritems
    iterkeys = _iterkeys
    itervalues = _itervalues

Fact #3 Tox can be your friend

envlist = py2.7-d1.6, py3.3-d1.6

[testenv] commands = py.test tests/ deps = mock pytest-django [testenv:py2.7-d1.6] basepython = python2.7 deps = django>=1.6,<1.7 [testenv:py3.3-d1.6] basepython = python3.3 deps = django>=1.6,<1.7

Fact #4 Rewrite Exceptions

except MyException as exc:

# Python 2 try: ... except MyException, exc: # Don't do that! ...

Are there JavaScript geeks here?

Meet.JS in Katowice

JavaScript community together (yay!)



Any questions?

Porting Django Apps to Python3

By Kamil Gałuszka

Porting Django Apps to Python3

  • 2,003
Loading comments...

More from Kamil Gałuszka