Django - Xadmin (三) 分頁、搜索和批量操做

Django - Xadmin (三) 分頁、搜索和批量操做

分頁和 ShowList 類

由於 list_view 視圖函數裏面代碼太多,太亂,因此將其裏面的用於處理表頭、處理表單數據的關鍵代碼提取出來,做爲函數包裝到一個類當中,同時,將分頁功能代碼也封裝到該類中。html

ShowList 類

由於將代碼封裝成了一個類,最早重要的是初始化,這裏的初始化所傳參數以下:前端

def __init__(self, config, data_list, request):python

config: 即每一個表對應的配置類 data_list: 數據列表 request: 就是 Django 的響應對象git

首先,須要引入分頁類。實例化分頁類對象。並將其做爲類的變量以方便調用。github

from Xadmin.utils.page import Paginationdjango

其次,更改代碼,一些關鍵變量此時須要加上 self 或者 self.config 等。後端

class ShowList(object):
    def __init__(self, config, data_list, request):
        self.config = config
        self.data_list = data_list
        self.request = request

        # 擴展分頁類
        current_page = int(self.request.GET.get("page", 1))
        data_count = self.data_list.count()
        base_path = self.request.path
        self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=1, pager_count=3)
        self.data_page = self.data_list[self.pagination.start: self.pagination.end]

    def get_header(self):
        # 處理表頭
        header_list = []

        # 爲list_display的每一個字段都添加相應的表頭
        for field in self.config.new_display_list():

            # 字段爲數據表自帶
            if isinstance(field, str):
                # 默認list_display
                if field == '__str__':
                    val = self.config.model._meta.model_name.upper()
                else:
                    field_obj = self.config.model._meta.get_field(field)
                    val = field_obj.verbose_name
            # 字段爲自添加函數
            else:
                # is_header判斷是否在傳表頭時調用
                val = field(self.config, is_header=True)
            header_list.append(val)

        return header_list

    def get_body(self):
        # 處理表單數據的列表
        new_data_list = []

        for data_obj in self.data_page:
            temp = []
            for field in self.config.new_display_list():
                # 取數據對象相應的字段
                if isinstance(field, str):
                    val = getattr(data_obj, field)
                    # 若是是根據該字段進入編輯頁面
                    if field in self.config.list_display_links:
                        _url = self.config.get_change_url(data_obj)
                        val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
                else:
                    val = field(self.config, data_obj)

                temp.append(val)

            new_data_list.append(temp)

        return new_data_list

視圖函數的改變

視圖函數 list_view 如今只須要構建一個 ShowList 的實例對象傳到前端便可。app

# 構建ShowList列表
showlist = ShowList(self, data_list, request)

前端的改變

以前是直接使用從後端傳來的數據變量,如今從後端傳來的是 ShowList 實例對象,只需將原來的數據變量改爲 showlist 調用相應函數便可。函數

加上了分頁功能:調用 ShowList 類中 pagination 變量中的 page_html 方法。post

<table class="table table-bordered table-striped">
	<thead>
	<tr>
		{% for item in showlist.get_header %}
			<td>{{ item }}</td>
		{% endfor %}

	</tr>
	</thead>
	<tbody>
	{% for new_data in showlist.get_body %}
		<tr>
			{% for data in new_data %}
				<td>{{ data }}</td>
			{% endfor %}

		</tr>
	{% endfor %}

	</tbody>
</table>
<nav>
	<ul class="pagination">
		<li>{{ showlist.pagination.page_html | safe }}</li>
	</ul>
</nav>

搜索

前端的搜索框

由於功能是根據後端 search_fields 列表來判斷是否有搜索功能以及搜索的字段,同時經過從後端的 key_words 來保持搜索框內容:

{% if showlist.config.search_fields %}
	<form action="" class="pull-right">
		<input type="text" name="q" value="{{ showlist.config.key_words }}">
		<button>搜索</button>
	</form>
{% endif %}

後端的處理

在 ModelXadmin 類中增長一個變量 search_fields 來指定能夠搜索的字段。默認爲空,在每一個表各自的配置類中能夠加以指定。

search_fields = []

在 ModelXadmin 類中增長一個函數 get_search_condition 來獲取搜索篩選的條件。

基於 Q 函數,以 或 爲鏈接搜索條件。

def get_search_conditon(self, request):
	key_words = request.GET.get("q", "")
	self.key_words = key_words
	from django.db.models import Q
	search_connection = Q()
	if key_words:
		search_connection.connector = "or"
		for field in self.search_fields:
			search_connection.children.append((field + "__contains", key_words))

	return search_connection

最後在 list_view 中進行實際數據過濾操做。

# 獲取search的Q對象
search_connection = self.get_search_conditon(request)

# 篩選數據
data_list = self.model.objects.filter(search_connection)

批量操做

與 admin 相似,批量操做也是選中多個數據後在下拉框中選中要作的操做。一樣,定義批量操做的代碼須要放在各個表的配置類中。

前端

由於批量操做須要對錶單數據進行處理,因此要將整個表單也放到 form 中。

<form method="post">
	{% csrf_token %}
	<select name="action" id="" style="width: 200px;padding: 5px 8px;display: inline-block">
		<option value="">------</option>
		{% for action in showlist.get_action_list %}
			<option value="{{ action.name }}">{{ action.short_description }}</option>
		{% endfor %}

	</select>
	<button class="btn btn-info">Go</button>
	<table>表</table>
	<nav>分頁</nav>
</form>

表的配置類

定義批量操做函數。

給函數加上 short_description 屬性來描述和在前端顯示。

而後將批量操做函數加到配置類的 actions 列表中。

def patch_init(self, request, queryset):
	queryset.update(price=123)

patch_init.short_description = "批量初始化"

actions = [patch_init]

後端

表的配置類中,只是對批量操做函數的定義,真正運行時實際上是在後端。

從前端中獲取要進行的操做和數據,並運行。重點在 action_func(request, queryset)

def list_view(self, request):

	if request.method == "POST":
		action = request.POST.get("action")
		selected_pk = request.POST.getlist("selected_pk")
		action_func = getattr(self, action)
		queryset = self.model.objects.filter(pk__in=selected_pk)
		action_func(request, queryset)

默認批量處理

前面提到批量操做函數的定義在各個表的配置類中,能夠爲每一個表定義各自的操做。而一些全部表都須要的批量操做,即默認批量操做,如批量刪除,也是能夠實現的。

在 ModelXadmin 類中進行批量操做函數定義並加到 actions 列表中,這樣,就是默認批量操做了。

def patch_delete(self, request, queryset):
	queryset.delete()

patch_delete.short_description = "批量刪除"

def new_actions(self):
	temp = []
	temp.append(ModelXadmin.patch_delete)
	temp.extend(self.actions)

	return temp

1542080421375

完整代碼:GitHub地址

相關文章
相關標籤/搜索