Storing binary data in the database
|Reported by:||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||master|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
You can store binary data in your database with a CharField that on the database side supports binary data, or is a blob column. The only change that needs to be made to Django is to a function in backend/init.py called last_executed_query. Currently it forces all strings to unicode, so a logical fix would be to catch UnicodeDecodeError, and give a different representation, like base64, hex, or a placeholder like [binary data length=314]. Since last_executed_query seems to be mostly for debugging purposes, I think base64 would at least allow a person to know what data was saved.
Here is something illustrating the proposed fix:
def last_executed_query(self, cursor, sql, params): """ Returns a string of the query last executed by the given cursor, with placeholders replaced with actual values. `sql` is the raw query containing placeholders, and `params` is the sequence of parameters. These are used by default, but this method exists for database backends to provide a better implementation according to their own quoting schemes. """ from django.utils.encoding import smart_unicode, force_unicode # Convert params to contain Unicode values. def to_unicode(s): try: return force_unicode(s, strings_only=True) except UnicodeDecodeError: return force_unicode(s.encode('base64')) if isinstance(params, (list, tuple)): u_params = tuple([to_unicode(val) for val in params]) else: u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()]) return smart_unicode(sql) % u_params