将当前过滤器选择提供给Django中另一个定制的SimpleListFilter [英] Feeding a current filter selection to another custom SimpleListFilter in Django

查看:660
本文介绍了将当前过滤器选择提供给Django中另一个定制的SimpleListFilter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使一个过滤器的提示响应于在另一个过滤器中进行的当前选择。关于如何获取传入AttributeFilter的AttributeCategoryFilter的当前选定值,我很失落。我正在使用Django 1.4-dev。试图弄清楚我是否应该使用RelatedFieldListFilter来达到这个目的。看起来这些功能非常年轻,没有(m)在野外的任何例子浮动。

I am trying to make the prompts of one filter change in response to the current selection made in another filter. I am pretty lost as to how to get the currently selected value of the AttributeCategoryFilter passed into the AttributeFilter. I am using Django 1.4-dev. Trying to figure out if I should be using RelatedFieldListFilter for this purpose. It looks like these features are so young as to not have (m)any examples floating around in the wild yet.

    class AttributeCategoryFilter(SimpleListFilter):
        title = _('Attribute Category')
        parameter_name = 'attribute_category'
        def lookups(self, request, model_admin):
            attributes = Attribute.objects.filter(parent_attribute=None)
            prompts = []
            for attribute in attributes:
                prompts.append((attribute.title, _(str(attribute.title))))
            return prompts
        def queryset(self, request, queryset):
            if self.value():
                return queryset.filter(attribute__category=self.value())
            else:
                return queryset


    class AttributeFilter(SimpleListFilter):
        title = _('Attribute Title')
        parameter_name = 'attribute_title'
        def lookups(self, request, model_admin):
            desired_category =  # Needs to be a reference to the selected value in the AttributeCategoryFilter above
            attributes = Attribute.objects.filter(category=desired_category).exclude(parent_attribute=None)
            prompts = []
            for attribute in attributes:
                prompts.append((attribute.title, _(str(attribute.title))))
            return prompts
        def queryset(self, request, queryset):
            if self.value():
                return queryset.filter(attribute__title=self.value())
            else:
                return queryset


    class ValueAdmin(admin.ModelAdmin):
        list_display = ('package', 'attribute', 'presence', 'text', 'modified', 'created')
        list_filter = ('package', AttributeCategoryFilter, AttributeFilter, 'presence', 
            'attribute__admin_approved', 'attribute__dtype', 'modified')
        search_fields = ('package', 'attribute', 'text')
        list_display_links = ('package', )
        list_editable = ('presence', 'text')
        list_per_page = 20000
    admin.site.register(Value, ValueAdmin)   


推荐答案

这是对我有用的...TypeListFilter仅在使用类别过滤器后才可见,然后显示所有条目subTypeOf所选类别。 特殊情况进一步下降确保当用户选择其他类别时,过滤器消失。
_class参数增加了一些额外的灵活性。我使用与不同但相关的Type类相同的过滤器,只需覆盖此一个参数即可。只需将其替换为您要过滤的admin.Model类。

Here is what worked for me... The "TypeListFilter" is only visible once the "Category" filter is used and then displays all the entries that are a "subTypeOf" the selected category. The "special case" hack further down ensures that the filter disappears when the user selects another Category. The "_class" parameter adds some extra flexibility. I am using the same filter with different but related Type classes and just have to override this one parameter. Just replace it by the admin.Model class that you want to filter.

class TypeListFilter( admin.SimpleListFilter):
    """
    Provide filter for DnaComponentType (the actual "second level" type).

    This filter has one cosmetic problem, which is that it's setting is not
    automatically deleted if the category filter is changed. I tried but the
    request and queryset are all immutable. Instead, the queryset method is 
    checking for any missmatch between category and filter name and filtering
    is ignored if the category name doesn't match the current subType name.
    """
    title = 'Type'
    parameter_name = 'type'

    _class = None

    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.
        """
        if not u'category' in request.GET:
            return ()

        category_name = request.GET[u'category']
        types = self._class.objects.filter(subTypeOf__name=category_name)
        return ( (t.name, t.name) for t in types )

    def queryset(self, request, queryset):
        """
        Returns the filtered queryset based on the value
        provided in the query string and retrievable via
        `self.value()`.
        """
        if not u'category' in request.GET:
            return queryset

        category = request.GET[u'category']
        subtypes = self._class.objects.filter(subTypeOf__name=category)

        r = queryset.filter(componentType__subTypeOf__name=category)

        if not self.value():
            return r

        ## special case: missmatch between subtype and category
        ## which happens after switching the category
        if len(subtypes.filter(name=self.value())) == 0:
            return r

        return r.filter(componentType__name=self.value())

这篇关于将当前过滤器选择提供给Django中另一个定制的SimpleListFilter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