django admin應用開發(2) 之 查看、過濾、搜索和排序

django

 

第二節 查看、過濾、搜索和排序

2.1 ModelAdmin能作什麼

ModelAdmin是admin應用中最經常使用的一個類,最終效果都將在這個類中體現出來。總的來講,這個類能夠完成如下功能:html

邏輯實現

單個對象(object)的操做:建立(add)、修改(change)、刪除(delete)python

結果集(queryset)的操做:查看(display)、搜索(search)、過濾(filter)、分頁(paginator)、排序(sort)git

權限控制:增刪改查、自定義權限github

界面佈局

每一個modelAdmin有四個頁面,添加頁面(add)、修改頁面(change)、列表頁面(changelist)、歷史頁面(history),每一個頁面含有本身特定的區域,稱之爲block。使用ModelAdmin自定義各個block的內容和位置。數據庫

2.2 ModelAdmin基本準則

MVT模式

admin應用和普通Django同樣,也有本身的urls模塊、views模塊、template前臺模板,記住它們的規則是很是必要的。urls-views-template對應關係在定義在django.contrib.admin.options.ModelAdmin的get_urls方法中。django

    def get_urls(self):
        from django.conf.urls import patterns, url

        def wrap(view):
            def wrapper(*args, **kwargs):
                return self.admin_site.admin_view(view)(*args, **kwargs)
            return update_wrapper(wrapper, view)

        info = self.model._meta.app_label, self.model._meta.module_name

        urlpatterns = patterns('',
            url(r'^$',
                wrap(self.changelist_view),
                name='%s_%s_changelist' % info),
            url(r'^add/$',
                wrap(self.add_view),
                name='%s_%s_add' % info),
            url(r'^(.+)/history/$',
                wrap(self.history_view),
                name='%s_%s_history' % info),
            url(r'^(.+)/delete/$',
                wrap(self.delete_view),
                name='%s_%s_delete' % info),
            url(r'^(.+)/$',
                wrap(self.change_view),
                name='%s_%s_change' % info),
        )
        return urlpatterns

 

摘自:https://github.com/django/django/blob/master/django/contrib/admin/options.py app

ModelAdmin和Model

使用admin.site.register方法將ModelAdmin和Model關聯起來,每一個model只能擁有一個ModelAdmin與之關聯,關聯以後在ModelAdmin中可使用self.model訪問該model,ModelAmin方法的obj參數也是指的這個model。Model能夠是一個代理模型類,使用方法參見這裏proxy modelide

選項靜態和動態配置

 ModelAdmin對於同一個選項一般有靜態(成員變量形式)和動態(成員方法形式)兩種不一樣的方式,且後者具備更高的優先級。在下面的例子裏remark列不會顯示。函數

#coding=utf8
from django.contrib import admin

class StudentModelAdmin(admin.Model):
    list_display = ['name','sex','remark']

    def get_list_display(self, request):
        return ['name','sex']

 

 動態性體如今能夠根據每次請求的相關信息決定不一樣的內容。具體來講,在每一個選項的方法中都含有一個request參數,是HttpRequest類型的,表明了本次請求對象,你能夠根據request包含一些請求相關信息和數據返回不一樣的內容。經常使用見下表。工具

屬性 類型 描述
path string 路徑,不含主機和端口
method string 請求方法
GET/POST/REQUEST dict 請求數據
user User/AnonymousUser 當前登陸用戶對應的User對象或匿名用戶對象

 

 

2.3 數據查看

列顯示

list_display和get_list_display(self,request)返回是一個tuple或list,若是子類須要進行修改請使用list。每一個元素都是一個字符串,按優先級高低排列以下:

  1. 模型字段:在model定義的XxxField字段

  2. 函數:原型def get_filed_name(obj)

  3. ModelAdmin方法:原型def get_filed_name(self,obj)

  4. model方法:def get_filed_name(self)

最常使用的是1,2,3。第二/三種方法(它們的區別是一個寫在ModelAdmin類外面,一個做爲ModelAdmin成員函數)除了能夠顯示字符串以外,還能夠顯示html文本,好比一個連接、一張圖片等,需設置allow_tags=True。下面是一個完整的例子,顯示當前帳戶的餘額狀態。

from django.contrib import admin

class PayAccount(models.Model):
    customer = models.OneToOneField(Customer, verbose_name=u'客戶')
    balance = models.FloatField(verbose_name=u'餘額(元)', default=0)
    remark = models.CharField(max_length=200, verbose_name='備註', null=True, blank=True)

    def __unicode__(self):
        return self.customer.name

    class Meta:
        verbose_name = u'預繳帳戶'
        verbose_name_plural = u'預繳帳戶'
#admin.py
class PayAccountModelAdmin(CustomizeModelAdmin):
    def get_account_state(self, obj):
        if obj.balance < 0:
            return u'<span style="color:red;font-weight:bold">%s</span>' % (u"已欠費",)
        elif obj.balance <= 50:
            return u'<span style="color:orange;font-weight:bold">%s</span>' % (u"餘額不足",)
        else:
            return u'<span style="color:green;font-weight:bold">%s</span>' % (u"正常",)

    get_account_state.short_description = u'帳戶狀態'
    get_account_state.allow_tags = True
    get_account_state.admin_order_field = 'balance' 
    list_display = ['customer', 'balance', 'get_account_state', 'remark']

 

