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

发布于 2024-08-07 17:17:08 字数 886 浏览 2 评论 0原文

我正在尝试在 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

留一抹残留的笑 2024-08-14 17:17:08

问题在于 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:

  • changed the table charset to utf8 and the collation to utf8_bin
  • changed the binary field from VARCHAR to VARBINARY in the MySQL table
  • used in the to_python method return hexlify(value)
云朵有点甜 2024-08-14 17:17:08

您提到的同一张票证还有一个补丁,它应该提供一些实施该领域的指针。

无论如何,将其存储在 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

新雨望断虹 2024-08-14 17:17:08

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文