Django:如何建模MySQL VARBINARY HEX字段?

3 投票
3 回答
4732 浏览
提问于 2025-04-15 15:10

我正在尝试在Django v1.1.1中建模一个VARBINARY的MySQL字段。这个二进制字段用来存储数据的十六进制表示(比如可以用INSERT INTO test(bin_val) VALUES X'4D7953514C'来插入数据)。

根据Django的文档[1],我想出了这个解决方案:

class MyTest(models.Model):
    bin_val = BinValField()

class BinValField(models.Field):
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        """ DB -> Python """
        return ''.join('%X%X' % ((ord(byte)>>4) & 0xF, ord(byte) & 0xF) for byte in value)

    def get_db_prep_value(self, value):
        """ Python -> DB """
        return a2b_hex(value).decode('latin1')

不过这个方法并不奏效,原因有:

  • Django会对从MySQL获取的二进制数据进行Unicode转换。
  • 在保存一个新的MyTest对象时,get_db_prep_value()这个方法会被调用两次(我觉得这可能是Django的一个bug?)

我的问题是,应该如何建模这样一个字段呢?

附注:与这个问题相关的一个票据[2]在三年后仍然没有解决 :(

[1] Django: 编写自定义模型字段

[2] http://code.djangoproject.com/ticket/2417

3 个回答

0

MySQL 对于 VARBINARY 字段既不存储十六进制的表示法,也不需要在插入数据时使用这种表示法。它和 VARCHAR 字段的唯一区别在于,MySQL 对 VARBINARY 使用的是二进制排序方式。你可以把任何 8 位的字符串作为参数传递给它。

0

你提到的那个问题也有一个补丁,可以给你一些关于如何实现这个字段的提示。

不管怎样,你真正的问题是什么,为什么要把它存储在CharField里呢?

即使你想实现一个二进制字段,你也可以扩展models.CharField,并在to_python方法中把它转换成十六进制。

另外,之前也有人问过同样的问题:在Django模型字段中存储二进制哈希值

2

问题出在Django创建数据库表的方式,以及数据库的排序规则。

我解决这个问题的方法如下:

  • 把表的字符集改成 utf8,排序规则改成 utf8_bin
  • 把MySQL表中的二进制字段从 VARCHAR 改成 VARBINARY
  • to_python 方法中使用 return hexlify(value)

撰写回答