在/stark目錄下建立utils工具包目錄,複製page.py到該目錄下,文件中有以前自定義的分頁組件。php
class Pagination(object): def __init__(self, current_page, all_count, base_url, params, per_page_num=8, pager_count=11, ): """ 封裝分頁相關數據 :param current_page: 當前頁 :param all_count: 數據庫中的數據總條數 :param per_page_num: 每頁顯示的數據條數 :param base_url: 分頁中顯示的URL前綴 :param pager_count: 最多顯示的頁碼個數 """ try: current_page = int(current_page) except Exception as e: current_page = 1 if current_page < 1: current_page = 1 self.current_page = current_page self.all_count = all_count self.per_page_num = per_page_num self.base_url = base_url # 總頁碼 all_pager, tmp = divmod(all_count, per_page_num) if tmp: all_pager += 1 self.all_pager = all_pager self.pager_count = pager_count # 最多顯示頁碼數 self.pager_count_half = int((pager_count - 1) / 2) import copy params = copy.deepcopy(params) params._mutable = True self.params = params # self.params : {"page":77,"title":"python","nid":1} @property def start(self): return (self.current_page - 1) * self.per_page_num @property def end(self): return self.current_page * self.per_page_num def page_html(self): # 若是總頁碼 < 11個: if self.all_pager <= self.pager_count: pager_start = 1 pager_end = self.all_pager + 1 # 總頁碼 > 11 else: # 當前頁若是<=頁面上最多顯示(11-1)/2個頁碼 if self.current_page <= self.pager_count_half: pager_start = 1 pager_end = self.pager_count + 1 # 當前頁大於5 else: # 頁碼翻到最後 if (self.current_page + self.pager_count_half) > self.all_pager: pager_start = self.all_pager - self.pager_count + 1 pager_end = self.all_pager + 1 else: pager_start = self.current_page - self.pager_count_half pager_end = self.current_page + self.pager_count_half + 1 page_html_list = [] self.params["page"] = 1 first_page = '<li><a href="%s?%s">首頁</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(first_page) if self.current_page <= 1: prev_page = '<li class="disabled"><a href="#">上一頁</a></li>' else: self.params["page"] = self.current_page - 1 prev_page = '<li><a href="%s?%s">上一頁</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(prev_page) for i in range(pager_start, pager_end): # self.params : {"page":77,"title":"python","nid":1} self.params["page"] = i # {"page":72,"title":"python","nid":1} if i == self.current_page: temp = '<li class="active"><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,) else: temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,) page_html_list.append(temp) if self.current_page >= self.all_pager: next_page = '<li class="disabled"><a href="#">下一頁</a></li>' else: self.params["page"] = self.current_page + 1 next_page = '<li><a href="%s?%s">下一頁</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(next_page) self.params["page"] = self.all_pager last_page = '<li><a href="%s?%s">尾頁</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(last_page) return ''.join(page_html_list)
將list_view函數中的構建表頭代碼挪移到ShowList類的get_header函數下,將將list_view函數中的構建表單代碼挪移到ShowList類的get_body函數下。html
/stark/serivce/stark.py:java
class ShowList(object): """展現頁面類""" def __init__(self, config, data_list): self.config = config # 接收傳遞過來的配置類對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 def get_header(self): """構建表頭""" header_list = [] print("header", self.config.new_list_display()) # [checkbox ,"__str__", edit ,deletes] for field in self.config.new_list_display(): if callable(field): # 若是是函數 val = field(self, header=True) header_list.append(val) else: # 若是是字符串 if field == "__str__": header_list.append(self.config.model._meta.model_name.upper()) # 當前模型表名 else: # 若是不是"__str__" # header_list.append(field) val = self.config.model._meta.get_field(field).verbose_name header_list.append(val)
return header_list def get_body(self): """構建表單數據""" new_data_list = [] for obj in self.data_list: temp = [] for field in self.config.new_list_display(): # ["__str__", ] ["pk","name","age",edit] if callable(field): val = field(self.config, obj) else: val = getattr(obj, field) if field in self.config.list_display_links: # _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) _url = self.config.get_change_url(obj) val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) temp.append(val) new_data_list.append(temp)
return new_data_list class ModelStark(object): """代碼省略""" def list_view(self, request): data_list = self.model.objects.all() # 拿到對應表全部的對象 show_list = ShowList(self, data_list) # 傳入self,即將當前ModelStark的實例對象傳給ShowList
header_list = show_list.get_header()
new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() return render(request, "list_view.html", locals())
(1)在list_view函數下執行ShowList實例化,在實例化時傳入:python
self:即當前ModelStark的實例對象;data_list:對應表全部的對象。數據庫
(2)在新的類ShowList經過__init__方法來接收者兩個參數:django
class ShowList(object): """展現頁面類""" def __init__(self, config, data_list): self.config = config # 接收傳遞過來的配置類對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象
(3)給模板傳遞正確的數據app
因爲模板接收的數據是header_list和new_data_list。須要給get_header和get_body函數添加返回值。ide
同時在list_view中構建header_list和new_data_list變量:函數
show_list = ShowList(self, data_list) # 傳入self,即將當前ModelStark的實例對象傳給ShowList header_list = show_list.get_header() new_data_list = show_list.get_body()
(1)service/stark.py:工具
from stark.utils.page import Pagination class ShowList(object): """展現頁面類""" def __init__(self, config, data_list, request): self.config = config # 接收傳遞過來的配置類對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 self.request = request # 分頁 data_count = self.data_list.count() current_page = int(self.request.GET.get("page", 1)) # 默認是第一頁 base_path = self.request.path self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=1, pager_count=11,) self.page_data = self.data_list[self.pagination.start:self.pagination.end] """代碼省略""" class ModelStark(object): """代碼省略""" def list_view(self, request): data_list = self.model.objects.all() # 拿到對應表全部的對象 show_list = ShowList(self, data_list, request) # 傳入self,即將當前ModelStark的實例對象傳給ShowList header_list = show_list.get_header() new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() print("add_url", add_url) return render(request, "list_view.html", locals())
(1)list_view函數中建立ShowList示例時多傳入了一個request參數。ShowList拿到request後獲取GET請求數據和請求路徑:
class ShowList(object): """展現頁面類""" def __init__(self, config, data_list, request): self.config = config # 接收傳遞過來的配置類對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 self.request = request # <WSGIRequest: GET '/stark/app01/book/?page=2'> # 分頁 data_count = self.data_list.count() current_page = int(self.request.GET.get("page", 1)) # 默認是第一頁 base_path = self.request.path # /stark/app01/book/
(2)實例化pagination,獲取頁碼數據
引入自定義分頁組件,將參數傳入完成pagination實例化。獲取當前頁碼數據:
class ShowList(object): """展現頁面類""" def __init__(self, config, data_list, request): '''代碼省略''' self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=1, pager_count=11,) print("data_list", self.data_list) # data_list <QuerySet [<Book: python葵花寶典>, <Book: go>, <Book: java>]> self.page_data = self.data_list[self.pagination.start:self.pagination.end] print("page_data", self.page_data) # page_data <QuerySet [<Book: python葵花寶典>]> '''代碼省略''' def get_body(self): """構建表單數據""" new_data_list = [] # for obj in self.data_list: for obj in self.page_data: # 當前頁面的數據 '''代碼省略'''
(3)list_view.html添加分頁
<body> <h4>數據列表</h4> <div class="container"> <div class="row"> <div class="col-md-9"....代碼省略..> <nav> <ul class="pagination"> {{ show_list.pagination.page_html|safe }} </ul> </nav> </div> </div>
(4)顯示效果以下:
<h4>數據列表</h4> <div class="container"> <div class="row"> <div class="col-md-9"> <a href="{{ add_url }}" class="btn btn-primary">添加數據</a> <form action="" class="pull-right"> <input type="text" name="q"> <button>搜索</button> </form> <table class="table table-bordered table-striped".....> </div> <nav....> </div> </div>
輸入查詢內容後,點擊搜索按鈕,發送的get請求以下所示:
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' from django.conf.urls import url from django.shortcuts import HttpResponse, render, redirect from django.utils.safestring import mark_safe from django.urls import reverse from stark.utils.page import Pagination class ShowList(object): """展現頁面類""" def __init__(self, config, data_list, request): self.config = config # 接收傳遞過來的配置類對象 ModelStark的實例對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 self.request = request # <WSGIRequest: GET '/stark/app01/book/?page=2'> # 分頁 data_count = self.data_list.count() current_page = int(self.request.GET.get("page", 1)) # 默認是第一頁 base_path = self.request.path # /stark/app01/book/ self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=1, pager_count=11,) print("data_list", self.data_list) # data_list <QuerySet [<Book: python葵花寶典>, <Book: go>, <Book: java>]> self.page_data = self.data_list[self.pagination.start:self.pagination.end] print("page_data", self.page_data) # page_data <QuerySet [<Book: python葵花寶典>]> def get_header(self): """構建表頭""" header_list = [] print("header", self.config.new_list_display()) # [checkbox ,"__str__", edit ,deletes] for field in self.config.new_list_display(): if callable(field): # 若是是函數 val = field(self, header=True) header_list.append(val) else: # 若是是字符串 if field == "__str__": header_list.append(self.config.model._meta.model_name.upper()) # 當前模型表名 else: # 若是不是"__str__" # header_list.append(field) val = self.config.model._meta.get_field(field).verbose_name header_list.append(val) return header_list def get_body(self): """構建表單數據""" new_data_list = [] # for obj in self.data_list: for obj in self.page_data: # 當前頁面的數據 temp = [] for field in self.config.new_list_display(): # ["__str__", ] ["pk","name","age",edit] if callable(field): val = field(self.config, obj) else: val = getattr(obj, field) if field in self.config.list_display_links: # _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) _url = self.config.get_change_url(obj) val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) temp.append(val) new_data_list.append(temp) return new_data_list class ModelStark(object): """默認類,定製配置類""" list_display = ["__str__",] list_display_links = [] modelform_class = [] search_fields = [] def __init__(self, model, site): self.model = model self.site = site # 刪除、編輯,複選框 def edit(self, obj=None, header=False): """編輯""" if header: # 若是是表頭顯示操做 return "操做" _url = self.get_change_url(obj) return mark_safe("<a href='%s'>編輯</a>" % _url) def deletes(self, obj=None, header=False): """刪除""" if header: # 若是是表頭顯示操做 return "操做" _url = self.get_delete_url(obj) # return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk) return mark_safe("<a href='%s/'>刪除</a>" % _url) def checkbox(self, obj=None, header=False): """複選框""" if header: # 若是是表頭顯示操做 return mark_safe("<input id='choice' type='checkbox'>") return mark_safe("<input class='choice_item' type='checkbox'>") def get_modelform_class(self): """用來獲取modelform類""" if not self.modelform_class: # 若是沒有值 from django.forms import ModelForm from django.forms import widgets as wid class ModelFormDemo(ModelForm): class Meta: model = self.model fields = "__all__" return ModelFormDemo else: # 若是有值說明在用戶已經本身定製過了,直接取值 return self.modelform_class def add_view(self, request): ModelFormDemo = self.get_modelform_class() if request.method == "POST": form = ModelFormDemo(request.POST) if form.is_valid(): # 校驗字段所有合格 form.save() return redirect(self.get_list_url()) # 跳轉到當前訪問表的查看頁面 # (精髓)校驗有錯誤返回頁面,且包含了錯誤信息 return render(request, "add_view.html", locals()) form = ModelFormDemo() # 實例化 return render(request, "add_view.html", locals()) def delete_view(self, request, id): url = self.get_list_url() if request.method == "POST": self.model.objects.filter(pk=id).delete() return redirect(url) # self.model.objects.filter(pk=id).delete() return render(request, "delete_view.html", locals()) def change_view(self, request, id): """編輯視圖""" ModelFormDemo = self.get_modelform_class() # 編輯對象 edit_obj = self.model.objects.filter(pk=id).first() if request.method == "POST": form = ModelFormDemo(request.POST, instance=edit_obj) # instance就是給這個記錄更改成最新的數據 if form.is_valid(): # 校驗字段所有合格 form.save() return redirect(self.get_list_url()) # 跳轉到當前訪問表的查看頁面 # (精髓)校驗有錯誤返回頁面,且包含了錯誤信息 return render(request, "add_view.html", locals()) form = ModelFormDemo(instance=edit_obj) # 用instance放入編輯對象就有了編輯數據 return render(request, "change_view.html", locals()) def new_list_display(self): """返回新的列表""" temp = [] temp.append(ModelStark.checkbox) # 在列表中放一個checkbox名字 temp.extend(self.list_display) # 擴展進一個列表["pk","name","age"] if not self.list_display_links: # 若是沒有值 temp.append(ModelStark.edit) # temp.append(ModelStark.edit) # edit函數名 temp.append(ModelStark.deletes) # deletes函數名 return temp # 返回新的列表 def get_change_url(self,obj): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) return _url def get_delete_url(self, obj): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,)) return _url def get_add_url(self): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_add" % (app_label, model_name)) return _url def get_list_url(self): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_list" % (app_label, model_name)) return _url def get_search_condition(self, request): key_word = request.GET.get("q", "") # 取不到q則直接取空 self.key_word = key_word from django.db.models import Q search_connection = Q() if key_word: # 判斷key_word是否爲空 search_connection.connector = "or" # 查詢條件設置爲或 for search_field in self.search_fields: # self.search_fields # ['title', "price"] search_connection.children.append((search_field + "__contains", key_word)) return search_connection def list_view(self, request): # 獲取search的Q對象 search_condition = self.get_search_condition(request) # 篩選當前表獲取的數據 data_list = self.model.objects.all().filter(search_condition) # 獲取showlist展現頁面 show_list = ShowList(self, data_list, request) header_list = show_list.get_header() new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() print("add_url", add_url) return render(request, "list_view.html", locals()) def get_urls_2(self): temp = [] # 用name取別名app名+model名+操做名能夠保證別名不會重複 model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name))) temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name))) temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name))) temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name))) return temp @property def urls_2(self): return self.get_urls_2(), None, None # [], None, None class StarkSite(object): """site單例類""" def __init__(self): self._registry = {} def register(self, model, stark_class=None, **options): """註冊""" if not stark_class: # 若是註冊的時候沒有自定義配置類,執行 stark_class = ModelStark # 配置類 # 將配置類對象加到_registry字典中,鍵爲模型類 self._registry[model] = stark_class(model, self) # _registry={'model':admin_class(model)} def get_urls(self): """構造一層url""" temp = [] for model, stark_class_obj in self._registry.items(): # model:一個模型表 # stark_class_obj:當前模型表相應的配置類對象 model_name = model._meta.model_name app_label = model._meta.app_label # 分發增刪改查 temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2)) """ path('app01/userinfo/',UserConfig(Userinfo,site).urls2), path('app01/book/',ModelStark(Book,site).urls2), """ return temp @property def urls(self): return self.get_urls(), None, None site = StarkSite() # 單例對象
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是須要執行更復雜的查詢(例如OR 語句)能夠使用Q對象。能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象能夠使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢。
在這裏因爲須要循環self.search_fields,且拿到的都是一個個字符串。因此須要使用Q對象實例化的用法:
from .models import * def test(request): from django.db.models import Q # Q查詢普通寫法: ret = Book.objects.all().filter(Q(title="go")|Q(price=103)) print("ret", ret) # ret <QuerySet [<Book: go>]> # Q查詢特殊用法: q = Q() q.connectiion = "or" q.children.append(("title", "go")) q.children.append(("price", 103)) print("q", q) # q (AND: ('title', 'yuan'), ('price', 123)) return HttpResponse(ret, q)
Q查詢特殊用法應用:
class ModelStark(object): def list_view(self, request): key_word = request.GET.get("q") from django.db.models import Q search_connection = Q() search_connection.connector = "or" # 查詢條件設置爲或 for search_field in self.search_fields: # self.search_fields # ['title', "price"] search_connection.children.append((search_field, key_word)) data_list = self.model.objects.all().filter(search_connection) # 獲取showlist展現頁面 show_list = ShowList(self, data_list, request) header_list = show_list.get_header() new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() print("add_url", add_url) return render(request, "list_view.html", locals())
# __startwith: 以...開頭 ret = Book.objects.filter(title__startswith="py") print(ret) # <QuerySet [<Book: python紅寶書>]> # __contains:帶有...字符 ret = Book.objects.filter(title__contains="h") print(ret) # <QuerySet [<Book: python紅寶書>, <Book: php寶典>]>
模糊查詢應用:search_field+"__contains"
class ModelStark(object): def list_view(self, request): key_word = request.GET.get("q") from django.db.models import Q search_connection = Q() if key_word: # 判斷key_word是否爲空 search_connection.connector = "or" # 查詢條件設置爲或 for search_field in self.search_fields: # self.search_fields # ['title', "price"] search_connection.children.append((search_field + "__contains", key_word)) # 獲取當前表全部數據 data_list = self.model.objects.all().filter(search_connection)
查詢效果:
class ModelStark(object): def get_search_condition(self, request): key_word = request.GET.get("q") from django.db.models import Q search_connection = Q() if key_word: # 判斷key_word是否爲空 search_connection.connector = "or" # 查詢條件設置爲或 for search_field in self.search_fields: # self.search_fields # ['title', "price"] search_connection.children.append((search_field + "__contains", key_word)) return search_connection def list_view(self, request): # 獲取search的Q對象 search_condition = self.get_search_condition(request) # 篩選當前表獲取的數據 data_list = self.model.objects.all().filter(search_condition) # 獲取showlist展現頁面 show_list = ShowList(self, data_list, request) header_list = show_list.get_header() new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() print("add_url", add_url) return render(request, "list_view.html", locals())
提交查詢後至關於獲取了一個新的頁面,要顯示搜索的字段,必須獲取該字段並傳到新頁面中。
<form action="" class="pull-right"> <input type="text" name="q" value="{{ show_list.config.key_word }}"> <button>搜索</button> </form>
這裏須要注意show_list這個變量,在ModelStark類中list_view實例方法中,實例化ShowList類時,傳遞了self,這個self是ModelStark的實例對象,而這個實例對象由ShowList用self.config接收。所以show_list是ShowList的實例對象,具有config屬性,show_list.config就是ModelStark的實例對象,具有key_word實例屬性。
顯示效果:
若是沒有輸入任何內容直接搜索,搜索框會顯示一個None,若是要只顯示爲空,須要在request.GET.get("q")作以下調整:
class ModelStark(object): def get_search_condition(self, request): key_word = request.GET.get("q", "") # 取不到q則直接取空 self.key_word = key_word from django.db.models import Q search_connection = Q() if key_word: # 判斷key_word是否爲空 search_connection.connector = "or" # 查詢條件設置爲或 for search_field in self.search_fields: # self.search_fields # ['title', "price"] search_connection.children.append((search_field + "__contains", key_word)) return search_connection
在list_view.html中先經過if判斷show_list.config.search_fields是否有值,有值則顯示搜索框,不然不顯示。
<h4>數據列表</h4> <div class="container"> <div class="row"> <div class="col-md-9"> {# <a href="add/" class="btn btn-primary">添加數據</a> #} <a href="{{ add_url }}" class="btn btn-primary">添加數據</a> {% if show_list.config.search_fields %} <form action="" class="pull-right"> <input type="text" name="q" value="{{ show_list.config.key_word }}"> <button>搜索</button> </form> {% endif %} <table class="table table-bordered table-striped"......> </div> <nav> <ul class="pagination"> {{ show_list.pagination.page_html|safe }} </ul> </nav> </div> </div>
在自定義配置類註釋掉search_fields字段。
app01/stark.py:
class BookConfig(ModelStark): list_display = ["title", "price", "publishDate"] modelform_class = BookModelForm # search_fields = ['title', "price"] site.register(Book, BookConfig)
頁面顯示:
app01/admin.py:
from django.contrib import admin from .models import Book class BookConfig(admin.ModelAdmin): list_display = ["title", "price"] def patch_init(self, request, queryset): print("queryset", queryset) # queryset <QuerySet [<Book: java>, <Book: python葵花寶典>]> queryset.update(price=100) patch_init.short_description = "批量初始化" actions = [patch_init] admin.site.register(Book, BookConfig)
注意在這裏能夠經過patch_init.short_description設置批量操做中文名稱。
批量處理前:
批量處理後:
<div class="container"> <div class="row"> <div class="col-md-9"> {# <a href="add/" class="btn btn-primary">添加數據</a> #} <a href="{{ add_url }}" class="btn btn-primary">添加數據</a> {% if show_list.config.search_fields %} <form action="" class="pull-right"> <input type="text" name="q" value="{{ show_list.config.key_word }}"> <button>搜索</button> </form> {% endif %} <form action=""> <select name="action" id="" style="width: 200px; padding: 5px 8px; display: inline-block"> <option value="">xxxxx</option> </select> <button type="submit" class="btn-info">Go</button> <table class="table table-bordered table-striped"......> <nav.....> </form> </div> </div> </div>
注意頁面中有兩個表單,一個是搜索框的表單,另外一個則是包含了aciton、表格、分頁。
頁面顯示效果以下所示:
app01/stark.py:
class BookConfig(ModelStark): list_display = ["title", "price", "publishDate"] modelform_class = BookModelForm search_fields = ['title', "price"] def patch_init(self, request, queryset): print(queryset) patch_init.short_description = "批量初始化" actions = [patch_init] site.register(Book, BookConfig)
/stark/service/stark.py:
class ShowList(object): """展現頁面類""" def __init__(self, config, data_list, request): self.config = config # 接收傳遞過來的配置類對象 ModelStark的實例對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 self.request = request # <WSGIRequest: GET '/stark/app01/book/?page=2'> # 分頁 data_count = self.data_list.count() current_page = int(self.request.GET.get("page", 1)) # 默認是第一頁 base_path = self.request.path # /stark/app01/book/ self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=3, pager_count=11,) self.page_data = self.data_list[self.pagination.start:self.pagination.end] # actions self.actions = self.config.actions # 拿到配置好的函數對象列表 [patch_init,] def get_action_list(self): temp = [] for action in self.actions: temp.append({ "name": action.__name__, # 函數.__name__:拿到函數名 "desc": action.short_description }) # [{"name": "patch_init", "desc": "批量處理"}] return temp """代碼省略""" class ModelStark(object): """默認類,定製配置類""" list_display = ["__str__",] list_display_links = [] modelform_class = [] search_fields = [] actions = [] # 調用self.actions拿到的是函數 """代碼省略"""
在ModelStark類中默認actions= [],所以在中實例化ShowList時,經過self將actions傳遞到ShowList類對象,以self.config.actions拿到配置好的函數對象列表交給get_action_list函數處理。
在get_action_list中循環處理函數對象列表,經過函數對象.__name__方式拿到函數名;經過函數對象.short_description拿到描述別名。以字典的形式保存在列表中返回給show_list對象交給頁面進行渲染。
<form action="" method="post"> {% csrf_token %} <select name="action" id="" style="width: 200px; padding: 5px 8px; display: inline-block"> <option value="">-----------</option> {% for item in show_list.get_action_list %} <option value="{{ item.name }}">{{ item.desc }}</option> {% endfor %} </select> <button type="submit" class="btn-info">Go</button> <table class="table table-bordered table-striped"......> <nav> <ul class="pagination"> {{ show_list.pagination.page_html|safe }} </ul> </nav> </form>
show_list.get_action_list拿到函數的返回值temp,循環拿到的item爲一個個字典,鍵爲name的是函數名,鍵爲desc的是描述別名。
點選批量操做須要拿到當前操做對象的pk值,也須要判斷哪些標籤被點選提交。
class ModelStark(object): """代碼省略""" def checkbox(self, obj=None, header=False): """複選框""" if header: # 若是是表頭顯示操做 return mark_safe("<input id='choice' type='checkbox'>") return mark_safe("<input class='choice_item' type='checkbox' name='selected_pk' value='%s'>" % obj.pk)
class ModelStark(object): def list_view(self, request): if request.method == "POST": # action print("POST:", request.POST) action = request.POST.get("action") selected_pk = request.POST.getlist("selected_pk") # 拿到列表 # 反射 # self這裏是配置類BookConfig,要在類中找到對應的函數 action_func = getattr(self, action) # patch_init # 拿到選中狀態的pk值對象 queryset = self.model.objects.filter(pk__in=selected_pk) # <QuerySet [<Book: go>]> action_func(request, queryset) # 獲取search的Q對象 search_condition = self.get_search_condition(request) # 篩選當前表獲取的數據 data_list = self.model.objects.all().filter(search_condition) # 獲取showlist展現頁面 show_list = ShowList(self, data_list, request) header_list = show_list.get_header() new_data_list = show_list.get_body() # 構建一個查看url add_url = self.get_add_url() print("add_url", add_url) return render(request, "list_view.html", locals())
在這裏POST請求處理不須要返回值,批量初始化後,數據庫已經更改,代碼順着下來緊接着就是查詢拿到新的頁面。
class BookConfig(ModelStark): list_display = ["title", "price", "publishDate"] modelform_class = BookModelForm search_fields = ['title', "price"] def patch_init(self, request, queryset): print(queryset) queryset.update(price=123) patch_init.short_description = "批量初始化" actions = [patch_init] site.register(Book, BookConfig)
顯示效果:
class ShowList(object): def __init__(self, config, data_list, request): self.config = config # 接收傳遞過來的配置類對象 ModelStark的實例對象 self.data_list = data_list # 接收傳遞過來的當前表的全部對象 self.request = request # <WSGIRequest: GET '/stark/app01/book/?page=2'> # 分頁 data_count = self.data_list.count() current_page = int(self.request.GET.get("page", 1)) # 默認是第一頁 base_path = self.request.path # /stark/app01/book/ self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=3, pager_count=11,) self.page_data = self.data_list[self.pagination.start:self.pagination.end] # actions # self.actions = self.config.actions # 拿到配置好的函數對象列表 [patch_init,] self.actions = self.config.new_actions() # 拿到方法運行的返回結果 def get_action_list(self): """獲取自定義批量操做""" temp = [] for action in self.actions: temp.append({ "name": action.__name__, # 函數.__name__:拿到函數名 "desc": action.short_description }) # [{"name": "patch_init", "desc": "批量處理"}] return temp class ModelStark(object): """默認類,定製配置類""" list_display = ["__str__",] list_display_links = [] modelform_class = [] search_fields = [] actions = [] # 調用self.actions拿到的是函數 def __init__(self, model, site): self.model = model self.site = site def patch_delete(self, request, queryset): """默認批量刪除操做""" queryset.delete() patch_delete.short_description = "批量刪除" def new_actions(self): """返回全部批量操做""" temp = [] # 默認添加批量刪除 temp.append(ModelStark.patch_delete) # 添加自定義action temp.extend(self.actions) return temp
在new_actions實例方法中,首先能夠經過ModelStark.patch_delete固定拿到默認須要添加的批量刪除方法。其次ModelStark類中默認actions=[],所以在自定義配置類有配置actions時,self.actions拿到默認配置類配置的列表,若是沒有配置拿到空列表。而後經過extend函數擴展列表返回全部批量操做函數。
ShowList實例化時,self.actions屬性經過self.config.new_actions()拿到new_actions返回結果。而後在模板上就能夠經過show_list.config.actions渲染全部的actions操做了。
顯示效果:
1)自定義配置類沒有配置actions:
2)自定義配置類配置了actions: