Code

Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#6416 closed (duplicate)

Storing binary data in the database

Reported by: Sandra <sandravandale@…> Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

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

Attachments (0)

Change History (2)

comment:1 Changed 6 years ago by russellm

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to duplicate
  • Status changed from new to closed

If I'm understanding the actual problem (notwithstanding the proposed solution), this is a duplicate of #2417.

comment:2 Changed 6 years ago by Sandra <sandravandale@…>

Vaguely. #2417 is about adding a BinaryCharField or some such field so you can create binary fields on models. That is no doubt a very good end goal, but before you can think about it, you have to fix this issue with last_executed_query. This is a prerequisite for #2417, not a duplicate.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.