2010-06-18 5 views
19

Я знаю, что уже удалось сделать это, но не могу вспомнить, как ни я не могу найти никакой документации об этом ..Django администратора по умолчанию фильтр

Как можно применить фильтр по умолчанию на экране списка объектов в админ?

У меня есть приложение, список котировок которого и те кавычки имеют статус (например: принято, отклонено, приостановлено).

Я хочу, чтобы фильтр, установленный на статус = «принято» по умолчанию, который ..

+1

Только для записи этот вопрос [правильно ответил здесь] (http://stackoverflow.com/questions/851636/default-filter-in-django-admin/3783930#3783930) –

+1

Возможный дубликат [Фильтр по умолчанию в Django admin] (https://stackoverflow.com/questions/851636/default-filter-in- django-admin) –

ответ

6

Вы можете переопределить QuerySet

class QuoteAdmin(admin.ModelAdmin): 
    def get_queryset(self, request): 
     return super(QuoteAdmin,self).get_queryset(request).filter(status="accepted") 

Однако переопределением QuerySet вы никогда не будете иметь возможность просмотр цитат, которые не имеют статуса «принято».

В качестве альтернативы вы можете ссылаться на следующий URL-адрес, добавляя фильтр к параметрам GET.

/admin/myapp/quote/?status=accepted 
7

Наконец, это то, что я искал:

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 в классе администратора не работает. Фактически он фильтрует результаты, но оставляет функциональность фильтра нарушенной.

Решение я нашел не является совершенным либо, это не представляется возможным при использовании его для выбора «All/фильтра. В моем случае это не драматично, и это будет достаточно, хотя хорошо ..

2

Я думаю, Я нашел способ сделать это, не ограничивая пользователя. Посмотрите на реферера, чтобы определить, только что пользователь только что пришел на эту страницу. Если это так перенаправить их на требуемый по умолчанию 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) 
+0

Это довольно жесткий код, но этот ответ работает. Я сделал это всего лишь малейшим образом, заменив «/ admin/app/model /» на request.path и связав мне эквивалент «? Status__exact = 1» перед отправкой для меня ответа на перенаправление http – Archie1986

17

Немного более многоразовый подход:

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',) 
+0

(что может быть другой, потому что я использую django-grappelli), это работает, но только тогда, когда это 'snapshot = 0', а не' snapshot__exact = 0', а также, по какой-то причине, фильтры больше не работают, и это связано с тем, что javascript (консоль говорит: «Uncaught TypeError: Object [object Object] не имеет методов« действия »), и снова это может быть из-за grappelli. извините за приговор, lol. –

+0

работал просто отлично для меня с django == 1.3.4 и grappelli == 2.3.9. основные опоры для смеси. –

+0

Спасибо за этот фрагмент, но он не работает с Python 3 и Django 1.9.7. Просто замолчать исключения - не такая хорошая идея, поэтому я прокомментировал это. Затем я обнаружил, что self.opts.module_name должен быть self.opts.model_name, а «request.GET.has_key (key)' »: был заменен на« 'key in request.GET'»: (слишком короткий код принимается здесь) –

1

Это работает для меня, и избегал «Все» проблем упоминаемых 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) 
5

Я решил эту проблему с поддержкой «все».

в 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) 
+0

Благодарим. Я не смог найти способ удалить «Все». Все остальные сказали, что вы просто оставили его в функции «lookups». На самом деле вам нужно было оставить это в функции «выбора» – MagicLAMP

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) 
1

Вот мое обновление для кода 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)    
0

Вот моя попытка иметь фильтр по умолчанию установлен в админ (протестирован только с 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, чтобы получить поведение по умолчанию

Смежные вопросы