﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
28772	UnicodeWarning produced when using callable default on BinaryField in Python 2	Tim Dawborn	nobody	"This affects versions all the way back from 1.8 and the rest of the 1.x series (the issue tracker only lets me go back to 1.8). This only happens when running under Python 2.

When using a callable `default` value to a `BinaryField` instance, a `UnicodeWarning` is produced due to the comparison of the return value of `default` against a Unicode string (from https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L2306):

{{{#!python
class BinaryField(Field):
    ...
    def get_default(self):
        if self.has_default() and not callable(self.default):
            return self.default
        default = super(BinaryField, self).get_default()
        if default == '':
            return b''
        return default
}}}


I've created a blank Django project called `foo` and created an app called `bar`. In there, I've created a model called `Baz` which has a `BinaryField` with a callable default.

{{{
$ cat bar/models.py
import os

from django.db import models


def my_default():
    return os.urandom(12)


class Baz(models.Model):
    my_field = models.BinaryField(default=my_default)
}}}

I have two virtualenvs setup — one running Python 2.7 and one running 3.6. Both have Django 1.11 installed:
{{{
$ ../ve2/bin/pip install -q --upgrade 'django<2'
$ ../ve3/bin/pip install -q --upgrade 'django<2'
}}}

When running under Python 2, Django versions 1.8 through 1.11 (all minor versions inclusive) produce a `UnicodeWarning` when deprecation warnings are enabled:
{{{
$ ../ve2/bin/python -W default manage.py shell -c 'from bar.models import Baz; b = Baz()'
/private/tmp/django/ve2/lib/python2.7/site-packages/django/db/models/fields/__init__.py:2343: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  if default == '':
$ ../ve3/bin/python -W default manage.py shell -c 'from bar.models import Baz; b = Baz()'
$
}}}

This could be fixed by doing a type check on the returned value of the callable to see if it is of type `six.text_type` a la https://docs.djangoproject.com/en/1.11/topics/python3/#string-handling-with-six:
{{{#!python
class BinaryField(Field):
    ...
    def get_default(self):
        if self.has_default() and not callable(self.default):
            return self.default
        default = super(BinaryField, self).get_default()
        if isinstance(default, six.text_type) and default == '':
            return b''
        return default
}}}

"	Cleanup/optimization	closed	Database layer (models, ORM)	1.8	Normal	wontfix	UnicodeWarning BinaryField		Unreviewed	0	0	0	0	1	0
