有没有办法根据值查询Django中的枚举类型?

时间:2013-12-29 18:22:37

标签: python django django-models enumerated-types

我正在摸索着这个。我的数据库中有一个枚举数据。我的模型有类似的东西:

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中的枚举类型?

1 个答案:

答案 0 :(得分:1)

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

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

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

就你的问题而言,这里的问题是你正在使用IntegerField myfield来尝试按字符串过滤。无论何时进行筛选查找(filter(...) or exclude(...)),都必须提供与数据库中存储的内容相关的值。因此,无论何时要在IntegerField上进行过滤,都必须提供一个用于过滤的整数。我不确定为什么Django允许你选择IntegerField,其中第一个值不是整数,但你应该改变它。如果您将使用上述示例选项值,则可以按

过滤yesno
.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)。