【问题标题】:Filter on a field with choices过滤带有选项的字段
【发布时间】:2019-04-09 23:10:15
【问题描述】:

我有这个字段:

operation = models.CharField(max_length=10, choices=OPERATIONS)

让这个过滤器起作用:

class OperationFilter(django_filters.Filter):

    def filter(self, qs, value):
        try:
            qs = qs.filter(operation=value.upper())
        except:
            pass
        return qs

带网址:

/api/v1/operation/?operation=CREATE

但是使用默认过滤器(没有额外的OperationFilter)失败:

{
    "operation": [
        "Select a valid choice. %(value)s is not one of the available choices."
    ]
}

为什么对有选择的字段进行过滤器失败?

对于其他非选择字段,默认过滤器可以正常工作:

/api/v1/operation/?recipient=recipient-19

编辑

OPERATIONS:

from enum import Enum

def enum_as_choices(enum_class):
    """From an enum class, generate choices for a django field"""
    return ((entry, entry.value) for entry in enum_class)

class OperationType(Enum):
    CREATE = 'CREATE'
    STATUS = 'STATUS'
    EXPAND = 'EXPAND'
    DELETE = 'DELETE'

OPERATIONS = enum_as_choices(OperationType)

【问题讨论】:

  • 您的OPERATIONS 选项是否包括空白选项或默认选项?
  • @DanielH.,不,没有空白选择。选项来自Enum
  • 请在帖子中包含您如何定义Enum
  • 请显示 OPERATIONS 变量。
  • 你在使用 DRF 吗?

标签: django django-rest-framework django-filter


【解决方案1】:

您正在使用django_filters 包,我建议您阅读文档,因为您已经支持此

https://django-filter.readthedocs.io/en/master/ref/filters.html#choicefilter

只需将您的 choices 指向其他答案建议的值(或查看文档中的示例)

【讨论】:

    【解决方案2】:

    您编写的选项将被转换为这种 Python 表示:

    (
        ('OperationType.CREATE', 'CREATE'), 
        ('OperationType.STATUS', 'STATUS'), 
        ('OperationType.EXPAND', 'EXPAND'), 
        ('OperationType.DELETE', 'DELETE')
    )
    

    如您所见,存储在操作字段(在 DB 中)中的实际值为 'OperationType.CREATE' 等。 因此,您应该将您的选择更改为正常的常量选择,或者您应该使用 'OperationType.CREATE' 之类的内容进行过滤,这不是 IMO 的好选择。

    您也可以像这样更改enum_as_choices 方法:

    def enum_as_choices(enum_class):
        """From an enum class, generate choices for a django field"""
        return ((entry.name, entry.value) for entry in enum_class)
    

    【讨论】:

    • 我同意你的观点,我认为最好在函数return tuple((entry.name, entry.value) for entry in enum_class)中使用tuple()list()
    • 其实不是('OperationType.CREATE', 'CREATE'),而是(OperationType.CREATE, 'CREATE')。使用名称可以解决问题,如('CREATE', 'CREATE')。您更正的enum_as_choices 可以解决问题。谢谢!
    • 您对类型是正确的,但保存在数据库中的实际数据是您的枚举字段的 str(),我提到了它。
    【解决方案3】:

    您尚未在 OPERATIONS 中定义空白/默认选项。为此,请添加如下内容:

    OPERATIONS = (
        ('', 'NONE'),
        # the rest of your choices here...
    )
    

    但您还需要将模型更新为:

    operation = models.CharField(max_length=10, choices=OPERATIONS, default='NONE')
    

    【讨论】:

    • 问题与默认选择无关。
    猜你喜欢
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 2021-12-09
    相关资源
    最近更新 更多