您的位置:首页 > 编程语言 > Go语言

扩展Django admin的list_filter()可使用范围

2018-03-09 18:46 666 查看

需求描述

有时候我们会基于已有数据生成一列在表格中,类似于下面的

class BaseSchema(models.Model):
...
def test_status(self):
# pdb.set_trace()
if datetime.date.today() < self.test_start_date:
return '未到测试区间'
elif self.test_end_date and datetime.date.today() > self.test_end_date:
return format_html('<p style="color: red">已下线</p>')
else:
return format_html('<p style="color: green">进行中</p>')

test_status.short_description = u'测试状态'


但同时我们也希望可以对这一列进行筛选,按常规的话也就是添加到list_filter中:

list_filter = ('test_status')


这时候我们会看到django的温馨报错:

The value of 'list_filter[0]' refers to 'test_status', which does not refer to a Field.


也就是说不能使用list_filter对非Field进行筛选。

解决办法

最简单的方法

那就是把这个字段记录进field啊,这样就可以用了。但是我并不想这么做

更高端的方法

参考https://stackoverflow.com/questions/12102697/creating-custom-filters-for-list-filter-in-django-admin/45136544#45136544第二个回答中的事例:

from django.contrib.admin import SimpleListFilter

class CountryFilter(SimpleListFilter):
title = 'country' # or use _('country') for translated title
parameter_name = 'country'

def lookups(self, request, model_admin):
countries = set([c.country for c in model_admin.model.objects.all()])
return [(c.id, c.name) for c in countries] + [
('AFRICA', 'AFRICA - ALL')]

def queryset(self, request, queryset):
if self.value() == 'AFRICA':
return queryset.filter(country__continent='Africa')
if self.value():
return queryset.filter(country__id__exact=self.value())

class CityAdmin(ModelAdmin):
list_filter = (CountryFilter,)


现在我们知道django中是这样实现的筛选的方法,那我们只要覆盖这个方法就好了:

class StatusFilter(SimpleListFilter):
title = 'status'
parameter_name = 'status'

def lookups(self, request, model_admin):
return [(1, '已下线'), (2, '进行中'), (3, '未到测试区间')]

def queryset(self, request, queryset):
this_day = datetime.date.today()
# pdb.set_trace()
if self.value() == '3':
return queryset.filter(test_start_date__gt=this_day)
elif self.value() == '1':
return queryset.filter(test_end_date__lt=this_day)
elif self.value() == '2':
return queryset.filter(test_end_date__gte=this_day, test_start_date__lte=this_day)


然后在添加进list_filter中:

list_filter = (StatusFilter,)


bingo!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  django filter 扩展 admin