Аргументы списка пользовательских изменений Django Admin: Override /? E =1
Я пытаюсь передать пользовательский аргумент представлению списка изменений администратора Django, чтобы я мог фильтровать список специализированным способом. Я хотел бы отфильтровать набор запросов по 2 полям, start_date и end_date, на основе параметра GET с именем 'active_pp'. Я правильно настроил фильтрацию, но не могу передать параметр запроса GET, который указывает, нужно ли отображать отфильтрованные результаты или обычные результаты.
Я знаю, что из-за безопасности администратор Django отфильтровывает любые передаваемые ему параметры запроса, которые не связаны с указанными полями модели; при обнаружении неверных аргументов администратор перенаправляет пользователя к текущему представлению, но заменяет параметры запроса 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, передаваемые в список изменений?
Спасибо за чтение и за ваше внимание, Джо
ОБНОВИТЬ:
Используя предоставленные 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)
4 ответа
Я думаю, вам просто нужно поместить свои настраиваемые поля фильтра в переменную класса search_fields, как указано в расширенном поиске Django Snippet.
Вы также сможете изменить фрагмент, чтобы он также поддерживал диапазоны дат.
Я знаю, что это старый пост, но просто столкнулся с необходимостью в этом и обнаружил очень короткое и простое решение, которым, как я думал, я поделюсь. Ключевым моментом здесь является создание фильтра, который не влияет на набор запросов и принимает все, что передается ему в поисках, как допустимый параметр. Примерно так:
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
с любыми параметрами, которые вам нужны. Это позволит разрешить эти параметры в строке запроса, не влияя на набор запросов или не отображаясь в столбце фильтра, и вы можете затем использовать их для любых целей, которые вам нужны в другом месте.
Надеюсь, это поможет кому-то в будущем.
Итак, вот недокументированный взлом, использованный выше:
задавать request.GET._mutable = True
, затем request.GET.pop()
от пользовательских аргументов GET, которые вы используете.
Я упростил принятое решение Это не будет работать, так как экземпляр ModelAdmin повторно используется между запросами, а self.active_pp сохраняет предыдущее значение, например
change_view
запрос :
class FeaduredAdmin(admin.ModelAdmin):
...
def get_queryset(self, request):
qs = super().get_queryset(request)
if self.active_pp:
qs = qs.filter(...)
return qs
def changelist_view(self, request, extra_context=None):
if request.GET:
request.GET._mutable=True
try:
self.active_pp = request.GET.pop('pp')[0]
except KeyError:
self.active_pp = None
request.GET_mutable=False
return super().changelist_view(request, extra_context=extra_context)
Это решение намеренно не позволяет участвовать в других фильтрах администратора. Если тебе надо
pp
чтобы быть отмеченным другими фильтрами, используйте решение @meesterguyperson.