热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

stark——分页、search、actions

一、分页1、引入自定义分页组件在stark目录下创建utils工具包目录,复制page.py到该目录下,文件中有之前自定义的分页组件。classPagi

一、分页

1、引入自定义分页组件

  在/stark目录下创建utils工具包目录,复制page.py到该目录下,文件中有之前自定义的分页组件。

class Pagination(object):def __init__(self, current_page, all_count, base_url, params, per_page_num&#61;8, pager_count&#61;11, ):"""封装分页相关数据:param current_page: 当前页:param all_count: 数据库中的数据总条数:param per_page_num: 每页显示的数据条数:param base_url: 分页中显示的URL前缀:param pager_count: 最多显示的页码个数"""try:current_page &#61; int(current_page)except Exception as e:current_page &#61; 1if current_page <1:current_page &#61; 1self.current_page &#61; current_pageself.all_count &#61; all_countself.per_page_num &#61; per_page_numself.base_url &#61; base_url# 总页码all_pager, tmp &#61; divmod(all_count, per_page_num)if tmp:all_pager &#43;&#61; 1self.all_pager &#61; all_pagerself.pager_count &#61; pager_count # 最多显示页码数self.pager_count_half &#61; int((pager_count - 1) / 2)import copyparams &#61; copy.deepcopy(params)params._mutable &#61; Trueself.params &#61; params # self.params : {"page":77,"title":"python","nid":1}
&#64;propertydef start(self):return (self.current_page - 1) * self.per_page_num&#64;propertydef end(self):return self.current_page * self.per_page_numdef page_html(self):# 如果总页码 <11个&#xff1a;if self.all_pager <&#61; self.pager_count:pager_start &#61; 1pager_end &#61; self.all_pager &#43; 1# 总页码 > 11else:# 当前页如果<&#61;页面上最多显示(11-1)/2个页码if self.current_page <&#61; self.pager_count_half:pager_start &#61; 1pager_end &#61; self.pager_count &#43; 1# 当前页大于5else:# 页码翻到最后if (self.current_page &#43; self.pager_count_half) > self.all_pager:pager_start &#61; self.all_pager - self.pager_count &#43; 1pager_end &#61; self.all_pager &#43; 1else:pager_start &#61; self.current_page - self.pager_count_halfpager_end &#61; self.current_page &#43; self.pager_count_half &#43; 1page_html_list &#61; []self.params["page"] &#61; 1first_page &#61; &#39;

  • 首页
  • &#39; % (self.base_url, self.params.urlencode(),)page_html_list.append(first_page)if self.current_page <&#61; 1:prev_page &#61; &#39;
  • 上一页
  • &#39;else:self.params["page"] &#61; self.current_page - 1prev_page &#61; &#39;
  • 上一页
  • &#39; % (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"] &#61; i # {"page":72,"title":"python","nid":1}if i &#61;&#61; self.current_page:temp &#61; &#39;
  • %s
  • &#39; % (self.base_url, self.params.urlencode(), i,)else:temp &#61; &#39;
  • %s
  • &#39; % (self.base_url, self.params.urlencode(), i,)page_html_list.append(temp)if self.current_page >&#61; self.all_pager:next_page &#61; &#39;
  • 下一页
  • &#39;else:self.params["page"] &#61; self.current_page &#43; 1next_page &#61; &#39;
  • 下一页
  • &#39; % (self.base_url, self.params.urlencode(),)page_html_list.append(next_page)self.params["page"] &#61; self.all_pagerlast_page &#61; &#39;
  • 尾页
  • &#39; % (self.base_url, self.params.urlencode(),)page_html_list.append(last_page)return &#39;&#39;.join(page_html_list)
    /stark/utils/page.py

    2、整合展示数据showlist类实现代码解耦

      将list_view函数中的构建表头代码挪移到ShowList类的get_header函数下&#xff0c;将将list_view函数中的构建表单代码挪移到ShowList类的get_body函数下。

    /stark/serivce/stark.py:

    class ShowList(object):"""展示页面类"""def __init__(self, config, data_list):self.config &#61; config # 接收传递过来的配置类对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象def get_header(self):"""构建表头"""header_list &#61; []print("header", self.config.new_list_display()) # [checkbox ,"__str__", edit ,deletes]for field in self.config.new_list_display():if callable(field):# 如果是函数val &#61; field(self, header&#61;True)header_list.append(val)else:# 如果是字符串if field &#61;&#61; "__str__":header_list.append(self.config.model._meta.model_name.upper()) # 当前模型表名else:# 如果不是"__str__"# header_list.append(field)val &#61; self.config.model._meta.get_field(field).verbose_nameheader_list.append(val)
    return header_listdef get_body(self):"""构建表单数据"""new_data_list &#61; []for obj in self.data_list:temp &#61; []for field in self.config.new_list_display(): # ["__str__", ] ["pk","name","age",edit]if callable(field):val &#61; field(self.config, obj)else:val &#61; getattr(obj, field)if field in self.config.list_display_links:# _url &#61; reverse("%s_%s_change" % (app_label, model_name), args&#61;(obj.pk,))_url &#61; self.config.get_change_url(obj)val &#61; mark_safe("%s" % (_url, val))temp.append(val)new_data_list.append(temp)
    return new_data_listclass ModelStark(object):"""代码省略"""def list_view(self, request):data_list &#61; self.model.objects.all() # 拿到对应表所有的对象show_list &#61; ShowList(self, data_list) # 传入self&#xff0c;即将当前ModelStark的实例对象传给ShowList
    header_list &#61; show_list.get_header()
    new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()return render(request, "list_view.html", locals())

    &#xff08;1&#xff09;在list_view函数下执行ShowList实例化&#xff0c;在实例化时传入&#xff1a;

      self:即当前ModelStark的实例对象&#xff1b;data_list&#xff1a;对应表所有的对象。

    &#xff08;2&#xff09;在新的类ShowList通过__init__方法来接收者两个参数&#xff1a;

    class ShowList(object):"""展示页面类"""def __init__(self, config, data_list):self.config &#61; config # 接收传递过来的配置类对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象

    &#xff08;3&#xff09;给模板传递正确的数据

      由于模板接收的数据是header_list和new_data_list。需要给get_header和get_body函数添加返回值。

      同时在list_view中构建header_list和new_data_list变量&#xff1a;

    show_list &#61; ShowList(self, data_list) # 传入self&#xff0c;即将当前ModelStark的实例对象传给ShowList
    header_list &#61; show_list.get_header()
    new_data_list &#61; show_list.get_body()

    3、给查看页码添加分页

    &#xff08;1&#xff09;service/stark.py:

    from stark.utils.page import Paginationclass ShowList(object):"""展示页面类"""def __init__(self, config, data_list, request):self.config &#61; config # 接收传递过来的配置类对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象self.request &#61; request# 分页data_count &#61; self.data_list.count()current_page &#61; int(self.request.GET.get("page", 1)) # 默认是第一页base_path &#61; self.request.pathself.pagination &#61; Pagination(current_page, data_count, base_path, self.request.GET, per_page_num&#61;1, pager_count&#61;11,)self.page_data &#61; self.data_list[self.pagination.start:self.pagination.end]"""代码省略"""class ModelStark(object):"""代码省略"""def list_view(self, request):data_list &#61; self.model.objects.all() # 拿到对应表所有的对象show_list &#61; ShowList(self, data_list, request) # 传入self&#xff0c;即将当前ModelStark的实例对象传给ShowListheader_list &#61; show_list.get_header()new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()print("add_url", add_url)return render(request, "list_view.html", locals())

    &#xff08;1&#xff09;list_view函数中创建ShowList示例时多传入了一个request参数。ShowList拿到request后获取GET请求数据和请求路径&#xff1a;

    class ShowList(object):"""展示页面类"""def __init__(self, config, data_list, request):self.config &#61; config # 接收传递过来的配置类对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象self.request &#61; request # # 分页data_count &#61; self.data_list.count()current_page &#61; int(self.request.GET.get("page", 1)) # 默认是第一页base_path &#61; self.request.path # /stark/app01/book/

    &#xff08;2&#xff09;实例化pagination&#xff0c;获取页码数据

      引入自定义分页组件&#xff0c;将参数传入完成pagination实例化。获取当前页码数据&#xff1a;

    class ShowList(object):"""展示页面类"""def __init__(self, config, data_list, request):&#39;&#39;&#39;代码省略&#39;&#39;&#39;self.pagination &#61; Pagination(current_page, data_count, base_path, self.request.GET, per_page_num&#61;1, pager_count&#61;11,)print("data_list", self.data_list) # data_list , , ]>self.page_data &#61; self.data_list[self.pagination.start:self.pagination.end]print("page_data", self.page_data) # page_data ]>&#39;&#39;&#39;代码省略&#39;&#39;&#39;def get_body(self):"""构建表单数据"""new_data_list &#61; []# for obj in self.data_list:for obj in self.page_data: # 当前页面的数据&#39;&#39;&#39;代码省略&#39;&#39;&#39;

    &#xff08;3&#xff09;list_view.html添加分页


    数据列表




    &#xff08;4&#xff09;显示效果如下&#xff1a;

      

    二、search查询

    1、在查看页面添加搜索框

    数据列表


    添加数据

      输入查询内容后&#xff0c;点击搜索按钮&#xff0c;发送的get请求如下所示&#xff1a;

      

    2、查询匹配

    # -*- coding:utf-8 -*-
    __author__ &#61; &#39;Qiushi Huang&#39;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 Paginationclass ShowList(object):"""展示页面类"""def __init__(self, config, data_list, request):self.config &#61; config # 接收传递过来的配置类对象 ModelStark的实例对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象self.request &#61; request # # 分页data_count &#61; self.data_list.count()current_page &#61; int(self.request.GET.get("page", 1)) # 默认是第一页base_path &#61; self.request.path # /stark/app01/book/
    self.pagination &#61; Pagination(current_page, data_count, base_path, self.request.GET, per_page_num&#61;1, pager_count&#61;11,)print("data_list", self.data_list) # data_list , , ]>self.page_data &#61; self.data_list[self.pagination.start:self.pagination.end]print("page_data", self.page_data) # page_data ]>def get_header(self):"""构建表头"""header_list &#61; []print("header", self.config.new_list_display()) # [checkbox ,"__str__", edit ,deletes]for field in self.config.new_list_display():if callable(field):# 如果是函数val &#61; field(self, header&#61;True)header_list.append(val)else:# 如果是字符串if field &#61;&#61; "__str__":header_list.append(self.config.model._meta.model_name.upper()) # 当前模型表名else:# 如果不是"__str__"# header_list.append(field)val &#61; self.config.model._meta.get_field(field).verbose_nameheader_list.append(val)return header_listdef get_body(self):"""构建表单数据"""new_data_list &#61; []# for obj in self.data_list:for obj in self.page_data: # 当前页面的数据temp &#61; []for field in self.config.new_list_display(): # ["__str__", ] ["pk","name","age",edit]if callable(field):val &#61; field(self.config, obj)else:val &#61; getattr(obj, field)if field in self.config.list_display_links:# _url &#61; reverse("%s_%s_change" % (app_label, model_name), args&#61;(obj.pk,))_url &#61; self.config.get_change_url(obj)val &#61; mark_safe("%s" % (_url, val))temp.append(val)new_data_list.append(temp)return new_data_listclass ModelStark(object):"""默认类&#xff0c;定制配置类"""list_display &#61; ["__str__",]list_display_links &#61; []modelform_class &#61; []search_fields &#61; []def __init__(self, model, site):self.model &#61; modelself.site &#61; site# 删除、编辑&#xff0c;复选框def edit(self, obj&#61;None, header&#61;False):"""编辑"""if header:# 如果是表头显示操作return "操作"_url &#61; self.get_change_url(obj)return mark_safe("编辑" % _url)def deletes(self, obj&#61;None, header&#61;False):"""删除"""if header:# 如果是表头显示操作return "操作"_url &#61; self.get_delete_url(obj)# return mark_safe("删除" % obj.pk)return mark_safe("删除" % _url)def checkbox(self, obj&#61;None, header&#61;False):"""复选框"""if header:# 如果是表头显示操作return mark_safe("")return mark_safe("")def get_modelform_class(self):"""用来获取modelform类"""if not self.modelform_class:# 如果没有值from django.forms import ModelFormfrom django.forms import widgets as widclass ModelFormDemo(ModelForm):class Meta:model &#61; self.modelfields &#61; "__all__"return ModelFormDemoelse:# 如果有值说明在用户已经自己定制过了,直接取值return self.modelform_classdef add_view(self, request):ModelFormDemo &#61; self.get_modelform_class()if request.method &#61;&#61; "POST":form &#61; ModelFormDemo(request.POST)if form.is_valid(): # 校验字段全部合格
    form.save()return redirect(self.get_list_url()) # 跳转到当前访问表的查看页面# &#xff08;精髓&#xff09;校验有错误返回页面&#xff0c;且包含了错误信息return render(request, "add_view.html", locals())form &#61; ModelFormDemo() # 实例化return render(request, "add_view.html", locals())def delete_view(self, request, id):url &#61; self.get_list_url()if request.method &#61;&#61; "POST":self.model.objects.filter(pk&#61;id).delete()return redirect(url)# self.model.objects.filter(pk&#61;id).delete()return render(request, "delete_view.html", locals())def change_view(self, request, id):"""编辑视图"""ModelFormDemo &#61; self.get_modelform_class()# 编辑对象edit_obj &#61; self.model.objects.filter(pk&#61;id).first()if request.method &#61;&#61; "POST":form &#61; ModelFormDemo(request.POST, instance&#61;edit_obj) # instance就是给这个记录更改为最新的数据if form.is_valid(): # 校验字段全部合格
    form.save()return redirect(self.get_list_url()) # 跳转到当前访问表的查看页面# &#xff08;精髓&#xff09;校验有错误返回页面&#xff0c;且包含了错误信息return render(request, "add_view.html", locals())form &#61; ModelFormDemo(instance&#61;edit_obj) # 用instance放入编辑对象就有了编辑数据return render(request, "change_view.html", locals())def new_list_display(self):"""返回新的列表"""temp &#61; []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 &#61; self.model._meta.model_nameapp_label &#61; self.model._meta.app_label_url &#61; reverse("%s_%s_change" % (app_label, model_name), args&#61;(obj.pk,))return _urldef get_delete_url(self, obj):model_name &#61; self.model._meta.model_nameapp_label &#61; self.model._meta.app_label_url &#61; reverse("%s_%s_delete" % (app_label, model_name), args&#61;(obj.pk,))return _urldef get_add_url(self):model_name &#61; self.model._meta.model_nameapp_label &#61; self.model._meta.app_label_url &#61; reverse("%s_%s_add" % (app_label, model_name))return _urldef get_list_url(self):model_name &#61; self.model._meta.model_nameapp_label &#61; self.model._meta.app_label_url &#61; reverse("%s_%s_list" % (app_label, model_name))return _urldef get_search_condition(self, request):key_word &#61; request.GET.get("q", "") # 取不到q则直接取空self.key_word &#61; key_wordfrom django.db.models import Qsearch_connection &#61; Q()if key_word: # 判断key_word是否为空search_connection.connector &#61; "or" # 查询条件设置为或for search_field in self.search_fields: # self.search_fields # [&#39;title&#39;, "price"]search_connection.children.append((search_field &#43; "__contains", key_word))return search_connectiondef list_view(self, request):# 获取search的Q对象search_condition &#61; self.get_search_condition(request)# 筛选当前表获取的数据data_list &#61; self.model.objects.all().filter(search_condition)# 获取showlist展示页面show_list &#61; ShowList(self, data_list, request)header_list &#61; show_list.get_header()new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()print("add_url", add_url)return render(request, "list_view.html", locals())def get_urls_2(self):temp &#61; []# 用name取别名app名&#43;model名&#43;操作名可以保证别名不会重复model_name &#61; self.model._meta.model_nameapp_label &#61; self.model._meta.app_labeltemp.append(url(r"^add/", self.add_view, name&#61;"%s_%s_add" % (app_label, model_name)))temp.append(url(r"^(\d&#43;)/delete/", self.delete_view, name&#61;"%s_%s_delete" % (app_label, model_name)))temp.append(url(r"^(\d&#43;)/change/", self.change_view, name&#61;"%s_%s_change" % (app_label, model_name)))temp.append(url(r"^$", self.list_view, name&#61;"%s_%s_list" % (app_label, model_name)))return temp&#64;propertydef urls_2(self):return self.get_urls_2(), None, None # [], None, Noneclass StarkSite(object):"""site单例类"""def __init__(self):self._registry &#61; {}def register(self, model, stark_class&#61;None, **options):"""注册"""if not stark_class:# 如果注册的时候没有自定义配置类,执行stark_class &#61; ModelStark # 配置类# 将配置类对象加到_registry字典中&#xff0c;键为模型类self._registry[model] &#61; stark_class(model, self) # _registry&#61;{&#39;model&#39;:admin_class(model)}def get_urls(self):"""构造一层url"""temp &#61; []for model, stark_class_obj in self._registry.items():# model:一个模型表# stark_class_obj:当前模型表相应的配置类对象
    model_name &#61; model._meta.model_nameapp_label &#61; model._meta.app_label# 分发增删改查temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))"""path(&#39;app01/userinfo/&#39;,UserConfig(Userinfo,site).urls2),path(&#39;app01/book/&#39;,ModelStark(Book,site).urls2),"""return temp&#64;propertydef urls(self):return self.get_urls(), None, Nonesite &#61; StarkSite() # 单例对象

    stark/service/stark.py

    &#xff08;1&#xff09;Q查询

      filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果需要执行更复杂的查询&#xff08;例如OR 语句&#xff09;可以使用Q对象可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时&#xff0c;Q 对象可以使用~ 操作符取反&#xff0c;这允许组合正常的查询和取反(NOT) 查询。

      在这里由于需要循环self.search_fields&#xff0c;且拿到的都是一个个字符串。所以需要使用Q对象实例化的用法&#xff1a;

    from .models import *def test(request):from django.db.models import Q# Q查询普通写法&#xff1a;ret &#61; Book.objects.all().filter(Q(title&#61;"go")|Q(price&#61;103))print("ret", ret) # ret ]># Q查询特殊用法&#xff1a;q &#61; Q()q.connectiion &#61; "or"q.children.append(("title", "go"))q.children.append(("price", 103))print("q", q) # q (AND: (&#39;title&#39;, &#39;yuan&#39;), (&#39;price&#39;, 123))return HttpResponse(ret, q)

      Q查询特殊用法应用&#xff1a;

    class ModelStark(object):def list_view(self, request):key_word &#61; request.GET.get("q")from django.db.models import Qsearch_connection &#61; Q()search_connection.connector &#61; "or" # 查询条件设置为或for search_field in self.search_fields: # self.search_fields # [&#39;title&#39;, "price"]search_connection.children.append((search_field, key_word))data_list &#61; self.model.objects.all().filter(search_connection)# 获取showlist展示页面show_list &#61; ShowList(self, data_list, request)header_list &#61; show_list.get_header()new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()print("add_url", add_url)return render(request, "list_view.html", locals())

    &#xff08;2&#xff09;基于双下划线的模糊查询

    # __startwith: 以...开头
    ret &#61; Book.objects.filter(title__startswith&#61;"py")
    print(ret) # ]># __contains:带有...字符
    ret &#61; Book.objects.filter(title__contains&#61;"h")
    print(ret) # , ]>

      模糊查询应用&#xff1a;search_field&#43;"__contains"

    class ModelStark(object):def list_view(self, request):key_word &#61; request.GET.get("q")from django.db.models import Qsearch_connection &#61; Q()if key_word: # 判断key_word是否为空search_connection.connector &#61; "or" # 查询条件设置为或for search_field in self.search_fields: # self.search_fields # [&#39;title&#39;, "price"]search_connection.children.append((search_field &#43; "__contains", key_word))# 获取当前表所有数据data_list &#61; self.model.objects.all().filter(search_connection)

      查询效果&#xff1a;

      

    &#xff08;3&#xff09;在实例方法中封装模糊查询

    class ModelStark(object):def get_search_condition(self, request):key_word &#61; request.GET.get("q")from django.db.models import Qsearch_connection &#61; Q()if key_word: # 判断key_word是否为空search_connection.connector &#61; "or" # 查询条件设置为或for search_field in self.search_fields: # self.search_fields # [&#39;title&#39;, "price"]search_connection.children.append((search_field &#43; "__contains", key_word))return search_connectiondef list_view(self, request):# 获取search的Q对象search_condition &#61; self.get_search_condition(request)# 筛选当前表获取的数据data_list &#61; self.model.objects.all().filter(search_condition)# 获取showlist展示页面show_list &#61; ShowList(self, data_list, request)header_list &#61; show_list.get_header()new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()print("add_url", add_url)return render(request, "list_view.html", locals())

    &#xff08;4&#xff09;查询提交后&#xff0c;查询框依旧显示搜索的字段

      提交查询后相当于获取了一个新的页面&#xff0c;要显示搜索的字段&#xff0c;必须获取该字段并传到新页面中。



       这里需要注意show_list这个变量&#xff0c;在ModelStark类中list_view实例方法中&#xff0c;实例化ShowList类时&#xff0c;传递了self&#xff0c;这个self是ModelStark的实例对象&#xff0c;而这个实例对象由ShowList用self.config接收。因此show_list是ShowList的实例对象&#xff0c;具备config属性&#xff0c;show_list.config就是ModelStark的实例对象&#xff0c;具备key_word实例属性。

      显示效果&#xff1a;

      

      如果没有输入任何内容直接搜索&#xff0c;搜索框会显示一个None&#xff0c;如果要只显示为空&#xff0c;需要在request.GET.get("q")做如下调整&#xff1a;

    class ModelStark(object):def get_search_condition(self, request):key_word &#61; request.GET.get("q", "") # 取不到q则直接取空self.key_word &#61; key_wordfrom django.db.models import Qsearch_connection &#61; Q()if key_word: # 判断key_word是否为空search_connection.connector &#61; "or" # 查询条件设置为或for search_field in self.search_fields: # self.search_fields # [&#39;title&#39;, "price"]search_connection.children.append((search_field &#43; "__contains", key_word))return search_connection

    3、自定义配置类中配置search_fields则显示搜索框&#xff0c;否则不显示

      在list_view.html中先通过if判断show_list.config.search_fields是否有值&#xff0c;有值则显示搜索框&#xff0c;否则不显示。

    数据列表


    {# 添加数据 #}添加数据{% if show_list.config.search_fields %}{% endif %}


      在自定义配置类注释掉search_fields字段。

    app01/stark.py&#xff1a;

    class BookConfig(ModelStark):list_display &#61; ["title", "price", "publishDate"]modelform_class &#61; BookModelForm# search_fields &#61; [&#39;title&#39;, "price"]site.register(Book, BookConfig)

      页面显示&#xff1a;

      

    三、actions——批量处理

    1、admin组件实现actions批量处理

    app01/admin.py:

    from django.contrib import admin
    from .models import Bookclass BookConfig(admin.ModelAdmin):list_display &#61; ["title", "price"]def patch_init(self, request, queryset):print("queryset", queryset)# queryset , ]>queryset.update(price&#61;100)patch_init.short_description &#61; "批量初始化"actions &#61; [patch_init]admin.site.register(Book, BookConfig)

      注意在这里可以通过patch_init.short_description设置批量操作中文名称。

    批量处理前&#xff1a;

      

    批量处理后&#xff1a;

      

    2、在list_view.html中添加action选择框&#xff0c;重构form表单

    {# 添加数据 #}添加数据{% if show_list.config.search_fields %}{% endif %}


      注意页面中有两个表单&#xff0c;一个是搜索框的表单&#xff0c;另一个则是包含了aciton、表格、分页。

      页面显示效果如下所示&#xff1a;

      

    3、自定义配置actions

    &#xff08;1&#xff09;构建自定义配置类actions的函数

     app01/stark.py:

    class BookConfig(ModelStark):list_display &#61; ["title", "price", "publishDate"]modelform_class &#61; BookModelFormsearch_fields &#61; [&#39;title&#39;, "price"]def patch_init(self, request, queryset):print(queryset)patch_init.short_description &#61; "批量初始化"actions &#61; [patch_init]site.register(Book, BookConfig)

    &#xff08;2&#xff09;处理actions批量操作函数

    /stark/service/stark.py:

    class ShowList(object):"""展示页面类"""def __init__(self, config, data_list, request):self.config &#61; config # 接收传递过来的配置类对象 ModelStark的实例对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象self.request &#61; request # # 分页data_count &#61; self.data_list.count()current_page &#61; int(self.request.GET.get("page", 1)) # 默认是第一页base_path &#61; self.request.path # /stark/app01/book/self.pagination &#61; Pagination(current_page, data_count, base_path, self.request.GET, per_page_num&#61;3, pager_count&#61;11,)self.page_data &#61; self.data_list[self.pagination.start:self.pagination.end]# actionsself.actions &#61; self.config.actions # 拿到配置好的函数对象列表 [patch_init,]def get_action_list(self):temp &#61; []for action in self.actions:temp.append({"name": action.__name__, # 函数.__name__&#xff1a;拿到函数名"desc": action.short_description}) # [{"name": "patch_init", "desc": "批量处理"}]return temp"""代码省略"""class ModelStark(object):"""默认类&#xff0c;定制配置类"""list_display &#61; ["__str__",]list_display_links &#61; []modelform_class &#61; []search_fields &#61; []actions &#61; [] # 调用self.actions拿到的是函数"""代码省略"""

      在ModelStark类中默认actions&#61; []&#xff0c;因此在中实例化ShowList时&#xff0c;通过self将actions传递到ShowList类对象&#xff0c;以self.config.actions拿到配置好的函数对象列表交给get_action_list函数处理。

      在get_action_list中循环处理函数对象列表&#xff0c;通过函数对象.__name__方式拿到函数名&#xff1b;通过函数对象.short_description拿到描述别名。以字典的形式保存在列表中返回给show_list对象交给页面进行渲染。

    &#xff08;3&#xff09;进一步构建批量操作表单

    {% csrf_token %}



      show_list.get_action_list拿到函数的返回值temp&#xff0c;循环拿到的item为一个个字典&#xff0c;键为name的是函数名&#xff0c;键为desc的是描述别名。

    &#xff08;4&#xff09;显示效果

      

    3、实现点选提交

    &#xff08;1&#xff09;重构checkbox标签

      点选批量操作需要拿到当前操作对象的pk值&#xff0c;也需要判断哪些标签被点选提交。

    class ModelStark(object):"""代码省略"""def checkbox(self, obj&#61;None, header&#61;False):"""复选框"""if header:# 如果是表头显示操作return mark_safe("")return mark_safe("" % obj.pk)

     &#xff08;2&#xff09;list_view处理post请求

    class ModelStark(object):def list_view(self, request):if request.method &#61;&#61; "POST": # actionprint("POST:", request.POST)action &#61; request.POST.get("action")selected_pk &#61; request.POST.getlist("selected_pk") # 拿到列表# 反射# self这里是配置类BookConfig&#xff0c;要在类中找到对应的函数action_func &#61; getattr(self, action) # patch_init# 拿到选中状态的pk值对象queryset &#61; self.model.objects.filter(pk__in&#61;selected_pk) # ]>action_func(request, queryset)# 获取search的Q对象search_condition &#61; self.get_search_condition(request)# 筛选当前表获取的数据data_list &#61; self.model.objects.all().filter(search_condition)# 获取showlist展示页面show_list &#61; ShowList(self, data_list, request)header_list &#61; show_list.get_header()new_data_list &#61; show_list.get_body()# 构建一个查看urladd_url &#61; self.get_add_url()print("add_url", add_url)return render(request, "list_view.html", locals())

      在这里POST请求处理不需要返回值&#xff0c;批量初始化后&#xff0c;数据库已经更改&#xff0c;代码顺着下来紧接着就是查询拿到新的页面。

    &#xff08;3&#xff09;配置校验

    class BookConfig(ModelStark):list_display &#61; ["title", "price", "publishDate"]modelform_class &#61; BookModelFormsearch_fields &#61; [&#39;title&#39;, "price"]def patch_init(self, request, queryset):print(queryset)queryset.update(price&#61;123)patch_init.short_description &#61; "批量初始化"actions &#61; [patch_init]site.register(Book, BookConfig)

    app01/stark.py

      显示效果&#xff1a;

      

    4、添加admin批量操作自带的delete功能

    class ShowList(object):def __init__(self, config, data_list, request):self.config &#61; config # 接收传递过来的配置类对象 ModelStark的实例对象self.data_list &#61; data_list # 接收传递过来的当前表的所有对象self.request &#61; request # # 分页data_count &#61; self.data_list.count()current_page &#61; int(self.request.GET.get("page", 1)) # 默认是第一页base_path &#61; self.request.path # /stark/app01/book/self.pagination &#61; Pagination(current_page, data_count, base_path, self.request.GET, per_page_num&#61;3, pager_count&#61;11,)self.page_data &#61; self.data_list[self.pagination.start:self.pagination.end]# actions# self.actions &#61; self.config.actions # 拿到配置好的函数对象列表 [patch_init,]self.actions &#61; self.config.new_actions() # 拿到方法运行的返回结果def get_action_list(self):"""获取自定义批量操作"""temp &#61; []for action in self.actions:temp.append({"name": action.__name__, # 函数.__name__&#xff1a;拿到函数名"desc": action.short_description}) # [{"name": "patch_init", "desc": "批量处理"}]return tempclass ModelStark(object):"""默认类&#xff0c;定制配置类"""list_display &#61; ["__str__",]list_display_links &#61; []modelform_class &#61; []search_fields &#61; []actions &#61; [] # 调用self.actions拿到的是函数def __init__(self, model, site):self.model &#61; modelself.site &#61; sitedef patch_delete(self, request, queryset):"""默认批量删除操作"""queryset.delete()patch_delete.short_description &#61; "批量删除"def new_actions(self):"""返回所有批量操作"""temp &#61; []# 默认添加批量删除temp.append(ModelStark.patch_delete)# 添加自定义actiontemp.extend(self.actions)return temp

      在new_actions实例方法中&#xff0c;首先可以通过ModelStark.patch_delete固定拿到默认需要添加的批量删除方法。其次ModelStark类中默认actions&#61;[]&#xff0c;因此在自定义配置类有配置actions时&#xff0c;self.actions拿到默认配置类配置的列表&#xff0c;如果没有配置拿到空列表。然后通过extend函数扩展列表返回所有批量操作函数。

      ShowList实例化时&#xff0c;self.actions属性通过self.config.new_actions()拿到new_actions返回结果。然后在模板上就可以通过show_list.config.actions渲染所有的actions操作了。

      显示效果&#xff1a;

    1&#xff09;自定义配置类没有配置actions:

      

    2&#xff09;自定义配置类配置了actions&#xff1a;

     

    转:https://www.cnblogs.com/xiugeng/p/9515102.html



    推荐阅读
    • 向QTextEdit拖放文件的方法及实现步骤
      本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
    • Python瓦片图下载、合并、绘图、标记的代码示例
      本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
    • ASP.NET2.0数据教程之十四:使用FormView的模板
      本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
    • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
    • Day2列表、字典、集合操作详解
      本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
    • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
    • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
    • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
    • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
    • Nginx使用(server参数配置)
      本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
    • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
    • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
    • XML介绍与使用的概述及标签规则
      本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
    • 十大经典排序算法动图演示+Python实现
      本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
    • 超级简单加解密工具的方案和功能
      本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
    author-avatar
    灰色头像6888
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有