Under Python 2, it checks if the class has a __str__ method, and if it doesn’t, it raises an error. Otherwise, it assigns the __str__ method to the name __unicode__ and redefines __str__ as a lamdba function that calls __unicode__ and encodes the result as UTF-8.

Under Python 3, it just returns the unmodified class.

Note that the decorator originally comes from the six package, which consists of multiple utilities to enable Python 2 and 3 compatibility. If you ever want to use it in a non-django project, just use six.

@python_2_unicode_compatible Cheat Sheet

Phew, quite a bit that is going on here! Don’t worry if you didn’t grasp everything on the first read. Wrapping your head around strings, Unicode and encodings and the different behaviors between Python 2 and 3 can take a while.

I’ll try to give a concise summary:

When your code should only run under Python 3, write a __str__ method and don’t use @python_2_unicode_compatible.

When your code should support Python 2 and Python 3, write a __str__ method, make sure it returns unicode under Python 2 and use @python_2_unicode_compatible.

When your code runs under Python 2 and will never run under Python 3, write a __unicode__ method, make sure it actually returns unicode and don’t use @python_2_unicode_compatible.