2010-06-18 161 views
19

我知道,我已經成功地做到這一點,但怎麼也想不起,也找不到這方面有任何文檔..Django管理缺省過濾

如何在默認情況下一個對象列表視圖應用過濾器管理員?

我有一個應用程序列表引號和那些引號有狀態(例如:接受,拒絕,擱置..)。

我希望過濾器上的狀態設置=通過重寫你永遠不會能夠在查詢集在默認情況下是「接受」 ..

+1

只是爲了記錄這個問題[在這裏是正確的答案](http://stackoverflow.com/questions/851636/default-filter-in-django-admin/3783930#3783930) – 2011-10-22 15:09:51

+1

可能重複[在Django管理員默認過濾器] (https://stackoverflow.com/questions/851636/default-filter-in- django-admin) – 2017-06-28 07:17:56

回答

6

可以重寫查詢集

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

的另一種方式,用在管理類的查詢集方法不起作用。實際上它會過濾結果,但會導致過濾功能失效。

我已經找到了解決辦法也不是完美的,它使用它時,選擇「全部/過濾器是不可能的。對我來說,這不是戲劇性的,這將是足夠雖好..

2

我想我已經找到了一種不限制用戶的方法,只要看一下引用者就可以確定用戶是否剛剛到達此頁面,如果是這樣,就會根據該過濾器將它們重定向到默認的url。

​​
+0

這是相當硬編碼的黑客,但這個答案的作品。我通過用request.path替換「/ admin/app/model /」,並將它的「?status__exact = 1」替換爲它,然後再發送http響應重定向 – Archie1986 2011-06-16 18:22:55

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)    

然後只是定義您的ModelAdmin一個default_filters:

class YourModelAdmin(DefaultFilterMixIn): 
    .... 
    default_filters = ('snapshot__exact=0',) 
+0

給我(這可能是不同的是因爲我使用的是django-grappelli),只有當它是'snapshot = 0'而不是'snapshot__exact = 0',並且出於某種原因,過濾器不再工作,這是因爲JavaScript是破壞(控制檯說:「未捕獲TypeError:對象[對象對象]沒有方法的'行動'」),這也可能是因爲grappelli。對不起,我們可以開始判罰,哈哈。 – 2012-12-20 22:42:20

+0

用django == 1.3.4和grappelli == 2.3.9對我來說工作得很好。 mixin的主要道具。 – 2013-02-20 22:50:23

+0

感謝此片段,但它不適用於Python 3和Django 1.9.7。只是沉默例外是不是一個好主意,所以我評論這一點。然後我發現self.opts.module_name應該是self.opts.model_name,而「request.GET.has_key(key)'」:已被request.GET中的''鍵替換:「(更新代碼太長在這裏被接受) – 2016-07-01 08:52:42

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

我用支持'all'解決了這個問題。

在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

謝天謝地。我找不到刪除「全部」的方法。其他人都說你只是在「查找」功能中將其留在了外面。實際上,您需要在「選擇」功能中將其保留 – MagicLAMP 2015-11-05 00:23:46

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代碼的更新(請參閱comment),它適用於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獲取默認的行爲