【问题标题】:Create alias for filtering ChoiceField in django-filters在 django-filters 中为过滤 ChoiceField 创建别名
【发布时间】:2020-08-03 22:55:27
【问题描述】:

我有一些型号的过滤器集:

class MyModel(models.Model):
    STATUS_ACTIVE = 0
    STATUS_DONE = 1
    STATUSES = (
        (STATUS_ACTIVE, 'Active'),
        (STATUS_DONE, 'Done'),
    )

    status = models.IntegerField(choices=STATUSES, default=STATUS_ACTIVE)


class ModelFilter(FilterSet):
    status = ChoiceFilter(choices=MyModel.STATUSES)

    class Meta:
        model = MyModel
        fields = (
            'status',
        )

当我向某些 API 发出请求时,我应该使用状态作为数字 - /app/model?status=0

如何给它起别名,这样我就可以使用/app/model?status=active而不是数字,而不改变模型?

【问题讨论】:

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


【解决方案1】:

最后我在库中找到了源代码并创建了这个解决方案:

class AliasesChoiceField(ChoiceField):
    def valid_value(self, value):
        for _, v in self.choices:
            if value == v or str(value) == str(v):
                return True
        return False

class AliasesChoiceFilter(ChoiceFilter):
    field_class = AliasesChoiceField
    def filter(self, qs, value):
        for val, alias in self.extra['choices']:
            if value == alias:
                return super(AliasesChoiceFilter, self).filter(qs, val)
        return super(AliasesChoiceFilter, self).filter(qs, value)

AliasesChoiceField.valid_value(),我只是复制了基本方法并进行了简单的更改以正确验证值。

AliasesChoiceFilter 使用field_class 进行验证,所以我只需将其替换为ChoiceFilter,并将filter() 方法更改为我选择参数的正确映射。

最后我的模型是这样的

class ModelFilter(FilterSet):
    STATUSES = (
        (MyModel.STATUS_ACTIVE, 'active'),
        (MyModel.STATUS_DONE, 'done')
    )
    status = AliasesChoiceFilter(choices=STATUSES)

API 路由 /app/model?status=active 工作正常,设置正确的过滤状态。

但是!此解决方案不适用于 Django Admin 或通过 web api 接口,因为它将提供真实值,并会尝试传递 0 而不是 active

【讨论】:

    猜你喜欢
    • 2019-03-25
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    相关资源
    最近更新 更多