我有一个 model IPInfo
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)
然后我用 django_filter 做过滤
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 的值“内网“、“外网”做参数值,而不是“ 1 ”和“ 2 ”。
我该怎么做?
1
arischow 2019-01-24 22:19:09 +08:00 via iPhone
IPInfoModel.TYPE_INTRANET
|
3
leisurelylicht OP @arischow ? 这... 什么意思?
|
4
yim7 2019-01-25 03:27:32 +08:00
你可以写一个函数做映射,或者两个常量直接定义为字符串...
|
5
XiaolinLeo 2019-01-25 07:56:30 +08:00
filter_class .get_ip_type_display 试试
|
7
freakxx 2019-01-25 09:49:33 +08:00
不过你数据库存的是 1,2 呀,
不过无论想怎么搞,一般在前端层面的去做 widgets 就 ok 了。 思路这么进去 看这个库的 225 行 ``` class ChoiceFilter(Filter): field_class = ChoiceField # 这一行 def __init__(self, *args, **kwargs): self.null_value = kwargs.get('null_value', settings.NULL_CHOICE_VALUE) super(ChoiceFilter, self).__init__(*args, **kwargs) def filter(self, qs, value): if value != self.null_value: return super(ChoiceFilter, self).filter(qs, value) qs = self.get_method(qs)(**{'%s__%s' % (self.field_name, self.lookup_expr): None}) return qs.distinct() if self.distinct else qs ``` 然后追溯到 django 的 form widgets, 第 550 行, s ``` def render_option(self, selected_choices, option_value, option_label): if option_value is None: option_value = '' option_value = force_text(option_value) if option_value in selected_choices: selected_html = mark_safe(' selected="selected"') if not self.allow_multiple_selected: # Only allow for a single selection. selected_choices.remove(option_value) else: selected_html = '' return format_html('<option value="{}"{}>{}</option>', option_value, selected_html, force_text(option_label)) ``` 然后再把 allow none 那个----也做个处理就 OK 了。 |
8
leisurelylicht OP |
9
freakxx 2019-01-25 11:51:26 +08:00
@leisurelylicht
你把 option_value 改为 lforce_text(option_label) 就可以了。 另外一种做法是,自定义 filter,做个 dict,key,value 再做一遍反向查询。 |
10
leisurelylicht OP @freakxx option_value 和 lforce_text 是 django_filter 里的参数吗?我在文档里没搜到?
|