在Django Admin中保持过滤器
我想要实现的目标是:
- 我进入管理网站,给对象列表应用一些筛选条件
- 我点击一个对象进行编辑,修改,修改,最后点击“保存”
- 网站把我带回对象列表...没有任何筛选。我希望能记住第一步的筛选条件,并且继续应用。
有没有简单的方法可以做到这一点?
7 个回答
1
有一个简单的方法可以做到这一点,但这并不是一个通用的解决方案,需要对每个你想支持的 ModelAdmin
进行修改。也许有更通用的方法,但我没有花时间去解决这个问题。
第一步是为过滤器写一个自定义的 FilterSpec
(可以参考Harley的帖子,里面有一些有用的链接),这个过滤器会把选择的过滤值保存在会话中(当不再需要时会删除它)。
# in cust_admin/filterspecs.py
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
class MyFilterSpec(ChoicesFilterSpec):
def __init__(self, f, request, params, model, model_admin):
super(MyFilterSpec, self).__init__(f, request, params, model,
model_admin)
if self.lookup_val is not None:
request.session[self.lookup_kwarg] = self.lookup_val
elif self.lookup_kwarg in request.session:
del(request.session[self.lookup_kwarg])
# Register the filter with a test function which will apply it to any field
# with a my_filter attribute equal to True
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'my_filter', False),
MyFilterSpec))
你必须在某个地方导入这个模块,比如你的 urls.py
文件:
# in urls.py
from cust_admin import filterspecs
在你想应用过滤器的字段上设置一个属性:
# in models.py
class MyModel(models.Model):
my_field = Models.IntegerField(choices=MY_CHOICES)
my_field.my_filter = True
在一个自定义的 ModelAdmin
类中,重写 change_view
方法,这样在用户点击保存后,他们会被带回列表视图,并且过滤字段的值会被添加到网址中。
class MyModelAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, extra_context=None):
result = super(MyModelAdmin, self).change_view(request, object_id,
extra_context)
if '_save' in request.POST:
if 'my_field__exact' in request.session:
result['Location'] = '/admin/myapp/mymodel/?my_field__exact=%s' \
% request.session['my_field__exact']
return result
2
点击“返回”两次?
4
很遗憾,这件事没有简单的方法。过滤的设置似乎没有保存在任何会话变量里。
通常的做法是点击返回两次,但如果你刚刚修改了某个对象,导致它不应该再通过你的过滤条件显示,这样的操作可能会让人觉得麻烦和烦人。
如果只是偶尔需要这样做,点击返回两次或者重新进行过滤是最简单的方法。
如果你经常需要过滤,或者想学习如何修改管理界面(其实这个界面很开放,也很简单),你可以尝试写一个FilterSpec。
有一种非常糟糕的方法是修改管理界面,让你在点击“保存”后直接跳转到你过滤后的网址。我不推荐这样做,但这也是一种选择。
还有一种相对简单的方法是写一个通用的视图来显示你的过滤对象,然后使用Django表单从那里编辑这些项目。我建议你看看这个,你会惊讶于其实只需要写很少的代码就能实现一个简单的查看/编辑页面。