Django管理员自定义更改列表参数:覆盖/?e = 1

Joe*_*e J 18 django arguments admin filter querystringparameter

我正在尝试将自定义参数传递给Django Admin更改列表视图,以便我可以以专门的方式过滤列表.我想基于名为'active_pp'的GET参数在2个字段start_date和end_date上过滤查询集.我已经使过滤正常工作,但我无法传入GET查询参数,该参数指定是否应显示过滤结果或正常结果.

我知道,由于安全性,Django Admin会过滤掉任何与指定模型字段无关的传递给它的查询参数.在找到错误的参数后,管理员将用户重定向到当前视图,但用e = 1替换GET查询参数.我想将我的自定义'active_pp'参数列入白名单,这样页面就不会被重定向,我将能够使用该参数.

以下是带有queryset自定义的admin.py中的ModelAdmin示例.

class FeaduredAdmin(admin.ModelAdmin): 

    ....

    def get_changelist(self, request, **kwargs):
        from django.contrib.admin.views.main import ChangeList

        # Try to get the 'active_pp' query parameter
        active_pp = request.GET.get('active_pp',None)

        # Define a custom ChangeList class with a custom queryset
        class ActiveChangeList(ChangeList):
            def get_query_set(self, *args, **kwargs):
                now = datetime.datetime.now()
                qs = super(ActiveChangeList, self).get_query_set(*args, **kwargs)
                return qs.filter((Q(start_date=None) | Q(start_date__lte=now))
                             & (Q(end_date=None) | Q(end_date__gte=now)))

        # use the custom ChangeList class if the parameter exists
        if active_pp:
             return ActiveChangeList

        return ChangeList
Run Code Online (Sandbox Code Playgroud)

有谁知道如何将传递给change_list的自定义GET查询字符串参数列入白名单?

感谢阅读和考虑,乔

更新:

使用Uvasal提供的链接,我能够正确地将GET参数列入白名单.

class ActiveFilterAminForm(forms.Form):
    active_pp = forms.CharField()

class FeaduredAdmin(admin.ModelAdmin): 

    ....

    # Based on: http://djangosnippets.org/snippets/2322/
    advanced_search_form = ActiveFilterAminForm()

    def get_changelist(self, request, **kwargs):

        from django.contrib.admin.views.main import ChangeList
        active_pp = self.other_search_fields.get('active_pp',None)
        # now we have the active_pp parameter that was passed in and can use it.

        class ActiveChangeList(ChangeList):

            def get_query_set(self, *args, **kwargs):
                now = datetime.datetime.now()
                qs = super(ActiveChangeList, self).get_query_set(*args, **kwargs)
                return qs.filter((Q(start_date=None) | Q(start_date__lte=now))
                                 & (Q(end_date=None) | Q(end_date__gte=now)))

        if not active_pp is None:
            return ActiveChangeList

        return ChangeList


    def lookup_allowed(self, lookup):
        if lookup in self.advanced_search_form.fields.keys():
            return True
        return super(MyModelAdmin, self).lookup_allowed(lookup)


    def changelist_view(self, request, extra_context=None, **kwargs):
        self.other_search_fields = {} 
        asf = self.advanced_search_form
        extra_context = {'asf':asf}

        request.GET._mutable=True

        for key in asf.fields.keys():
            try:
                temp = request.GET.pop(key)
            except KeyError:
                pass 
            else:
                if temp!=['']: 
                    self.other_search_fields[key] = temp 

        request.GET_mutable=False
        return super(FeaduredProductAdmin, self)\
               .changelist_view(request, extra_context=extra_context)
Run Code Online (Sandbox Code Playgroud)

mee*_*son 8

我知道这是一篇旧帖子,但刚刚遇到了这个需要,并发现了一个非常简短的解决方案,我想我会分享。这里的关键是创建一个不影响查询集并接受查找中传递给它的任何内容作为有效选项的过滤器。像下面这样:

from django.contrib.admin import SimpleListFilter    

class PassThroughFilter(SimpleListFilter):
    title = ''
    parameter_name = 'pt'
    template = 'admin/hidden_filter.html'

    def lookups(self, request, model_admin):
        return (request.GET.get(self.parameter_name), ''),

    def queryset(self, request, queryset):
        return queryset
Run Code Online (Sandbox Code Playgroud)

hidden_filter模板是空白的,以防止向过滤器区域添加任何内容,并且该lookups方法将始终返回我为参数输入的任何内容pt作为有效的过滤器条目。这将防止?e=1页面加载时弹出错误。

任何管理员都可以使用该pt参数重复使用它。如果您需要为单个管理员传递多个参数,则只需将其子类化为单独的过滤器并parameter_name用您需要的任何参数覆盖即可。这将具有允许查询字符串中的这些参数的效果,而不影响查询集或显示在过滤器列中,然后您可以将它们用于其他地方需要它们的任何目的。

希望这可以帮助某人。


dan*_*son 7

我认为您只需要将自定义过滤器字段放在search_fields类变量中,如高级搜索 Django Snippet中所述.

您应该能够修改代码段以支持日期范围.


Col*_*son 5

总之,这是上面使用的未记录的黑客:

set request.GET._mutable = True,然后request.GET.pop()关闭您正在使用的自定义 GET 参数。