如果我们有这样一个model:

class IPInfoModel(models.Model):
TYPE_INTRANET = 1
TYPE_INTERNET = 2
IP_TYPES = (
(TYPE_INTRANET, u'内网'),
(TYPE_INTERNET, u'外网'),
)
ip = models.GenericIPAddressField("IP", unique=True)
ip_type = models.SmallIntegerField(choices=IP_TYPES)

然后我使用 rest_frame_work + django_filter 做API

from django_filters import rest_framework as django_filters 

class IPInfoFilter(django_filters.FilterSet):
ip_type = django_filters.ChoiceFilter(choices=IPInfoModel.IP_TYPES) class Meta:
model = IPInfoModel
fields = ["ip_type",] class IPInfoViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = IPInfoModel.objects.all()
serializer_class = IPInfoSerializer
filter_class = IPInfoFilter

但是这样在过滤 ip_type 时,只能使用choice field 的 key 值 “1”, “2” 来进行过滤。

这样很不直观,那么如何才能使用choice field 的 value 值 “内网”, “外网” 来过滤对象呢?


方法一

我的做法是通过自定义一个 ChoiceValueFilter,并覆盖 Django 的 forms.ChoiceField 中的验证函数 valid_value 来实现。

代码如下:

from django import forms

from django_filters import rest_framework as django_filters
from django_filters.conf import settings class ChoiceValueField(forms.ChoiceField):
def valid_value(self, value):
text_value = str(value) for k, v in self.choices:
if value == v or text_value == str(v):
return True return False class ChoiceValueFilter(django_filters.Filter):
field_class = ChoiceValueField def __init__(self, *args, **kwargs):
self.null_value = kwargs.get('null_value', settings.NULL_CHOICE_VALUE)
self.choices = kwargs.get('choices')
super().__init__(*args, **kwargs) def filter(self, qs, value):
value_map = {v: k for k, v in self.choices} return qs.filter(ip_type=value_map[value]) if value else qs

这样做的好处是

  1. 比较通用,只要传入对应choice field 的元祖就可以使用了。
  2. 仍然会对传入的参数进行验证,保证只能使用 choice field 的 value 值中已有的值进行过滤。

然后改写原有的IPInfoFilter, 改为使用 ChoiceValueFilter 就可以了。

class IPInfoFilter(django_filters.FilterSet):
ip_type = ChoiceValueFilter(choices=IPInfoModel.IP_TYPES) class Meta:
model = IPInfoModel
fields = ["ip_type", "is_vip"]

方法二

也可以通过自定义filter的方法来实现

参考: https://django-filter.readthedocs.io/en/master/ref/filters.html#method

class IPInfoFilter(django_filters.FilterSet):
ip_type = django_filters.CharFilter(method='filter_ip_type') def filter_ip_type(self, queryset, name, value):
# create a dictionary string -> integer
value_map = {v: k for k, v in IPInfoModel.IP_TYPES.items()}
# get the integer value for the input string
value = value_map[value]
return queryset.filter(ip_type=value)

如何在django-filter中用choice field 的 value 值过滤对象的更多相关文章

  1. Django filter中用contains 在mysql中的问题

    用PYTHON ,DJANGO 做站,在通常的情况下,需要用到 orM 的查询方法,比如object.filter(tag__contains='keywords').... 在这种情况下,如果你跟踪 ...

  2. 深入浅出SharePoint——获取Choice Field的Mapping value

    list field对应的caml定义如下 <Field Type="Choice" DisplayName="Inspection Result" Re ...

  3. 如何在Django模型中管理并发性 orm select_for_update

    如何在Django模型中管理并发性 为单用户服务的桌面系统的日子已经过去了 - 网络应用程序现在正在为数百万用户提供服务,许多用户出现了广泛的新问题 - 并发问题. 在本文中,我将介绍在Django模 ...

  4. filter 中用spring StopWatch 监控请求执行时间

    在filter中用spring stopWatch 来统计每个请求的执行时间: 虽然在firefox 中可以清楚的看到每个请求的执行时间,但是为了测试,记录日志, 方便以后查询维护. 还是必要的,下面 ...

  5. Flask WTForm disable choice field

    Flask disable choice field ChoiceField = { render_kw={'disabled':''} } form.my_field.render_kw = {'d ...

  6. Django——8 关系表的数据操作 表关联对象的访问 多表查询

    Django 关系表中的数据操作 表关联对象的访问 关联对象的add方法 create方法 remove方法 clear方法 多表查询 查询补充 聚合查询 分组查询 F查询 Q查询 关系表的数据操作 ...

  7. Django model.py表单的默认值 默认允许为空

    Field.null 默认是null=False,这时不能传入NULL型数据,但是可以是空字符. 如果BooleanField中想要null数据类型,可以选择NullBooleanField   Fi ...

  8. Filter中排除对指定URL的过滤

    1. 我们可以在web.xml中配置filter来对指定的URL进行过滤,进行一些特殊操作如权限验证等. <!– session过滤filter –> <filter> < ...

  9. django - request.POST和request.body获取值时出现的情况

    django request.POST / request.body 当request.POST没有值 需要考虑下面两个要求 1.如果请求头中的: Content-Type: application/ ...

随机推荐

  1. 第八届极客大挑战 Web-iPhone X

    题目: 解题思路: 第一次看到html里只有字其他啥也没有的题,一脸懵逼,学长提示抓包改包,于是开始我的苦逼解题. 0x01 抓包 0x02 改包 由于题目说只有iphoneX才能接受这个websit ...

  2. Ubuntu 安装 uWSGI

    uWSGI官方网址: https://pypi.org/project/uWSGI/ 使用如下命令安装: pip install uWSGI 报如下错: Collecting uWSGI Using ...

  3. Linux - 查看所有服务状态

    ubuntu: service --status-all 例如可查看ssh, apache2等服务是否开启

  4. 25 JavaScript对象原型&ES5新的对象方法

    JavaScript对象原型 所有JavaScript对象都从原型继承对象和方法 日期对象继承自Date.prototype,数组继承自Array.prototype,对象构造器新建的对象Person ...

  5. springboot pom问题及注解

    springboot pom不需要指定版本号 springboot会自己管理版本号 <!-- 支持热部署 --> <dependency> <groupId>org ...

  6. mybatis源码探索笔记-4(缓存原理)

    前言 mybatis的缓存大家都知道分为一级和二级缓存,一级缓存系统默认使用,二级缓存默认开启,但具体用的时候需要我们自己手动配置.我们依旧还是先看一个demo.这儿只贴出关键代码 public in ...

  7. Notepad++查看文本文件的总的字符数、GBK字节数、UTF8字节数

    如果其编码是 小结:UTF-8编码下,一个汉字占3字节,GBK编码下,一个汉字占2字节:

  8. pexpect &&pxssh

    python 3.6 pip  install pexpect #!/usr/bin/python3 import os import sys curPath = os.path.abspath(os ...

  9. idea提交项目到码云

    1.安装Git 2.在码云上创建项目 3.在IDEA提交项目到码云

  10. php 基础 php获取前一天,前一个月,前一年的时间

    获取前一天的时间: $mytime= date("Y-m-d H:i:s", strtotime("-1 day")); $mytime=mktime(0, 0 ...