django admin-過濾器

django框架的admin模塊,通過list_filter提供給用戶自定義分類查詢的接口,并且我們可以在原有類的基礎(chǔ)上擴展出符合自身應(yī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)該是一個列表或元組。

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

Filter 會自動列出所有不同的姓:

1-直接激活.png

當(dāng)然,其指定的字段應(yīng)該是BooleanField、CharField、DateField、DateTimeField、IntegerField、ForeignKey 或ManyToManyField中的一種。并且其屬性可以為對應(yīng)關(guān)聯(lián)的外鍵,通過兩個下劃線指定關(guān)聯(lián)表中對應(yīng)屬性:FK__key

激活帶選項的屬性

很多時候,我們的屬性只有固定的幾種類別,比如性別;一般我們會為該屬性綁定選項,這樣在展示時也更加直觀:

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

這時,我們在激活該屬性的過濾器,顯示的就是選項所對應(yīng)的值,而不是數(shù)據(jù)庫真正存儲的值:

2-激活帶選項的屬性.png

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

繼承自 django.contrib.admin.SimpleListFilter 的類,需要給它提供 titleparameter_name 屬性來重寫 lookupsqueryset 方法,title為頁面上該過濾器的標(biāo)題、parameter為加載頁面時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 會列出 lookups 中定義的選項:

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

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

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

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

自定義輸入框查詢(SingleTextInputFilter)

django自帶的過濾器是不含輸入框的,但是我們可以自己重寫一個帶輸入框的過濾器,并且自己指定樣式:

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

參考文獻

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容