效果如圖

結果集顯示

def queryset(self,request)(django1.6如下)或def get_queryset(self,request)(django1.6+)

返回一個queryset對象,經常使用的作法是先調用父類的queryset方法獲得默認結果集在進行過濾,固然仍是一次性訪問數據庫的。

2.4 數據過濾

在數據表格的右上角顯示爲一個過濾工具條,如圖。每一個過濾值以一個連接形式展示。

list_filter是描述可過濾的列的集合,返回的是一個tuple或list。其中的每一個元素能夠是如下的類型。

字段名稱:這個字段能夠是BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey 和ManyToManyField,不過若是可能值太多的話,仍是考慮用搜索的方法,否則過濾工具條會拖得很長。

一個繼承自admin.SimpleListFilter的類,它主要有如下幾個重要的屬性和方法:

title:就是過濾條上「以」後面的文字。

def lookups(self,request,modeladmin):返回一個nX2的二維列表,每一個元素表明一個過濾值,前面是查詢變量值,後面是顯示在工具條的文字。

paramter_name:查詢變量名

def queryset(self,request,queryset):返回結果集,在處理GET參數時已經複製給self.value()中了,所以這個函數的實現方式一般是 對self.value()進行判斷,返回相應的結果集,不過注意一點的是self.value()是字符型,若是你的lookup是整數型的須要轉化類型。

下面的這個例子實現了帳戶餘額狀態過濾。

功能需求:狀態分爲三種:當餘額大於50元時,爲正常狀態;當餘額在0-50元(含0和50)時,爲餘額不足狀態;當餘額小於0時,爲已欠費狀態。由於數據存的是餘額這個字段,狀態過濾須要自定過濾器。

class AccountBalanceStateFilter(admin.SimpleListFilter):
    title = (u'餘額狀態')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'balance_state'

    def lookups(self, request, model_admin):
        """
        Returns a list of tuples. The first element in each
        tuple is the coded value for the option that will
        appear in the URL query. The second element is the
        human-readable name for the option that will appear
        in the right sidebar.
        """
        return (
            (0, u'正常'),
            (1, u'餘額不足'),
            (2, u'已欠費'),
        )

    def queryset(self, request, queryset):
        """
        Returns the filtered queryset based on the value
        provided in the query string and retrievable via
        `self.value()`.
        """
        if self.value():
            if int(self.value()) == 0:
                return queryset.filter(balance__gt=50)
            if int(self.value()) == 1:
                return queryset.filter(balance__range=(0, 50))
            if int(self.value()) == 2:
                return queryset.filter(balance__lt=0)

 

效果見上圖。其中「已欠費」的連接GET字符串就含有:?balance_state=2。「所有」過濾值是admin自動添加的,它的鏈接就沒有balance_state這個查詢變量了。

另外,admin對於時間的過濾處理可使用上面的形式即在list_filter添加一個datetime類型的字段,還能夠用date_hierarchy 選項控制,它將在表頭顯示一個「年-月-日」過濾器。

2.5 搜索

 

在ModelAdmin中與搜索有關的屬性和方法是search_fields和get_search_results(request,queryset,search_term) 。

基本搜索

前者和顯示和過濾同樣,也是一個列名組成的list或tuple。每一個列必須是字符串或文本類型的,這個字段能夠屬於本model或者model的外鍵對象的,用'foreign_key__related_fieldname'形式表示。

在搜索類型方面,admin支持精確、模糊以及自定義搜索三種,默認是模糊搜索。還能夠經過前綴符控制匹配的具體條件:^表示以此開始的字符;=表示精確匹配,@表示全文搜索。

具體參見官方Demo:

https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

自定義搜索

get_search_results(request,queryset,search_term)是定義當用戶輸入的文本內容應該返回的結果集。此方法Django1.6+有效。

2.6 排序

排序可分爲database層和django層。它們的區別是:

  • 前者指的是數據庫結果集返回的順序,影響的是查詢SOL的ORDER BY後面的內容,後者指的是傳遞給前臺模板中queryset的順序。

  • 後者優先級大於前者,前者只有當調用ModelAdmin(Django內置,不是本身寫的)queryset方法時候起做用。

  • 前者只支持按數據已存在的列排序(由於要組成SQL),後者是結果集排序,因此支持自定義排序。(參見內置的sort函數)。

在admin中與排序有關有如下幾個地方:

  • Model內部類Meta的ordering成員變量(database層)

  • ModelAdmin中ordering變量 (database層)

  • ModelAdmin中get_ordering(self, request)方法(database層)

  • ModelAdmin中queryset方法 (django層)

以上幾項優先級按從低到高。database的排序配置和過濾、顯示等同樣,支持list或tuple,降序排序時在該列名字之間加「-」前綴。

在changelist頁面來看,每一個可排序的列,一般是數據庫的列的表頭是帶有連接的,點擊後可按此列升降序排序。若是想讓自定義的列也支持排序只要設置admin_order_field便可。好比在上述的例子中,想讓帳戶帳戶狀態按餘額排序,只要添加如下如下代碼便可。

get_account_state.admin_order_field = 'balance'

 

可是這種排序並非實時的,是新的HTTP請求,連接的地址能夠看出是以"o"爲查詢變量的。格式相似於「o=1,-2」,即按list_display中第2列升序、第3列降序排列。

相關文章
相關標籤/搜索