【问题标题】:Is There a Way to Query Enumerated Types in Django Based on Values?有没有办法根据值在 Django 中查询枚举类型?
【发布时间】:2013-12-30 03:09:44
【问题描述】:

我正在为此挠头。我的数据库中有一个枚举数据。我的模型是这样的:

class SomeModel(models.Model):
    TWOCHOICE = (
    ('YES', 'YES'),
    ('NO', 'NO'),
    ('DK', 'Don't Know'),
    )

myfield = models.IntegerField(max_length=1, choices=TWOCHOICE)

现在当我想查询这个时,我不能使用:

SomeModel.objects.filter(myfield__in = ['YES', 'NO'])

这看起来最直接。我必须使用整数值。所以我最终使用了:

SomeModel.objects.filter(myfield__in = [[t[0] for t in SomeModel.TWOCHOICE].index(i) for i in ['YES', 'NO']])

但这还不够。这些字段似乎是从 1 开始索引的!!!!所以我需要类似的东西:

SomeModel.objects.filter(myfield__in = [[t[0] for t in SomeModel.TWOCHOICE].index(i)+1 for i in ['YES', 'NO']])

我只是觉得这种方式太复杂了。有没有更好的方法来查询 Django 中的枚举类型?

【问题讨论】:

  • 我刚刚预感到 0 是为数据库中的 NULL 值保留的。但这至少记录在某处吗?
  • 这甚至不是一个有效的字段定义。选项的键需要与字段的类型相同,在本例中为整数。而且Django会使用key的绝对值,而不是基于一些枚举计算出来的值。
  • 感谢 Daniel 的启发。这解决了我所有的问题......

标签: python django django-models enumerated-types


【解决方案1】:

对于可读性的选择字段,Django 允许您指定两个值,第一个是要存储在 DB 中的实际值,第二个将显示在表单等中以提高可读性。例如在

CHOICES = (
    (0, 'No'),
    (1, 'Yes'),
    (2, 'Don\'t Know'),
)

将存储在数据库中的值将是[0,1,2],但是为了便于阅读,它们的相关字符串将以表单等形式显示。

现在,至于您的问题,这里的问题是您使用 IntegerField 来表示 myfield,但是却试图通过字符串进行过滤。每当您进行过滤查找 (filter(...) or exclude(...)) 时,您必须提供与数据库中存储的内容相关的值。因此,每当您想过滤 IntegerField 时,您必须提供一个整数进行过滤。我不确定为什么 Django 允许您选择 IntegerField,其中第一个值不是整数,但您可能应该更改它。如果您将使用上面的示例选择值,您可以过滤 yesno by

.filter(myfield__in=[0,1])

如果你想通过关联的字符串值进行过滤,真的没有简单的方法。您必须先查找与字符串相关的存储值。

def lookup_choices(choices, values):
    choices = dict(choices)
    rchoices = {choices [k]: k for k in choices}
    return [rchoices[v] for v in values]

.filter(myfield__in=lookup_choices(CHOICES, ['Yes', 'No'])

但是您很少需要这样做,因为 Django 只会使用关联的字符串值来呈现值(选择框),但总是会返回实际值(例如 form.cleaned_data)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 2021-08-03
    • 2011-06-26
    • 2014-02-17
    相关资源
    最近更新 更多