【问题标题】:Keeping filters in Django Admin在 Django Admin 中保留过滤器
【发布时间】:2010-09-15 16:53:37
【问题描述】:

我想要达到的是:

  • 我进入管理站点,对对象列表应用一些过滤器
  • 我点击对象编辑,编辑,编辑,点击“保存”
  • 站点将我带到对象列表...未过滤。我希望记住并应用第 1 步中的过滤器。

有简单的方法吗?

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    此功能已作为 1.6 版本的一部分添加到 Django,现在默认启用。在release notes中有描述:

    ModelAdmin 现在在创建后保留列表视图中的过滤器, 编辑或删除对象。可以恢复以前的 通过设置 preserve_filters 属性清除过滤器的行为 为假。

    【讨论】:

      【解决方案2】:

      在 Django 项目中有一个更改请求,正是要求提供此功能。

      等待签入的只是一些测试和文档。您可以编写这些内容并帮助整个项目,或者您可以直接获取建议的补丁(靠近页面底部)并尝试一下。

      https://code.djangoproject.com/ticket/6903

      【讨论】:

        【解决方案3】:

        在我看来,最好覆盖 ModelAdmin changelist_viewchange_view 的方法:

        像这样:

        class FakturaAdmin(admin.ModelAdmin):
        
        [...]
        
        def changelist_view(self, request, extra_context=None):
            result = super(FakturaAdmin, self).changelist_view(request, extra_context=None)
            request.session['qdict'] = request.GET
            return result
        
        def change_view(self, request, object_id, extra_context=None):
            result = super(FakturaAdmin, self).change_view(request, object_id, extra_context)
            try:
                result['location'] = result['location']+"?"+request.session['qdict'].urlencode()
            except:
                pass
            return result
        

        如您所愿,保存对象后,您将返回到具有活动过滤器的对象列表。

        【讨论】:

          【解决方案4】:

          另一种方法是将过滤器嵌入到查询集中。

          您可以使用按您想要的方式过滤的管理器动态创建代理模型,然后调用 admin.site.register() 来创建新的模型管理员。然后所有链接都将与此视图相关。

          【讨论】:

            【解决方案5】:

            有一个简单的技巧可以做到这一点,但这不是一个通用的解决方案,需要修改你想要支持的每个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 方法,以便用户单击保存 后,他们将返回到列表视图,并将过滤字段值添加到URL。

            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
            

            【讨论】:

            • 这是否意味着每次查看模型的管理页面都会被过滤掉?还是它只记得您为会话应用的过滤器?
            【解决方案6】:

            不幸的是,没有简单的方法可以做到这一点。过滤似乎没有保存在任何会话变量中。

            点击两次是正常的方法,但如果您刚刚更改了一个对象以使其不再使用您的过滤器显示,那么它可能会很笨拙和烦人。

            如果只是一次性的,点击返回两次或再次过滤,这是最简单的方法。

            如果您要更频繁地进行过滤,或者您只是想了解如何破解管理员(这非常开放且简单),您需要写一个FilterSpec

            查看herehere 以了解人们自己编写的示例。

            执行此操作的一个非常非常糟糕的方法是编辑管理界面,以便在您单击“保存”后,您将被重定向到过滤后的 URL。我根本不推荐这个,但这是一个选择。

            另一种相当简单的方法是编写一个通用视图来显示您过滤的对象,然后使用 Django 表单从那里编辑项目。我会看看这个,你会惊讶于你需要编写这么少的代码来获得一个简单的查看/编辑页面。

            【讨论】:

            • 写一个FilterSpec 是不够的。它实际上是控制查询集的视图,它的参数来自request.GETFilterSpecs 所做的只是影响过滤器选项的显示。
            • 另外,重定向到经过过滤的 URL 并不是“非常非常糟糕”。过滤器选项应该在 URL 中明确。这比让一个不可见的会话变量影响查询集而不在 URL 中明显要好。
            【解决方案7】:

            点击2次“返回”?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-01-30
              • 2016-09-21
              • 2012-10-18
              • 2010-10-25
              • 1970-01-01
              • 2012-06-29
              • 1970-01-01
              • 2018-01-15
              相关资源
              最近更新 更多