使用Django和SQLite存储BLOB数据

2 投票
2 回答
4769 浏览
提问于 2025-04-17 19:31

首先,我知道有很多类似的问题,但其他的解决方案并没有解决我的具体情况:

在我的sqlite数据库中,有一些二进制数据(比如SHA1和类似的哈希值)。通过谷歌搜索和阅读django文档,我得出了以下内容:

import base64

class BlobField(models.Field):
""" 
Stores raw binary data
"""

description = 'Stores raw binary data'
__metaclass__ = models.SubfieldBase

def __init__(self, *args, **kwds):
    super(BlobField, self).__init__(*args, **kwds)

def get_internal_type(self):
    return "BlobField"

def get_db_prep_value(self, value, connection=None, prepared=False):
    return base64.decodestring(value)

def to_python(self, value):
    return base64.encodestring(value)

这个代码实现了我想要的功能,值在合适的时候被编码和解码,但在将模型保存到数据库时,我遇到了以下错误:

数据库错误:你不能使用8位字节字符串,除非你使用一个可以解释8位字节字符串的text_factory(比如text_factory = str)。强烈建议你将应用程序切换到Unicode字符串。

我该如何解决这个问题?(最好不要影响到我应用中其他地方的Unicode兼容性)

我不能改变数据库列的格式,因为这些数据被另一个应用程序使用。


编辑:根据@filip-dupanovic的建议,我对BinaryField类进行了如下修改:

class BinaryField(models.Field):
description = _("原始二进制数据")

def __init__(self, *args, **kwargs):
    kwargs['editable'] = False
    super(BinaryField, self).__init__(*args, **kwargs)
    if self.max_length is not None:
        self.validators.append(validators.MaxLengthValidator(self.max_length))

def get_internal_type(self):
    return "BinaryField"

def get_default(self):
    if self.has_default() and not callable(self.default):
        return self.default
    default = super(BinaryField, self).get_default()
    if default == '':
        return b''
    return default

def get_db_prep_value(self, value, connection, prepared=False):
    #value = super(BinaryField, self
    #    ).get_db_prep_value(value, prepared, connection=connection)
    #if value is not None:
    #    return connection.Database.Binary(value)
    return value

注意我在get_db_prep_value()中插入的注释,这样做后,它按预期工作,但如果我取消注释这些行,就会出现错误:

类型错误:get_db_prep_value()得到了多个关键字参数'connection'的值。

我可以接受这个情况,但不太明白不调用super()的后果。即使不调用它,代码还会正常工作吗?

2 个回答

0

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如说,有人可能会在使用某个特定的功能时,发现它并没有按照预期工作。这种情况可能会让人感到困惑,不知道该怎么解决。

通常,解决这类问题的第一步是检查代码,看看有没有写错的地方。接着,可以查阅相关的文档,了解这个功能的具体用法和注意事项。如果文档中没有找到答案,很多人会选择在网上搜索,看看其他人是否遇到过类似的问题。

在社区论坛,比如StackOverflow,很多开发者会分享他们的经验和解决方案。通过阅读这些帖子,可能会找到解决自己问题的线索或者直接的答案。

总之,遇到问题时,不要着急,先冷静下来,逐步排查,通常都能找到解决办法。

def get_db_prep_value(self, value, connection, prepared=False):
    value = super(BinaryField, self
        ).get_db_prep_value(value, connection, prepared)
    if value is not None:
        return connection.Database.Binary(value)
    return value
1

最近关闭的票据 #2417 增加了一个 BinaryField 模型字段。你可以看看 这个提交,特别是关于如何将你内部的 BlobField 字段类型映射到你的数据库支持的合适类型的变化。

撰写回答