Фильтр Django admin по умолчанию
Я знаю, что мне уже удалось это сделать, но не могу вспомнить, как и я не могу найти документацию об этом.
Как применить фильтр по умолчанию в представлении списка объектов в admin?
У меня есть приложение, список котировок которого и те кавычки имеют статус (например: принято, отклонено, на удержании..).
Я хочу, чтобы фильтр, установленный по статусу = 'принято' по умолчанию, был..
Ответы
Ответ 1
Несколько более многоразовый подход:
class DefaultFilterMixIn(admin.ModelAdmin):
def changelist_view(self, request, *args, **kwargs):
from django.http import HttpResponseRedirect
if self.default_filters:
try:
test = request.META['HTTP_REFERER'].split(request.META['PATH_INFO'])
if test and test[-1] and not test[-1].startswith('?'):
url = reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.module_name))
filters = []
for filter in self.default_filters:
key = filter.split('=')[0]
if not request.GET.has_key(key):
filters.append(filter)
if filters:
return HttpResponseRedirect("%s?%s" % (url, "&".join(filters)))
except: pass
return super(DefaultFilterMixIn, self).changelist_view(request, *args, **kwargs)
И затем просто определите default_filters в ModelAdmin:
class YourModelAdmin(DefaultFilterMixIn):
....
default_filters = ('snapshot__exact=0',)
Ответ 2
Наконец, это то, что я искал:
def changelist_view(self, request, extra_context=None):
if not request.GET.has_key('status__exact'):
q = request.GET.copy()
q['status__exact'] = '1'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(SoumissionAdmin,self).changelist_view(request, extra_context=extra_context)
В противном случае метод queryset в классе admin не работает. Фактически он фильтрует результаты, но оставляет функциональность фильтра сломанной.
Решение, которое я нашел, также не является идеальным, при его использовании невозможно выбрать "All/filter". В моем случае это не драматично, и это будет достаточно хорошо, хотя..
Ответ 3
Вы можете переопределить запрос
class QuoteAdmin(admin.ModelAdmin):
def get_queryset(self, request):
return super(QuoteAdmin,self).get_queryset(request).filter(status="accepted")
Однако, переопределив запрос, вы никогда не сможете просматривать кавычки, которые не имеют статуса "принято".
В качестве альтернативы вы можете ссылаться на следующий URL-адрес, добавляя фильтр к параметрам GET.
/admin/myapp/quote/?status=accepted
Ответ 4
Я решил эту проблему с поддержкой "все".
в models.py:
STATUSES_CHOICE = (
('0', 'Active'),
('1', 'Deactive'),
('2', 'Suspended'),
)
class Client(models.Model):
...
status = models.IntegerField(verbose_name=_('Status'),
default=0,
db_index=True)
в admin.py:
class StatusAdminFilter(SimpleListFilter):
title = _('Status')
parameter_name = 'status'
all_param_value = 'all'
def lookups(self, request, model_admin):
return STATUSES_CHOICE
def queryset(self, request, queryset):
status = self.value()
try:
return (queryset if status == self.all_param_value else
queryset.filter(status=int(status)))
except ValueError:
raise Http404
def choices(self, cl):
yield {'selected': self.value() == self.all_param_value,
'query_string': cl.get_query_string(
{self.parameter_name: self.all_param_value},
[self.parameter_name]),
'display': _('All')}
for lookup, title in self.lookup_choices:
yield {'selected': self.value() == lookup,
'query_string': cl.get_query_string(
{self.parameter_name: lookup}, []),
'display': title}
class ClientAdmin(admin.ModelAdmin):
list_filter = (StatusAdminFilter,)
def changelist_view(self, request, extra_context=None):
if not request.GET.has_key('status'):
q = request.GET.copy()
q['status'] = '0' # default value for status
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(ClientAdmin, self).changelist_view(
request, extra_context=extra_context)
Ответ 5
Короткое и чистое решение. Хорошо работает с опцией "Все" при нажатии на просмотр списка изменений.
def changelist_view(self, request, extra_context=None):
if not request.META['QUERY_STRING'] and \
not request.META.get('HTTP_REFERER', '').startswith(request.build_absolute_uri()):
return HttpResponseRedirect(request.path + "?status__exact=1")
return super(YourModelAdmin,self).changelist_view(request, extra_context=extra_context)
Ответ 6
Я думаю, что нашел способ сделать это, не ограничивая пользователя. Просто посмотрите на референта, чтобы определить, только что пользователь только что прибыл на эту страницу. Если так перенаправить их на URL-адрес по умолчанию, который вы хотите на основе этого фильтра.
def changelist_view(self, request, extra_context=None):
try:
test = request.META['HTTP_REFERER'].split(request.META['PATH_INFO'])
if test and test[-1] and not test[-1].startswith('?') and not request.GET.has_key('status__exact'):
return HttpResponseRedirect("/admin/app/model/?status__exact=1")
except: pass # In case there is no referer
return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
Ответ 7
Это работало для меня и избегало упоминания проблемы "Все" h3.
class MyAdmin(admin.ModelAdmin):
def changelist_view(self, request, extra_context=None):
referer = request.META.get('HTTP_REFERER', '')
showall = request.META['PATH_INFO'] in referer and not request.GET.has_key('timeframe')
if not showall and not request.GET.has_key('param_name_here'):
q = request.GET.copy()
q['param_name_here'] = 'default_value_here'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(SerializableAdmin,self).changelist_view(request, extra_context=extra_context)
Ответ 8
Вот мое обновление для кода glic3rinu (см. комментарий там), который работает на Python 3.4 и Django 1.9.7:
class DefaultFilterMixIn(admin.ModelAdmin):
def changelist_view(self, request, *args, **kwargs):
from django.http import HttpResponseRedirect
if self.default_filters:
#try:
test = request.META['HTTP_REFERER'].split(request.META['PATH_INFO'])
if test and test[-1] and not test[-1].startswith('?'):
url = reverse('admin:{}_{}_changelist'.format(self.opts.app_label, self.opts.model_name))
filters = []
for filter in self.default_filters:
key = filter.split('=')[0]
if not key in request.GET:
filters.append(filter)
if filters:
return HttpResponseRedirect("{}?{}".format(url, "&".join(filters)))
#except: pass
return super(DefaultFilterMixIn, self).changelist_view(request, *args, **kwargs)
Ответ 9
Вот моя попытка установить фильтр по умолчанию в admin (только с Django 1.11):
class ZeroCountListFilter(admin.SimpleListFilter):
title = _('include zero count')
parameter_name = 'count'
def choices(self, changelist):
yield {
'selected': self.value() is None or self.value() == 0,
'query_string': changelist.get_query_string({}, [self.parameter_name]),
'display': _('No'),
}
yield {
'selected': self.value() == '1',
'query_string': changelist.get_query_string({self.parameter_name: '1'}, []),
'display': _("Yes"),
}
def lookups(self, request, model_admin):
return (
('0', _('No')),
('1', _('Yes')),
)
def queryset(self, request, queryset):
if self.value() is None or self.value() == '0':
return queryset.exclude(count=0)
else:
return queryset
Фокус в том, чтобы проверить self.value() is None
, чтобы получить поведение по умолчанию