Index: django/db/models/fields/__init__.py =================================================================== --- django/db/models/fields/__init__.py (revision 9673) +++ django/db/models/fields/__init__.py (working copy) @@ -417,6 +417,26 @@ defaults.update(kwargs) return super(CharField, self).formfield(**defaults) + +class BinaryField(Field): + """Sometimes we have fields that need to store a small amount of binary + data. This is different then a varchar on postgresql at least because it + will not allow fields that are just nul bytes. + """ + + def get_internal_type(self): + return "BinaryField" + +class BlobField(Field): + """Sometimes we have fields that need to store a large amounts of binary + data. + """ + + def get_internal_type(self): + return "BlobField" + + + # TODO: Maybe move this into contrib, because it's specialized. class CommaSeparatedIntegerField(CharField): def formfield(self, **kwargs): Index: django/db/backends/postgresql/introspection.py =================================================================== --- django/db/backends/postgresql/introspection.py (revision 9673) +++ django/db/backends/postgresql/introspection.py (working copy) @@ -4,6 +4,7 @@ # Maps type codes to Django Field types. data_types_reverse = { 16: 'BooleanField', + 17: 'BlobField', 21: 'SmallIntegerField', 23: 'IntegerField', 25: 'TextField', Index: django/db/backends/postgresql/creation.py =================================================================== --- django/db/backends/postgresql/creation.py (revision 9673) +++ django/db/backends/postgresql/creation.py (working copy) @@ -8,6 +8,8 @@ # If a column type is set to None, it won't be included in the output. data_types = { 'AutoField': 'serial', + 'BinaryField': 'bytea', + 'BlobField': 'bytea', 'BooleanField': 'boolean', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', Index: django/db/backends/sqlite3/creation.py =================================================================== --- django/db/backends/sqlite3/creation.py (revision 9673) +++ django/db/backends/sqlite3/creation.py (working copy) @@ -9,6 +9,8 @@ # schema inspection is more useful. data_types = { 'AutoField': 'integer', + 'BinaryField': 'BLOB', + 'BlobField': 'BLOB', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', Index: django/db/backends/mysql/base.py =================================================================== --- django/db/backends/mysql/base.py (revision 9673) +++ django/db/backends/mysql/base.py (working copy) @@ -30,6 +30,7 @@ from django.db.backends.mysql.introspection import DatabaseIntrospection from django.db.backends.mysql.validation import DatabaseValidation from django.utils.safestring import SafeString, SafeUnicode +from django.utils.encoding import smart_unicode # Raise exceptions for database warnings if DEBUG is on from django.conf import settings @@ -46,10 +47,22 @@ # add special handling for SafeUnicode and SafeString as MySQLdb's type # checking is too tight to catch those (see Django ticket #6052). django_conversions = conversions.copy() + +binstr_conversion = [(FLAG.BINARY, buffer), + (FLAG.BLOB, smart_unicode), + ] + django_conversions.update({ FIELD_TYPE.TIME: util.typecast_time, FIELD_TYPE.DECIMAL: util.typecast_decimal, FIELD_TYPE.NEWDECIMAL: util.typecast_decimal, + FIELD_TYPE.TINY_BLOB: binstr_conversion, + FIELD_TYPE.MEDIUM_BLOB: binstr_conversion, + FIELD_TYPE.LONG_BLOB: binstr_conversion, + FIELD_TYPE.BLOB: binstr_conversion, + FIELD_TYPE.VARCHAR: binstr_conversion, + FIELD_TYPE.VAR_STRING: binstr_conversion, + FIELD_TYPE.STRING: binstr_conversion, }) # This should match the numerical portion of the version numbers (we can treat Index: django/db/backends/mysql/introspection.py =================================================================== --- django/db/backends/mysql/introspection.py (revision 9673) +++ django/db/backends/mysql/introspection.py (working copy) @@ -7,7 +7,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): data_types_reverse = { - FIELD_TYPE.BLOB: 'TextField', + FIELD_TYPE.BLOB: 'BlobField', + FIELD_TYPE.LONG_BLOB: 'BlobField', + FIELD_TYPE.TINY_BLOB: 'BlobField', + FIELD_TYPE.MEDIUM_BLOB: 'BlobField', FIELD_TYPE.CHAR: 'CharField', FIELD_TYPE.DECIMAL: 'DecimalField', FIELD_TYPE.NEWDECIMAL: 'DecimalField', Index: django/db/backends/mysql/creation.py =================================================================== --- django/db/backends/mysql/creation.py (revision 9673) +++ django/db/backends/mysql/creation.py (working copy) @@ -8,6 +8,8 @@ # If a column type is set to None, it won't be included in the output. data_types = { 'AutoField': 'integer AUTO_INCREMENT', + 'BinaryField': 'varbinary(%(max_length)s)', + 'BlobField': 'blob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', @@ -63,4 +65,4 @@ field.rel.to._meta.db_table, field.rel.to._meta.pk.column) ] return table_output, deferred - \ No newline at end of file + Index: django/db/backends/__init__.py =================================================================== --- django/db/backends/__init__.py (revision 9673) +++ django/db/backends/__init__.py (working copy) @@ -172,7 +172,11 @@ from django.utils.encoding import smart_unicode, force_unicode # Convert params to contain Unicode values. - to_unicode = lambda s: force_unicode(s, strings_only=True) + def to_unicode(s): + if isinstance(s,buffer): + return u'' % len(s) + return force_unicode(s, strings_only=True) + if isinstance(params, (list, tuple)): u_params = tuple([to_unicode(val) for val in params]) else: