django admin-過濾器

django框架的admin模塊,通過list_filter提供給用戶自定義分類查詢的接口洪鸭,并且我們可以在原有類的基礎(chǔ)上擴(kuò)展出符合自身應(yīng)用場(chǎng)景的過濾器烤黍。

定義模型

以 Student 模型為準(zhǔn),管理類為 StudentAdmin先舷。

class Student(models.Model):
    id = models.AutoField(primary_key=True)
    first_name = models.CharField(
            max_length=20, verbose_name=u'姓')
    last_name = models.CharField(
            max_length=20, verbose_naem=u'名')
    gender = models.IntegerField(
            choices=choices_gender, verbose_name=u'性別')
    age = models.IntegerField(
            blank=True, verbose_name=u'年齡')
    birthday = models.DateTimeField(
            blank=True, verbose_name=u'生日')
@admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
    list_display = ('id', 'first_name', 'last_name', 'gender', 'age', 'birthday')
    list_per_page = 20

mysql創(chuàng)建student表:

CREATE TABLE student(
    id int(10) NOT NULL AUTO_INCREMENT,
    first_name varchar(20) NOT NULL,
    last_name varchar(20) NOT NULL,
    gender int(10) NOT NULL,
    age int(10) NOT NULL,
    birthday datetime,
    PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

直接激活過濾器

過濾器位于Admin頁面的右側(cè)哩盲,通過 list_filter 可以直接激活 Student 中已經(jīng)存在的模型仆抵。注:list_filter 應(yīng)該是一個(gè)列表或元組。

# 直接激活
list_filter = ('first_name',)

Filter 會(huì)自動(dòng)列出所有不同的姓:

1-直接激活.png

當(dāng)然种冬,其指定的字段應(yīng)該是BooleanField镣丑、CharField、DateField娱两、DateTimeField莺匠、IntegerField、ForeignKey 或ManyToManyField中的一種十兢。并且其屬性可以為對(duì)應(yīng)關(guān)聯(lián)的外鍵趣竣,通過兩個(gè)下劃線指定關(guān)聯(lián)表中對(duì)應(yīng)屬性:FK__key

激活帶選項(xiàng)的屬性

很多時(shí)候,我們的屬性只有固定的幾種類別旱物,比如性別遥缕;一般我們會(huì)為該屬性綁定選項(xiàng),這樣在展示時(shí)也更加直觀:

choices_gender = [
    (0, 'male'),
    (1, 'femal'),
]

這時(shí)宵呛,我們?cè)诩せ钤搶傩缘倪^濾器单匣,顯示的就是選項(xiàng)所對(duì)應(yīng)的值,而不是數(shù)據(jù)庫真正存儲(chǔ)的值:

2-激活帶選項(xiàng)的屬性.png

自定義查詢的過濾器(SimpleListFilter)

繼承自 django.contrib.admin.SimpleListFilter 的類宝穗,需要給它提供 titleparameter_name 屬性來重寫 lookupsqueryset 方法户秤,title為頁面上該過濾器的標(biāo)題、parameter為加載頁面時(shí)url中攜帶的參數(shù)名稱:

from django.utils.translation import ugettext_lazy as _

class AgeListFilter(admin.SimpleListFilter):
    title = _(u'年齡段')
    parameter_name = 'ages'

    def lookups(self, request, model_admin):
        return (
            ('0', _(u'未成年')),
            ('1', _(u'成年人')),
            ('2', _(u'老年人')),
        )
    
    def queryset(self, request, queryset):
        if self.value() == '0':
            return queryset.filter(age__lt='18')
        if self.value() == '1':
            return queryset.filter(age__gte='18', age__lte='50')
        if self.value() == '2':
            return queryset.filter(age__gt='50')
# 激活自定義過濾器
list_filter = (AgeListFilter,)

Filter 會(huì)列出 lookups 中定義的選項(xiàng):

3-自定義查詢的過濾器.png

日期的區(qū)間篩選(DateRangeFilter)

默認(rèn)的時(shí)間篩選只能選取某一段時(shí)間至今這樣的區(qū)間逮矛,而daterange_filter插件提供了自定義時(shí)間區(qū)間的篩選鸡号。使用DateRangeFilter 前需要安裝插件包 pip install django-daterange-filter,并在settings.pyINSTALLED_APPS 中添加 daterange_filter须鼎。

