使用Django和SQLite存储BLOB数据
首先,我知道有很多类似的问题,但其他的解决方案并没有解决我的具体情况:
在我的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 个回答
在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如说,有人可能会在使用某个特定的功能时,发现它并没有按照预期工作。这种情况可能会让人感到困惑,不知道该怎么解决。
通常,解决这类问题的第一步是检查代码,看看有没有写错的地方。接着,可以查阅相关的文档,了解这个功能的具体用法和注意事项。如果文档中没有找到答案,很多人会选择在网上搜索,看看其他人是否遇到过类似的问题。
在社区论坛,比如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