Django ORM 能否以可靠的与后端无关的方式存储无符号 64 位整数(又名 ulong64 或 uint64)?
Posted
技术标签:
【中文标题】Django ORM 能否以可靠的与后端无关的方式存储无符号 64 位整数(又名 ulong64 或 uint64)?【英文标题】:Can the Django ORM store an unsigned 64-bit integer (aka ulong64 or uint64) in a reliably backend-agnostic manner? 【发布时间】:2012-05-27 12:45:28 【问题描述】:我看到的所有文档都暗示您可能能够做到这一点,但没有任何官方 w/r/t ulong64/uint64 字段。有一些现成的选项在这个领域看起来很有希望:
BigIntegerField
... 差不多,但已签名;
PositiveIntegerField
... 32 位外观可疑;和
DecimalField
... 一个用python decimal
类型表示的固定指针,根据the docs ——它可能会变成一个类似迂腐和缓慢的数据库字段,当被放开时,á la DECIMAL 或 NUMERIC PostgreSQL 类型。
...所有这些看起来都像他们可能存储这样的数字。除了没有人会承诺,就像休格兰特描绘的每一个浪漫喜剧角色一样。
我的主要标准是它与 Django 支持的后端一起工作,没有任何 if postgresql (...) elif mysql (...)
类型的特殊情况废话。之后,需要速度——这是视觉数据库应用程序中的模型字段,它将索引图像派生数据(例如感知散列和提取的关键点特征),允许按这些图像的内容进行排序和分组.
那么:有没有一个好的 Django 扩展程序或应用程序可以提供某种符合我目的的PositiveBigIntegerField
?
并且,除此之外:如果有一种简单可靠的方法可以使用 Django 的库存 ORM 来存储无符号的 64 位整数,我想知道。看,我不是二进制高手;我必须在纸上做二进制补码——所以如果你的这种方法涉及一些位移技巧,请不要犹豫解释它是什么,即使它让你觉得很明显。提前致谢。
【问题讨论】:
+1 formuch like every single rom-com character portrayed by Hugh Grant
让我在一个阴沉潮湿的早晨笑了起来。
【参考方案1】:
虽然我没有测试它,但你可能希望只继承BigIntegerField
。原来的BigIntegerField
是这样的(source here):
class BigIntegerField(IntegerField):
empty_strings_allowed = False
description = _("Big (8 byte) integer")
MAX_BIGINT = 9223372036854775807
def get_internal_type(self):
return "BigIntegerField"
def formfield(self, **kwargs):
defaults = 'min_value': -BigIntegerField.MAX_BIGINT - 1,
'max_value': BigIntegerField.MAX_BIGINT
defaults.update(kwargs)
return super(BigIntegerField, self).formfield(**defaults)
派生的PositiveBigIntegerField
可能如下所示:
class PositiveBigIntegerField(BigIntegerField):
empty_strings_allowed = False
description = _("Big (8 byte) positive integer")
def db_type(self, connection):
"""
Returns MySQL-specific column data type. Make additional checks
to support other backends.
"""
return 'bigint UNSIGNED'
def formfield(self, **kwargs):
defaults = 'min_value': 0,
'max_value': BigIntegerField.MAX_BIGINT * 2 - 1
defaults.update(kwargs)
return super(PositiveBigIntegerField, self).formfield(**defaults)
虽然您应该在使用它之前对其进行彻底测试。如果你这样做,请分享结果:)
编辑:
我错过了一件事 - 内部数据库表示。这基于get_internal_type()
返回的值,并且存储了列类型的定义,例如。 here 在 MySQL 后端的情况下确定 here。看起来覆盖db_type()
将使您能够控制该字段在数据库中的表示方式。但是,您需要找到一种方法,通过检查 connection
参数来返回 db_type()
中特定于 DBMS 的值。
【讨论】:
哇,这看起来好得令人难以置信,可以这么说——我不太关心通过FormField
验证人工输入(因为该数据将来自图像分析功能)和如果你把这些东西拿出来,我们就剩下description
文本、MAX_BIGINT
属性和get_internal_type
规范……这些添加都没有让子类告诉 ORM 如何像对待uint64。我很可能弄错了——如果我在这里遗漏了任何这些内容,请告诉我。
@fish2000:你是对的,看我的编辑。我缺少的部分是db_field()
,它旨在根据get_internal_type()
返回的内部类型返回特定于DBMS 的类型,并在特定于DBMS 的data_types
字典中查找(见here)。现在解决你的问题了吗?
不错!很高兴知道 ORM 将其必要的专有边缘案例 SQL 片段堆存放在哪里——我之前没有遇到过,这是使用与 Django 本身相同的供应商特定逻辑实现 get_internal_type()
方法所需要的。这是一个很好的提示,谢谢!
据我所知,db_field
方法应该是 db_type
(提交的编辑正在等待同行评审)。
这也适用于 SQLite,但实际存储的值将是 有符号 64 位整数,因此允许的最大值为 2 ^ 63 - 1以上是关于Django ORM 能否以可靠的与后端无关的方式存储无符号 64 位整数(又名 ulong64 或 uint64)?的主要内容,如果未能解决你的问题,请参考以下文章