django:使用BInaryField模拟flags字段



所以我试图在Django(4.0和Python3(中模拟一个flags字段,就像在C或C++中一样。它看起来是这样的:

typedef enum{
flagA = 0,
flagB,
flagC
} myFlags;

有一个默认为00000000uint8,然后根据标志是打开还是关闭,我会做一些逐位操作,将三个最低有效位变成1或0。

现在,我可以在我的模型中通过简单地声明PositiveSmallIntegerFieldBinaryField并创建一些辅助函数来管理所有这些逻辑来实现这一点。

请注意,我不需要就可以通过此字段进行查询。我只想能够把它存储在数据库中,偶尔修改一下

由于可以扩展字段,我想知道将所有这些逻辑封装在从BinaryField继承的自定义字段中是否更干净。但我真的不确定如何从自定义类中操作Field值。

class CustomBinaryField(models.BinaryField):
description = "whatever"
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 1
super().__init__(*args, **kwargs)

例如,如果我想在CustomBinaryField中创建一个方法,如下所示,其中myFlagsStr包含枚举的str表示。

def getActiveFlags(self):
// For each bit which is set to 1 in the Binary value
// add it to an array with it's name such as: [flagA, flagC]
array = []
if self.value & (1 << myFlags.flagA):
array.append(myFlagsStr[flagA])
if self.value & (1 << myFlags.flagB):
array.append(myFlagsStr[flagB])
if self.value & (1 << myFlags.flagC):
array.append(myFlagsStr[flagC])
return array

不知道如何获得存储在DB中的实际值来进行if比较。

也许我的方法不是处理这个问题的最佳方法,所以我愿意接受你们的任何建议。但我认为,如果我知道如何从函数中获得DB中的实际二进制值,我就可以按照现在的方式做到这一点。

我看到有一个图书馆https://github.com/disqus/django-bitfield它处理了这个问题,但它仅限于使用PostgreSQL,而且,如前所述,我真的不需要通过这些标志进行过滤,所以更简单的方法也可以。

在django中,构建此类功能的常见方法是使用MultipleChoiceField。它假定数据存储在相关的表中,我认为这不是您想要的。

第二个机会是使用ArrayField,它也不适合您,因为您不希望您的解决方案局限于PostgreSQL。

如果要快速而直接地执行此操作,可以使用JSONField并存储Choices的字符串或数字ID。但如果你习惯了C++,你就不会喜欢这样:(

MariaDB 10.2.7+、MySQL 5.7.8+、Oracle、PostgreSQL和SQLite支持JSONField(启用了JSON1扩展(。

如果是这样,您应该查看SmallIntegerField,它存储为16位带符号的int,并使用getter-setter方法来维护它,如下所示。总的来说,你建议的方法的实施思路是正确的。

祝你好运:(

最新更新