list_filter = (('birthday', DateRangeFilter), )
4-時(shí)間區(qū)間的過濾.png

自定義輸入框查詢(SingleTextInputFilter)

django自帶的過濾器是不含輸入框的鲸伴,但是我們可以自己重寫一個(gè)帶輸入框的過濾器府蔗,并且自己指定樣式:

from django.contrib.admin import ListFilter

class SingleTextInputFilter(ListFilter):
    """
    renders filter form with text input and submit button
    """
    parameter_name = None
    template = "textinput_filter.html"

    def __init__(self, request, params, model, model_admin):
        super(SingleTextInputFilter, self).__init__(
            request, params, model, model_admin)
        if self.parameter_name is None:
            raise ImproperlyConfigured(
                "The list filter '%s' does not specify "
                "a 'parameter_name'." % self.__class__.__name__)

        if self.parameter_name in params:
            value = params.pop(self.parameter_name)
            self.used_parameters[self.parameter_name] = value

    def value(self):
        """
        Returns the value (in string format) provided in the request's
        query string for this filter, if any. If the value wasn't provided then
        returns None.
        """
        return self.used_parameters.get(self.parameter_name, None)

    def has_output(self):
        return True

    def expected_parameters(self):
        """
        Returns the list of parameter names that are expected from the
        request's query string and that will be used by this filter.
        """
        return [self.parameter_name]


    def choices(self, cl):
        all_choice = {
            'selected': self.value() is None,
            'query_string': cl.get_query_string({}, [self.parameter_name]),
            'display': _('All'),
        }
        return ({
            'get_query': cl.params,
            'current_value': self.value(),
            'all_choice': all_choice,
            'parameter_name': self.parameter_name
        }, )


class LastNameListFilter(SingleTextInputFilter):
    title = 'Last Name'
    parameter_name = 'last_name'

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(last_name=self.value())

將 textinput_filter.html放在templates文件夾下,并在settings.pyTEMPLATES'DIRS'汞窗,加上templates路徑姓赤。

{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>

{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
    <li>
        <form method="get">
            <input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>

            {#create hidden inputs to preserve values from other filters and search field#}
            {% for k, v in i.get_query.items %}
                {% if not k == i.parameter_name %}
                    <input type="hidden" name="{{ k }}" value="{{ v }}">
                {% endif %}
            {% endfor %}
            <input type="submit" value="{% trans 'apply' %}">
        </form>
    </li>

    {#show "All" link to reset current filter#}
    <li{% if i.all_choice.selected %} class="selected"{% endif %}>
        <a href="{{ i.all_choice.query_string|iriencode }}">
            {{ i.all_choice.display }}
        </a>
    </li>
</ul>
{% endwith %}
5-自定義輸入框查詢.png

參考文獻(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杉辙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捶朵,老刑警劉巖蜘矢,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異综看,居然都是意外死亡品腹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門红碑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舞吭,“玉大人,你說我怎么就攤上這事析珊∠叟福” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵忠寻,是天一觀的道長(zhǎng)惧浴。 經(jīng)常有香客問我,道長(zhǎng)奕剃,這世上最難降的妖魔是什么衷旅? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮纵朋,結(jié)果婚禮上柿顶,老公的妹妹穿的比我還像新娘。我一直安慰自己操软,他們只是感情好嘁锯,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著聂薪,像睡著了一般猪钮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胆建,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天烤低,我揣著相機(jī)與錄音,去河邊找鬼笆载。 笑死扑馁,一個(gè)胖子當(dāng)著我的面吹牛涯呻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腻要,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼复罐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了雄家?” 一聲冷哼從身側(cè)響起效诅,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎趟济,沒想到半個(gè)月后乱投,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顷编,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年戚炫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媳纬。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡双肤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钮惠,到底是詐尸還是另有隱情茅糜,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布素挽,位于F島的核電站限匣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毁菱。R本人自食惡果不足惜米死,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贮庞。 院中可真熱鬧峦筒,春花似錦、人聲如沸窗慎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遮斥。三九已至峦失,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間术吗,已是汗流浹背尉辑。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留较屿,地道東北人隧魄。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓卓练,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親购啄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子襟企,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容