Аргументы списка пользовательских изменений Django Admin: Override /? E = 1 - PullRequest
17 голосов
/ 13 декабря 2011

Я пытаюсь передать пользовательский аргумент представлению списка изменений администратора Django, чтобы я мог фильтровать список специальным образом. Я хотел бы отфильтровать набор запросов по 2 полям, start_date и end_date, на основе параметра GET с именем 'active_pp'. Я правильно настроил фильтрацию, но не могу передать параметр запроса GET, который указывает, нужно ли отображать отфильтрованные результаты или обычные результаты.

Я знаю, что из-за безопасности Django Admin отфильтровывает любые переданные ему параметры запроса, которые не связаны с указанными полями модели; при обнаружении неверных аргументов администратор перенаправляет пользователя в текущее представление, но заменяет параметры запроса GET на e = 1. Я хотел бы внести в белый список мой пользовательский параметр 'active_pp', чтобы страница не была перенаправлена, и я смог бы использовать этот параметр.

Вот пример ModelAdmin в admin.py с настройкой набора запросов.

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

Кто-нибудь знает, как внести в белый список пользовательские аргументы строки GET, переданные в список изменений?

Спасибо за чтение и за ваше внимание, Джо

UPDATE:

Используя предоставленные 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)

Ответы [ 3 ]

6 голосов
/ 13 декабря 2011

Я думаю, вам просто нужно поместить свои настраиваемые поля фильтра в переменную класса search_fields, как указано в Расширенном поиске Фрагмент Django.

Вы также сможете изменить фрагмент для поддержки диапазонов дат.

4 голосов
/ 22 апреля 2014

Итак, вот недокументированный взлом, использованный выше:

установите request.GET._mutable = True, затем request.GET.pop() отключите пользовательский аргумент (ы) GET, который вы используете.

0 голосов
/ 04 июня 2019

Я знаю, что это старый пост, но просто столкнулся с необходимостью в этом и обнаружил очень короткое и простое решение, которым я поделился. Ключевым моментом здесь является создание фильтра, который не влияет на набор запросов и принимает что-либо, переданное ему в поисках, как допустимый параметр. Примерно так:

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

Шаблон hidden_filter пуст, чтобы предотвратить добавление чего-либо в область фильтра, а метод lookups всегда вернет все, что я ввел для параметра pt, в качестве допустимой записи фильтра. Это предотвратит появление ошибки ?e=1 при загрузке страницы.

Это может быть повторно использовано любым администратором, используя параметр pt. Если вам нужно передать несколько параметров для одного администратора, просто разбейте их на отдельные фильтры и переопределите parameter_name с любыми необходимыми параметрами. Это позволит разрешить эти параметры в строке запроса, не влияя на набор запросов или не появившись в столбце фильтра, и вы сможете использовать их для любых целей, которые вам нужны в других местах.

Надеюсь, это поможет кому-то в будущем.

...