【问题标题】:django admin filters cascadingdjango 管理过滤器级联
【发布时间】:2011-11-09 21:38:21
【问题描述】:

我有一个问题 - 是否可以自定义 Django 管理界面,使其仅显示与当前选择的过滤器匹配的数据子集中出现的过滤器选项?

假设我有一个包含三个对象的数据库:

a.Foo = "One"
a.Bar = "Drink"

b.Foo = "One"
b.Bar = "Shot"

c.Foo = "Two"
c.Bar = "Shot"

还有一个带有“Foo”和“Bar”过滤器的 django 管理界面。我想要以下行为:

  • 如果没有选择过滤器,'Foo' 会列出 "One","Two"; “酒吧”列出“饮料”、“射击”
  • 如果“Foo”过滤器设置为“One”,“Bar”会同时列出“Drink”和“Shot”
  • 如果“Foo”过滤器设置为“Two”,“Bar”仅列出“Shot”
  • 如果“Bar”过滤器设置为“Shot”,“Foo”会同时列出“One”和“Two”
  • 如果“酒吧”过滤器设置为“饮料”,则“Foo”仅列出“一个”

干杯!


更具体地说 - 在阅读了一些文档之后:

from django.contrib.admin import SimpleListFilter

class SomeFilter(SimpleListFilter):
  title = "Foo"
  parameter_name="Some"
  def lookups(self, request, model_admin):
    qs = model_admin.queryset(request)
    print qs.query
    return (('Foo', 'Bar'))
  def queryset(self, request, queryset):
    if (self.value()):
      return queryset.filter(Some=self.value())
    else:
      return queryset

然而,它所做的是获取“查询集”,就像没有其他过滤器一样。我怎样才能通过其他过滤器?


理论上我可以手动解析请求并过滤 - 但肯定需要一种方法来管道所有过滤器。

【问题讨论】:

  • 经过一些研究后添加了更多信息 - 在所有其他过滤器都通过它之后,我无法弄清楚如何获取查询集。

标签: django database django-admin


【解决方案1】:

如果有人需要一个轻量级的解决方案,这个解决方案会执行一个 Country 过滤器,当过滤器中没有选择 Continent 时会隐藏该过滤器,并且只提供所选 Continent 中存在的那些国家/地区:

from django.utils.translation import ugettext_lazy as _
class ContinentCountryListFilter(admin.SimpleListFilter):
    # Human-readable title which will be displayed in the
    # right admin sidebar just above the filter options.
    title = _('country')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'country__iso_code__exact'

    def lookups(self, request, model_admin):
        """
        Returns a list of tuples. The first element in each
        tuple is the coded value for the option that will
        appear in the URL query. The second element is the
        human-readable name for the option that will appear
        in the right sidebar.
        """

        continent = request.GET.get('country__continent__iso_code__exact', '')

        if continent:
            countries = models.Country.objects.filter(continent__iso_code__exact=continent)
        else:
            countries = models.Country.objects.none()

        return countries.values_list('iso_code', 'name')

    def queryset(self, request, queryset):
        """
        Returns the filtered queryset based on the value
        provided in the query string and retrievable via
        `self.value()`.
        """
        continent = request.GET.get('country__continent__iso_code__exact', '')

        # only apply filter if continent is set and country exists in continent
        if continent and models.Country.objects.filter(continent__iso_code__exact=continent, iso_code__exact=self.value()).count():
            return queryset.filter(country__iso_code__exact=self.value())

        return queryset

然后申请:

list_filter = ('country__continent', ContinentCountryListFilter, )

【讨论】:

    【解决方案2】:

    这种动态过滤看起来真的很像 faceting。虽然您可以使用标准查询集实现此结果,但这可能不是最佳的。您可能有更多机会使用 Solr 等专用工具。

    Haystack has also a doc page on faceting.

    【讨论】:

    • haystack 听起来确实是一个开始钻研的好地方。好提示!
    猜你喜欢
    • 2013-07-26
    • 2020-09-15
    • 2013-08-20
    • 2011-02-24
    • 2021-01-01
    • 2011-11-13
    • 2011-03-05
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多