Django:如何建模MySQL VARBINARY HEX字段?
我正在尝试在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: 编写自定义模型字段
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)