Sunday, July 13, 2008

重写django的FilterSpec来实现filter tag的数据自定义

重写django的FilterSpec来实现filter tag的数据自定义, 注意FilterSpec的register始终将新加的test function和factory的tuple放到registered list的最后, 但是当FilterSpec查找model匹配的FilterSpec的时候是顺序遍历的, 所以当在FilterSpec中只要有一个test function返回True, 那么model就用这个, 就是说model一直用第一个匹配的FilterSpec, 所以就有了下边的insert_first_filter_spec.

from django.contrib.admin.filterspecs import FilterSpec

def insert_first_filter_spec(test,factory):
FilterSpec.filter_specs.insert(0,(test,factory))

class AdvancedChoicesFilterSpec(FilterSpec):
def __init__(self, f, request, params, model):
super(AdvancedChoicesFilterSpec, self).__init__(f, request, params, model)
self.lookup_kwarg = '%s__exact' % f.name

make models's field default value to default filter
self.lookup_val = request.GET.get(self.lookup_kwarg, None) or self.field.default

def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
for k, v in self.field.choices:
yield {'selected': str(k) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: k}),
'display': v}

replace choices tag factory
insert_first_filter_spec(lambda f: bool(f.choices), AdvancedChoicesFilterSpec)

No comments: