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 中的一个错误?
)问题是如何对这样一个字段进行建模?
PS:与此问题相关的是这张票[2],3年后仍然打开:(
[1] Django:编写自定义模型字段
[2]
I am trying to model a VARBINARY
MySQL field in Django v1.1.1. The binary field stores a hexadecimal representation of data (i.e. one would use INSERT INTO test(bin_val) VALUES X'4D7953514C'
)
Reading the Django documentation[1] I came up with this sollution:
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')
However this doesn't work correctly because:
- Django does a Unicode transformation of the binary data from MySQL
- When saving a new MyTest object, the
get_db_prep_value()
gets called twice (I think this is a bug in Django?)
The question is how would you model such a field?
PS: Related to this problem is this ticket[2] that is still opened after 3 years :(
[1] Django: Writing custom model fields
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题在于 Django 创建数据库表的方式,也与数据库排序规则有关。
我解决这个问题的方法如下:
utf8
并将排序规则更改为utf8_bin
VARCHAR
更改为VARBINARY
return hexlify(value)
to_python
方法中使用的The problem was the way Django creates database tables and was also related to database collation.
The way I solved it was the following:
utf8
and the collation toutf8_bin
VARCHAR
toVARBINARY
in the MySQL tableto_python
methodreturn hexlify(value)
您提到的同一张票证还有一个补丁,它应该提供一些实施该领域的指针。
无论如何,将其存储在 CharField 中的真正问题是什么?
即使您要实现 bin 字段,您也可以扩展 models.CharField 并在 to_python 方法中将其转换为十六进制。
之前也回答了同样的问题:在 Django 模型字段中存储二进制哈希值
The same ticket you referred to also has a patch which should give some pointers towards implementing this field.
In any case whats your real problem to store it in a CharField?
Even if you were to implement a bin field, you could just extend the models.CharField and cast it to hex in the to_python method.
Also the same question has also been answered earlier: Storing a binary hash value in a Django model field
MySQL 既不存储 VARBINARY 字段的十六进制表示形式,也不在 INSERT 语句中要求它。与 VARCHAR 的唯一区别是 MySQL 使用二进制排序规则。您可以传递任何 8 位字符串作为其参数。
MySQL neither store hexadecimal representation for VARBINARY fields nor require it in INSERT statement. The only difference from VARCHAR is that MySQL uses binary collation for it. You can pass any 8-bit string as parameter for it.