python - urls - 在Django 1.3或更低版本的Django Admin中定製過濾器




django設定 (6)

不幸的是,你不能。 目前非字段項目不能用作list_filter條目。

請注意,即使它是一個字段,您的管理員類也不會工作,因為單個項目元組需要逗號:( ('is_live',)

如何將自定義過濾器添加到django admin(出現在模型儀表板右側的過濾器)? 我知道它很容易包含基於該模型的字段的過濾器,但是像這樣的“計算”字段如何:

class NewsItem(models.Model):
    headline = models.CharField(max_length=4096, blank=False)
    byline_1 = models.CharField(max_length=4096, blank=True)
    dateline = models.DateTimeField(help_text=_("date/time that appears on article"))
    body_copy = models.TextField(blank=False)

    when_to_publish = models.DateTimeField(verbose_name="When to publish",  blank=True, null=True)

    # HOW CAN I HAVE "is_live" as part of the admin filter?  It's a calculated state!!
    def is_live(self):
        if self.when_to_publish is not None:
            if ( self.when_to_publish < datetime.now() ):
                return """ <img alt="True" src="/media/img/admin/icon-yes.gif"/> """
        else:
            return """ <img alt="False" src="/media/img/admin/icon-no.gif"/> """      

    is_live.allow_tags = True
class NewsItemAdmin(admin.ModelAdmin):
    form = NewsItemAdminForm
    list_display = ('headline', 'id', 'is_live')
    list_filter = ('is_live')  #  how can i make this work??

不是一個最佳的方式(CPU方式),但簡單,並會工作,所以我這樣做(為我的小型數據庫)。 我的Django版本是1.6。

在admin.py中:

class IsLiveFilter(admin.SimpleListFilter):
    title = 'Live'
    parameter_name = 'islive'
    def lookups(self, request, model_admin):
        return (
            ('1', 'islive'),
        )
    def queryset(self, request, queryset):
        if self.value():
            array = []
            for element in queryset:
                if element.is_live.__call__() == True:
                    q_array.append(element.id)
            return queryset.filter(pk__in=q_array)

...

class NewsItemAdmin(admin.ModelAdmin):
    form = NewsItemAdminForm
    list_display = ('headline', 'id', 'is_live')
    list_filter = (IsLiveFilter)

這裡的主要思想是通過__call __()函數訪問QuerySet中的自定義字段。


只是一個旁注:你可以更容易地使用Django admin上的deafult ticks:

def is_live(self):
    if self.when_to_publish is not None:
        if ( self.when_to_publish < datetime.now() ):
            return True
    else:
        return False

is_live.boolean = True


用戶向一些國家免費提供貨物。 我想過濾這些國家:

全部 - 所有國家, - 免郵費, 收取郵費。

這個問題的主要答案並不適用於我(Django 1.3)我認為,因為__init__方法中沒有提供field_path參數。 它也分類DateFieldFilterSpecpostage領域是一個FloatField

from django.contrib.admin.filterspecs import FilterSpec

class IsFreePostage(FilterSpec):

    def __init__(self, f, request, params, model, model_admin, field_path=None):
        super(IsFreePostage, self).__init__(f, request, params, model,
            model_admin, field_path)

        self.removes = {
            'Yes': ['postage__gt'],
            'No': ['postage__exact'],
            'All': ['postage__exact', 'postage__gt'] }

        self.links = (
            ('All', {}),
            ('Yes', {'postage__exact': 0}),
            ('No', {'postage__gt': 0}))

        if request.GET.has_key('postage__exact'):
            self.ttl = 'Yes'
        elif request.GET.has_key('postage__gt'):
            self.ttl = 'No'
        else:
            self.ttl = 'All'

    def choices(self, cl):
        for title, param_dict in self.links:
            yield {'selected': title == self.ttl,
                   'query_string': cl.get_query_string(param_dict,
                       self.removes[title]),
                   'display': title}
    def title(self):
        return 'Free Postage'

FilterSpec.filter_specs.insert(0,
    (lambda f: getattr(f, 'free_postage', False), IsFreePostage))

在self.links我們提供字典。 用於為每個可能的過濾器構造HTTP查詢字符串,如?postage__exact=0我認為過濾器是累計的,所以如果之前有'否'的請求,現在我們有'是'的請求,我們必須刪除'否'查詢。 self.removes指定了每個查詢需要刪除的內容。 choices方法構造查詢字符串,說明已選擇哪個過濾器並設置過濾器的顯示名稱。








django-admin