django:使用 BInaryField 模拟标志字段

Posted

技术标签:

【中文标题】django:使用 BInaryField 模拟标志字段【英文标题】:django: simulate a flags Field using BInaryField 【发布时间】:2022-01-23 01:56:32 【问题描述】:

所以我尝试在 Django(4.0 和 Python3)中模拟标志字段,就像在 C 或 C++ 中一样。它看起来像这样:

typedef enum
    flagA = 0,
    flagB,
    flagC
 myFlags;

有一个uint8,默认情况下是00000000,然后根据标志是打开还是关闭,我会做一些按位运算将三个最低有效位变为1或0。

现在,我可以在我的模型中做到这一点,只需声明 PositiveSmallIntegerFieldBinaryField 并创建一些辅助函数来管理所有这些逻辑。

请注意,我不需要能够通过此字段进行查询。我只是希望能够将它存储在数据库中并偶尔修改它。

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

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

不确定如何获取存储在数据库中的实际值来进行if 比较。

也许我的方法不是处理这个问题的最佳方法,所以我愿意接受你们可能提出的任何建议。但我想如果我知道如何从我的函数中从数据库中获取实际的二进制值,我可以设法做到这一点。

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

【问题讨论】:

【参考方案1】:

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

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

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

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

如果是这样,您应该查看SmallIntegerField,它存储为 16 位有符号整数并使用getter-setter 方法来维护它,like this。你建议的方法的实现思路大体上是对的。

祝你好运:)

【讨论】:

我想我会选择 SmallIntegerField 方法,感谢您提供的信息。无论如何,我有点好奇在创建继承自例如 IntegerField 的 CustomField 时如何获取 Field 的值。如果我想在自定义 Field 类中创建一个函数,我的意思是。关于如何做到这一点的任何想法? 我不完全确定,关于CustomField 的官方文档对我来说看起来非常直观和描述性。 that 不正是您需要的吗?

以上是关于django:使用 BInaryField 模拟标志字段的主要内容,如果未能解决你的问题,请参考以下文章

Django BinaryField 检索为内存位置?

Django数据模型--字段整理

Django的ORM字段与MySQL数据库实际字段的对应关系

Django模型类之models字段类型和参数以及元数据meta

Django:如何获取当前 URL 标记名(用于分页)?

CSS 模拟点击事件——css 模拟聚焦事件——css 向下的角标显示