• stark组件的分页,模糊查询,批量删除


    1、分页组件高阶

    1、分页的class形式(有bug,请看下面的)

     
    """
    自定义分页组件
    
    """
    
    
    class Pagination(object):
        # def __init__(self, data_num, current_page, url_prefix, params, per_page=10, max_show=3):
        def __init__(self, data_num, current_page, url_prefix,per_page=10, max_show=3):
            """
            进行初始化.
            :param data_num: 数据总数
            :param current_page: 当前页
            :param url_prefix: 生成的页码的链接前缀
            :param per_page: 每页显示多少条数据
            :param max_show: 页面最多显示多少个页码
            """
            self.data_num = data_num
            self.per_page = per_page
            self.max_show = max_show
            self.url_prefix = url_prefix
    
            # 把页码数算出来
            self.page_num, more = divmod(data_num, per_page)
            if more:
                self.page_num += 1
    
            try:
                self.current_page = int(current_page)
            except Exception as e:
                self.current_page = 1
                # 如果URL传过来的页码数是负数
            if self.current_page <= 0:
                self.current_page = 1
                # 如果URL传过来的页码数超过了最大页码数
            elif self.current_page > self.page_num:
                self.current_page = self.page_num  # 默认展示最后一页
    
            # 页码数的一半 算出来
            self.half_show = max_show // 2
    
            # 页码最左边显示多少
            if self.current_page - self.half_show <= 1:
                self.page_start = 1
                self.page_end = self.max_show
            elif self.current_page + self.half_show >= self.page_num:  # 如果右边越界
                self.page_end = self.page_num
                self.page_start = self.page_num - self.max_show
            else:
                self.page_start = self.current_page - self.half_show
                # 页码最右边显示
                self.page_end = self.current_page + self.half_show
    
            # import copy
            # self.params = copy.deepcopy(params)  # {"page":"12","title_startwith":"py","id__gt":"5"}
    
        @property
        def start(self):
            # 数据从哪儿开始切
            return (self.current_page - 1) * self.per_page
    
        @property
        def end(self):
            # 数据切片切到哪儿
            return self.current_page * self.per_page
    
        def page_html(self):
            # 生成页码
            l = []
            # 加一个首页
            l.append('<li><a href="{}?page=1">首页</a></li>'.format(self.url_prefix))
            # 加一个上一页
            if self.current_page == 1:
                l.append('<li class="disabled" ><a href="#">«</a></li>'.format(self.current_page))
            else:
                l.append('<li><a href="{}?page={}">«</a></li>'.format(self.url_prefix, self.current_page - 1))
    
    
            # {"page":"12","title_startwith":"py","id__gt":"5"}  #  "page=12&title_startwith=py&id__gt=5"
            # print(self.params.urlencode())
            
            for i in range(self.page_start, self.page_end + 1):
                # self.params["page"] = i  # {"page":"7","title_startwith":"py","id__gt":"5"}  #  "page=7&title_startwith=py&id__gt=5"
                if i == self.current_page:
                    tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
                else:
                    # tmp = '<li><a href="{0}?{1}">{2}</a></li>'.format(self.url_prefix, self.params.urlencode(), i)
                    tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
                l.append(tmp)
    
            # 加一个下一页
            if self.current_page == self.page_num:
                l.append('<li class="disabled"><a href="#">»</a></li>'.format(self.current_page))
            else:
                l.append('<li><a href="{}?page={}">»</a></li>'.format(self.url_prefix, self.current_page + 1))
            # 加一个尾页
            l.append('<li><a href="{}?page={}">尾页</a></li>'.format(self.url_prefix, self.page_num))
            return "".join(l)
     
    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    
    
    from .models import *
    def index(request):
        '''
        # 生成假数据
        book_list=[]
        for  i in range(500):
            book_obj=Book(title="book_%s"%i,price=i*i)
            book_list.append(book_obj)
        Book.objects.bulk_create(book_list)
        '''
        base_url = request.path  # /index/            # 当前url路径
        current_page=request.GET.get("page",1)      # 获取当前url中的page
        all_count=Book.objects.all().count()        # 所有book数据多少条
    
        # 分页器
        from app01.utils.page import  Pagination
    
        pagination=Pagination(all_count,int(current_page),base_url,per_page=10, max_show=11)
        # pagination=Pagination(all_count,int(current_page),base_url,request.GET,per_page=10, max_show=11)
                            # 所有数据条数,当前页的page=3,当前url路径,request.GET请求,每页显示数据,分页器最大展示几个项目
    
        print(pagination.start)
        print(pagination.end)
    
        book_list =Book.objects.all()[pagination.start:pagination.end]      # 对数据进行切片
    
        from django.http.request import QueryDict
        # dic = QueryDict(mutable=True)
        # dic["info"] = 123
    
    
        # print(type(request.GET))
        # request.GET["info"]=123
    
    
        import copy
        params=copy.deepcopy(request.GET)
        params["xxx"]=123
    
        return render(request,"index.html",locals())
    Views
    from django.db import models
    
    # Create your models here.
    
    
    
    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.DecimalField(max_digits=8,decimal_places=2)
    
    
        def __str__(self):
            return self.title
    models
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
    
    
    <ul>
        {% for foo in book_list %}
        <li>{{ foo }}</li>
        {% endfor %}
    
    </ul>
    <nav>
    <ul class="pagination">
       {{ pagination.page_html|safe }}
    </ul>
    </nav>
    
    
    
    </body>
    </html>
    index.html

     扩展分页组件:

    
                分页的是一个一个固定URL的a标签。
                class Pagination(object):
                    def __init__():
            在分页内加一个request.GET的参数.
            在视图使用分分页器的时候,加一个request.GET参数
            分页器内加一个形参params 接受request.GET
    
            import copy
            self.params=copy.deepcopy(params)
            应该把传过来的request.GET(是一个键值对),变成urlencode.
            通过{{ }}动态的传入前端a标签的href.
    
            self.params["page"] ==i   把循环的页面赋值给这个request.GET
            首先要做的是把list_view的函数进行一下封装,因为内容太多了。

    2、如何扩展分页

     

     

    2、整合展示数据showlist类

        def list_view(self, request):
            print(self.model)  # <class 'app01.models.Book'>  用户访问的模型表
    
            # 构建表头
            header_list = []  # # header_list = ['选择','pk',...'操作','操作']
            for field in self.new_list_play():
                if callable(field):
                    # header_list.append(field.__name__)
                    val = field(self,header=True)
                    header_list.append(val)
                else:
                    if field == "__str__":
                        header_list.append(self.model._meta.model_name.upper())
                    else:
                        val = self.model._meta.get_field(field).verbose_name    # 中文名称
                        header_list.append(val)
    
            # 构建表单
            data_list = self.model.objects.all()        # [obj1,obj2,...]
            new_data_list = []
            for obj in data_list:                   # Book表模型,Author表模型
                temp = []
                for field in self.new_list_play():     # ['name','age']
                    if callable(field):                 # edit()  可调用的
                        val = field(self,obj)           # 直接调用edit()函数
                        print('val--------->',val)
                    else:
                        val = getattr(obj,field)       # 反射  obj是实例对象,name是方法
    
                        # list_display_links 按钮
                        if field in self.list_display_links:
                            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,))
                            # print(_url)
                            val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            print('new_data_list',new_data_list)        # 构造数据  [['jack', 44], ['mark', 33]]
    
            # 构建一个addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
    list_view函数形式

     

    showlist类

     
        def list_view(self, request):
            # print(self.model)  # <class 'app01.models.Book'>  用户访问的模型表
            data_list = self.model.objects.all()        # [obj1,obj2,...]
    
            # 构建表头,表单
            show_list = ShowList(self,data_list)  # self=ModelSTark实例对象
    
            # 构建一个addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
     
     
    class ShowList(object):
        def __init__(self,config, data_list):
            self.config = config  # MOdelStark实例对象
            self.data_list = data_list      # 数据
    
        def get_header(self):
            # 构建表头
            header_list = []  # # header_list = ['选择','pk',...'操作','操作']
            for field in self.config.new_list_play():
                if callable(field):
                    # header_list.append(field.__name__)
                    val = field(self.config,header=True)
                    header_list.append(val)
                else:
                    if field == "__str__":
                        header_list.append(self.config.model._meta.model_name.upper())
                    else:
                        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:                   # Book表模型,Author表模型
                temp = []
                for field in self.config.new_list_play():     # ['name','age']
                    if callable(field):                 # edit()  可调用的
                        val = field(self.config,obj)           # 直接调用edit()函数
                        print('val--------->',val)
                    else:
                        val = getattr(obj,field)       # 反射  obj是实例对象,name是方法
    
                        # list_display_links 按钮
                        if field in self.config.list_display_links:
                            model_name = self.config.model._meta.model_name
                            app_label = self.config.model._meta.app_label
                            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                            # print(_url)
                            val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            print('new_data_list',new_data_list)        # 构造数据  [['jack', 44], ['mark', 33]]
    
            return new_data_list
     
     

     3、stark组件之分页

     

    stark/service/stark.py

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/17 0017 14:46
    # @Author  : Venicid
    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
    
            # 分页
            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]
    
        def get_header(self):
            # 构建表头
            header_list = []  # # header_list = ['选择','pk',...'操作','操作']
            for field in self.config.new_list_play():
                if callable(field):
                    # header_list.append(field.__name__)
                    val = field(self.config,header=True)
                    header_list.append(val)
                else:
                    if field == "__str__":
                        header_list.append(self.config.model._meta.model_name.upper())
                    else:
                        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.page_data:    #分页后的数据               # Book表模型,Author表模型
                temp = []
                for field in self.config.new_list_play():     # ['name','age']
                    if callable(field):                 # edit()  可调用的
                        val = field(self.config,obj)           # 直接调用edit()函数
                        print('val--------->',val)
                    else:
                        val = getattr(obj,field)       # 反射  obj是实例对象,name是方法
    
                        # list_display_links 按钮
                        if field in self.config.list_display_links:
                            model_name = self.config.model._meta.model_name
                            app_label = self.config.model._meta.app_label
                            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                            # print(_url)
                            val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            print('new_data_list',new_data_list)        # 构造数据  [['jack', 44], ['mark', 33]]
    
            return new_data_list
    
    
    class ModelStark(object):
        list_display = ["__str__"]  # 子类中没有,直接用父类自己的
        list_display_links = []
    
        modelform_class = []
    
        def __init__(self,model, site):
            self.model = model
            self.site = site
    
        # 增删改查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 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 edit(self,obj=None, header=False):
            if header:
                return "操作"
            # 方案1:固定url
            # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
            # 方案2:拼接url
            # return mark_safe("<a href='%s/change'>编辑</a>")
    
            # 方案3:反向解析
            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,))
            # print("_url",_url)
            return mark_safe("<a href='%s'>编辑</a>"%_url)
    
    
        def deletes(self,obj=None, header=False):
            if header:
                return "操作"
            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 mark_safe("<a href='%s'>删除</a>"%_url)
    
    
    
        # ModelForm组件渲染  list、增、删、改页面
        def get_modelform_class(self):
            """ModelForm组件"""
            if not self.modelform_class:
                from django.forms import ModelForm
                class ModelFormDemo(ModelForm):
                    class Meta:
                        model = self.model
                        fields = "__all__"
                return ModelFormDemo
            else:
                return self.modelform_class
    
        def new_list_play(self):
            """构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
            temp = []
            temp.append(ModelStark.checkbox)
            temp.extend(self.list_display)
            if not self.list_display_links:
                temp.append(ModelStark.edit)
            temp.append(ModelStark.deletes)
            return temp
    
        def list_view(self, request):
            # print(self.model)  # <class 'app01.models.Book'>  用户访问的模型表
            data_list = self.model.objects.all()        # [obj1,obj2,...]
    
            # 构建表头,表单
            show_list = ShowList(self,data_list,request)  # self=ModelSTark实例对象
    
            # 构建一个addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
    
    
        def add_view(self, request):
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo()
            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())
    
        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)
            return render(request, "delete_view.html", locals())
    
        def change_view(self, request, id):
            edit_obj = self.model.objects.filter(pk=id).first()
    
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo(instance=edit_obj)
            if request.method == "POST":
                form = ModelFormDemo(request.POST,instance=edit_obj)
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url())
    
            return render(request, "change_view.html",locals())
    
    
        #构造 add/delete/change
        def get_urls2(self):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            temp = []
            temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
            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)))
    
            return temp
    
        @property
        def urls2(self):
    
            return self.get_urls2(), None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self,model, stark_class=None):
            """注册"""
            if not stark_class:
                stark_class = ModelStark
    
            self._registry[model] = stark_class(model,self)
    
        def get_urls(self):
            """构造一层urls app01/book"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                print(model, 'stark_clas_obj', stark_class_obj)  # 不同的model模型表
                """
                 <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
                 <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
                 """
    
                app_label = model._meta.app_label     # app01
                model_name = model._meta.model_name   # book
                # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
                temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
    
            return temp
    
        @property
        def urls(self):
    
            # return [],None,None
            return self.get_urls(),None,None
    
    site = StarkSite()   # 单例对象
    View Code

    stark/utils/page.py(自定义分页,新版本)【旧的有bug】

     
    """
    自定义分页组件
    """
    
    
    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.html

     

    {% extends 'base.html' %}
    
    {% block title %}
        <title>list页面</title>
    {% endblock %}
    
    {% block header %}
        <h3>list页面</h3>
    {% endblock %}
    {% block content %}
        <a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
        <table class="table table-bordered table-striped">
            <tr>
                {% for header in show_list.get_header %}
                    {#            {% for header in header_list %}#}
                    <th>{{ header }}</th>
                {% endfor %}
            </tr>
    
            {% for data in show_list.get_body %}
                {#        {% for data in new_data_list %}#}
                <tr>
                    {% for item in data %}
                        <td>{{ item }}</td>
                    {% endfor %}
    
                </tr>
            {% endfor %}
        </table>
        <nav>
            <ul class="pagination">
                {{ show_list.pagination.page_html|safe }}
            </ul>
        </nav>
    
    {% endblock %}
    
    
    {% block javascript %}
        <script type="text/javascript">
            $('#choice').click(function () {
                if ($(this).prop('checked')) {   //对象自身属性中是否具有指定的属性
                    $('.choice_item').prop("checked", true)
                } else {
                    $('.choice_item').prop("checked", false)
                }
            })
        </script>
    {% endblock %}
    View Code

    全部封装在一个类里:

     class ShowList(object):
                '''
                将展示页面的表头和数据封装到这个类中,分别调用方法返回列表
                '''
                def __init__(self,config,data_list,request):
                    self.config=config   #这个就是那个modelStark的实例对象。拥有modelstark所有属性和方法
                    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=4, pager_count=11,)       #将数据进行分页,调用原有的分页器。
                    self.page_Data=self.data_list[self.pagination.start:self.pagination.end]  #将数据进行一个切片。
    
    
                    #actions
                    self.actions=self.config.actions  #首先拿到自定制的action列表
    
                def get_action_list(self):
                    temp=[]
                    for action in self.actions:
                        temp.append({
                            "name":action.__name__,
                            "desc":action.short_description
                        })
    
                        #上诉方法把action做成这个样子,一个是取到方法名一个是取到中文描述 
                        #[{"name":patch_init,"desc":"批量初始化"}]
                    return temp
    
    
    
                def get_header(self):
                    #构建表头数据
                    header_list=[]
                    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:
                                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.page_Data:   #注意分页后这里应该展示的是分页数据
                        temp = []
                        for field in self.config.new_list_display():
                            if callable(field):
                                val = field(self.config, obj)
                            else:
                                val = getattr(obj, field)
                                if field in self.config.list_display_links:
                                    _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
    View Code

     

    3、stark组件之search模糊查询

    1、orm中的模糊查询

     2、orm中的Q查询 与或非

    3、stark组件之模糊查询

     

     
     def list_view(self, request):
            # print(self.model)  # <class 'app01.models.Book'>  用户访问的模型表
    
            # 模糊查询过滤
            key_word = request.GET.get("q")
            from django.db.models import Q   # 与或非
            search_connection = Q()
            if key_word:
                search_connection.connector = "or"
                for search_field in self.search_fields:
                    search_connection.children.append((search_field+"__contains", key_word))
    
            data_list = self.model.objects.all().filter(search_connection)
    
    
            #按照showlist展示页面, 构建表头,表单
            show_list = ShowList(self,data_list,request)  # self=ModelSTark实例对象
    
            # 构建一个查看addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
     

    4、解耦

    如果没有在starkadmin定义search_fields字段,就不显示search按钮

     

     6、代码

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/17 0017 14:46
    # @Author  : Venicid
    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
    
            # 分页
            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=11, pager_count=11,)
    
            # 分页后的数据
            self.page_data = self.data_list[self.pagination.start:self.pagination.end]
    
        def get_header(self):
            # 构建表头
            header_list = []  # # header_list = ['选择','pk',...'操作','操作']
            for field in self.config.new_list_play():
                if callable(field):
                    # header_list.append(field.__name__)
                    val = field(self.config,header=True)
                    header_list.append(val)
                else:
                    if field == "__str__":
                        header_list.append(self.config.model._meta.model_name.upper())
                    else:
                        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.page_data:    #分页后的数据               # Book表模型,Author表模型
                temp = []
                for field in self.config.new_list_play():     # ['name','age']
                    if callable(field):                 # edit()  可调用的
                        val = field(self.config,obj)           # 直接调用edit()函数
                        print('val--------->',val)
                    else:
                        val = getattr(obj,field)       # 反射  obj是实例对象,name是方法
    
                        # list_display_links 按钮
                        if field in self.config.list_display_links:
                            model_name = self.config.model._meta.model_name
                            app_label = self.config.model._meta.app_label
                            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                            # print(_url)
                            val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            print('new_data_list',new_data_list)        # 构造数据  [['jack', 44], ['mark', 33]]
    
            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
    
        # 增删改查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 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 edit(self,obj=None, header=False):
            if header:
                return "操作"
            # 方案1:固定url
            # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
            # 方案2:拼接url
            # return mark_safe("<a href='%s/change'>编辑</a>")
    
            # 方案3:反向解析
            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,))
            # print("_url",_url)
            return mark_safe("<a href='%s'>编辑</a>"%_url)
    
    
        def deletes(self,obj=None, header=False):
            if header:
                return "操作"
            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 mark_safe("<a href='%s'>删除</a>"%_url)
    
    
    
        # ModelForm组件渲染  list、增、删、改页面
        def get_modelform_class(self):
            """ModelForm组件"""
            if not self.modelform_class:
                from django.forms import ModelForm
                class ModelFormDemo(ModelForm):
                    class Meta:
                        model = self.model
                        fields = "__all__"
                return ModelFormDemo
            else:
                return self.modelform_class
    
        def new_list_play(self):
            """构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
            temp = []
            temp.append(ModelStark.checkbox)
            temp.extend(self.list_display)
            if not self.list_display_links:
                temp.append(ModelStark.edit)
            temp.append(ModelStark.deletes)
            return temp
    
    
        '''
        def list_view(self,request):
            ret1 = self.model.objects.filter(title__startswith='py')
            ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
            ret3 = self.model.objects.filter(price__range=[10,20])
            ret4 = self.model.objects.filter(title__contains='O')
            ret5 = self.model.objects.filter(title__icontains='O')
            return HttpResponse("过滤成功")
        '''
    
        def get_search_condition(self,request):
            """search模糊查询"""
            key_word = request.GET.get("q",'')
            self.key_word = key_word
            from django.db.models import Q   # 与或非
            search_connection = Q()
            if key_word:
                search_connection.connector = "or"
                for search_field in self.search_fields:
                    search_connection.children.append((search_field+"__contains", key_word))
    
            return search_connection
    
        def list_view(self, request):
            # 获取search的Q对象
            search_connection = self.get_search_condition(request)
    
            # 筛选获取当前表所有数据
            data_list = self.model.objects.all().filter(search_connection)
    
            #按照showlist展示页面, 构建表头,表单
            show_list = ShowList(self,data_list,request)  # self=ModelSTark实例对象
    
            # 构建一个查看addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
    
    
        def add_view(self, request):
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo()
            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())
    
        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)
            return render(request, "delete_view.html", locals())
    
        def change_view(self, request, id):
            edit_obj = self.model.objects.filter(pk=id).first()
    
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo(instance=edit_obj)
            if request.method == "POST":
                form = ModelFormDemo(request.POST,instance=edit_obj)
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url())
    
            return render(request, "change_view.html",locals())
    
    
        #构造 add/delete/change
        def get_urls2(self):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            temp = []
            temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
            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)))
    
            return temp
    
        @property
        def urls2(self):
    
            return self.get_urls2(), None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self,model, stark_class=None):
            """注册"""
            if not stark_class:
                stark_class = ModelStark
    
            self._registry[model] = stark_class(model,self)
    
        def get_urls(self):
            """构造一层urls app01/book"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                print(model, 'stark_clas_obj', stark_class_obj)  # 不同的model模型表
                """
                 <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
                 <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
                 """
    
                app_label = model._meta.app_label     # app01
                model_name = model._meta.model_name   # book
                # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
                temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
    
            return temp
    
        @property
        def urls(self):
    
            # return [],None,None
            return self.get_urls(),None,None
    
    site = StarkSite()   # 单例对象
    stark/service/stark.py
    from stark.service import stark
    from .models import *
    from django.forms import ModelForm
    
    class BookModelForm(ModelForm):
        class Meta:
            model = Book
            fields = "__all__"
    
            labels = {
                "authors":"作者",
                "publishDate":"出版日期",
            }
    
    class BookConfig(stark.ModelStark):
        list_display = ['nid', 'title', 'price']
        modelform_class = BookModelForm
        # search_fields = ['title','price']
    
    class AuthorConfig(stark.ModelStark):
        list_display = ['nid', 'name', 'age']
        list_display_links = ['name','age']
    
    
    
    stark.site.register(Book,BookConfig)
    stark.site.register(Publish)
    stark.site.register(Author,AuthorConfig)
    stark.site.register(AuthorDetail)
    
    print(stark.site._registry)
    
    """
    {<class 'app01.models.Book'>: <stark.service.stark.ModelStark object at 0x0000003AA7439630>,
    <class 'app01.models.Publish'>: <stark.service.stark.ModelStark object at 0x0000003AA7439668>,
    <class 'app01.models.Author'>: <stark.service.stark.ModelStark object at 0x0000003AA74396A0>,
    <class 'app01.models.AuthorDetail'>: <stark.service.stark.ModelStark object at 0x0000003AA7439940>}
    """
    starkadmin.py
    {% extends 'base.html' %}
    
    {% block title %}
        <title>list页面</title>
    {% endblock %}
    
    {% block header %}
        <h3>list页面</h3>
    {% endblock %}
    {% block content %}
        <a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
        {% if show_list.config.search_fields %}
            <form action="" method="get" class="pull-right">
                <input type="text" name="q" value="{{ show_list.config.key_word }}">
                <button>submit</button>
            </form>
        {% endif %}
    
    
        <table class="table table-bordered table-striped">
            <tr>
                {% for header in show_list.get_header %}
                    {#            {% for header in header_list %}#}
                    <th>{{ header }}</th>
                {% endfor %}
            </tr>
    
            {% for data in show_list.get_body %}
                {#        {% for data in new_data_list %}#}
                <tr>
                    {% for item in data %}
                        <td>{{ item }}</td>
                    {% endfor %}
    
                </tr>
            {% endfor %}
        </table>
        <nav>
            <ul class="pagination">
                {{ show_list.pagination.page_html|safe }}
            </ul>
        </nav>
    
    {% endblock %}
    
    
    {% block javascript %}
        <script type="text/javascript">
            $('#choice').click(function () {
                if ($(this).prop('checked')) {   //对象自身属性中是否具有指定的属性
                    $('.choice_item').prop("checked", true)
                } else {
                    $('.choice_item').prop("checked", false)
                }
            })
        </script>
    {% endblock %}
    list_view.html

     代码解析:

     #设定一个search_fields=[],用户自定义好字段后,进行下一步。
                {% if showlist.config.serach_fields %}
                    <form action="" class="pull-right">
                        <input type="text" name="q" value="{{ showlist.config.key_word }}" class="form-control">
                        <button class="btn btn-default pull-right">搜索</button>
                    </form>
                {% endif %}
    #首先在前端加一个框,然后在将提交的name设为q。

    第二步:

     #下面函数取到get请求过来的数据。
             def get_serach_conditon(self,request):
                key_word = request.GET.get("q","")     #从前端拿到q
                self.key_word=key_word                 #然后赋给self.
                from django.db.models import Q
                search_connection = Q()   #生成一个Q()对象
                if key_word:              #如果请求有值,表示真实搜索。
                    # self.search_fields # ["title","price"]
                    search_connection.connector = "or"     #Q对象使用“或”查询。
                    #在这里组建一个Q对象,需要将列表内的字符串把引号去掉,并且这个Q对象是或的关系,最后返回
                    for search_field in self.serach_fields:       #遍历每一个字段,加上__contains
                        search_connection.children.append((search_field + "__contains", key_word))
                return search_connection  
                #之所以这么麻烦的创建Q对象,创建或关系,是因为model查询的是price=123,而search_fields是字符串,只有这样才能把字符串去掉。

    第三部:

    #视图中获取Q对象:
            search_connection=self.get_serach_conditon(request)
    
            #获取当前表筛选之后的数据,没有筛选条件则为全部
            data_list = self.model.objects.all().filter(search_connection)
    
            #按这个类的方法进行展示
            showlist=ShowList(self,data_list,request)
            #前端模板全部使用showlist.config.key_word,showlist.get_header,showlist.get_body,{{ showlist.pagination.page_html|safe }}这种的去进行渲染。
    
            #然后通过字段__contains可以模糊匹配到值,并且展示。

    4、action批量处理数据

    0、必备知识

    1、admin的批量初始化

     

    3、starkadmin之actions

    老样子,自定义一个列表,放入需要执行的函数名。

    self.actions=self.config.actions

    4、构建actions数据

     

     def get_action_list(self):
                temp=[]
                for action in self.actions:
                    temp.append({
                        "name":action.__name__,
                        "desc":action.short_description
                    })
                    #[{"name":patch_init,"desc":"批量初始化"}]
                return temp
           #在ShowList这个类中对这个列表进行修改,变成如上一样列表套字典的结构。

    5、前端的按钮checkbox,提交数据

           #这样在前端模板中使用:
            <select name="action" id="" style="150px;margin-top: 10px;margin-bottom: 10px ;padding: 4px 8px;display: inline-block">
                        <option value="">--------------</option>
                        {% for item in showlist.get_action_list  %}    
                            <option value="{{ item.name }}">{{ item.desc }}</option>
                        {% endfor %}
                    </select>
            进行一波渲染,将这个列表渲染进去。这样选中某个方法,前端传回到后端一个action的列表,
            取到这个列表即可知道你选的哪个。
            return mark_safe("<input class='choice_item' value='%s' type='checkbox' name='selected_pk'>"%obj.pk)
            在checkbox中加入一个name,和每个字段的主键值,这样选中后上传到后台的是一个
            'selected_pk': ['8', '9']这种类型的列表。

     6、post提交处理 数据

     

    #最后这个form表单不同于搜索的是,这个是post请求,所以在视图函数中需要处理的是post请求。
                if request.method == "POST":
                    print(request.POST)
                    action=request.POST.get("action")
                    select_pk=request.POST.getlist("selected_pk")
                    queryset=self.model.objects.filter(pk__in=select_pk)
                    action_func=getattr(self,action)
                    action_func(request,queryset)
                #首先取到方法名字,然后取到选中的主键值,这里注意需要用到gellist,不然只会取到一个。
               # 然后利用queryset=self.model.objects.filter(pk__in=select_pk),利用In可以取到一个
                queryset。#将这个queryset以后,传入需要执行的函数作为参数以后,方法执行update或者delete
                #等等各种操作就非常容易了。这样就可以进行批量的修改了。

    6、starkadmin.py

     
    from django.shortcuts import HttpResponse
    from stark.service import stark
    from .models import *
    from django.forms import ModelForm
    
    class AuthorConfig(stark.ModelStark):
        list_display = ['nid', 'name', 'age']
        list_display_links = ['name','age']
    
    
    class BookModelForm(ModelForm):
        class Meta:
            model = Book
            fields = "__all__"
    
            labels = {
                "authors":"作者",
                "publishDate":"出版日期",
            }
    
    class BookConfig(stark.ModelStark):
        list_display = ['nid', 'title', 'price']
        modelform_class = BookModelForm
        search_fields = ['title','price']
    
        # 批量修改数据
        def patch_init(self,request,queryset):
            queryset.update(price=111)
    
            # return HttpResponse("批量初始化OK")
    
        patch_init.short_description = "批量初始化"
    
        actions = [patch_init]
    
    
    stark.site.register(Book,BookConfig)
    stark.site.register(Publish)
    stark.site.register(Author,AuthorConfig)
    stark.site.register(AuthorDetail)
    
    print(stark.site._registry)
     

    7、stark/service /stark

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/17 0017 14:46
    # @Author  : Venicid
    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
    
            # 分页
            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=11, pager_count=11,)
    
            # 分页后的数据
            self.page_data = self.data_list[self.pagination.start:self.pagination.end]
    
            # actions 批量初始化,字段
            self.actions = self.config.actions # [patch_init]
            # 构建数据[{'name':'path_init',"desc":'xxxxx'}]
    
    
        def get_action_list(self):
            """action批量初始化,构架数据"""
            temp = []
            for action in self.actions:
                temp.append(
                    {'name':action.__name__,                # class的类名
                     "desc":action.short_description        # class的属性
                     }
                )
            return temp
    
        def get_header(self):
            # 构建表头
            header_list = []  # # header_list = ['选择','pk',...'操作','操作']
            for field in self.config.new_list_play():
                if callable(field):
                    # header_list.append(field.__name__)
                    val = field(self.config, header=True)
                    header_list.append(val)
                else:
                    if field == "__str__":
                        header_list.append(self.config.model._meta.model_name.upper())
                    else:
                        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.page_data:    #分页后的数据               # Book表模型,Author表模型
                temp = []
                for field in self.config.new_list_play():     # ['name','age']
                    if callable(field):                 # edit()  可调用的
                        print(obj,99999999999999999)
                        val = field(self.config,obj)           # 直接调用edit()函数
                        print('val--------->',val)
                    else:
                        val = getattr(obj,field)       # 反射  obj是实例对象,name是方法
    
                        # list_display_links 按钮
                        if field in self.config.list_display_links:
                            model_name = self.config.model._meta.model_name
                            app_label = self.config.model._meta.app_label
                            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                            # print(_url)
                            val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            print('new_data_list',new_data_list)        # 构造数据  [['jack', 44], ['mark', 33]]
    
            return new_data_list
    
    
    class ModelStark(object):
        list_display = ["__str__"]  # 子类中没有,直接用父类自己的
        list_display_links = []
        modelform_class = []
        search_fields = []  # 模糊查询字段
        actions = []
    
        def __init__(self,model, site):
            self.model = model
            self.site = site
    
        # 增删改查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 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)
    
    
        def edit(self,obj=None, header=False):
            if header:
                return "操作"
            # 方案1:固定url
            # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
            # 方案2:拼接url
            # return mark_safe("<a href='%s/change'>编辑</a>")
    
            # 方案3:反向解析
            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,))
            # print("_url",_url)
            return mark_safe("<a href='%s'>编辑</a>"%_url)
    
    
        def deletes(self,obj=None, header=False):
            if header:
                return "操作"
            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 mark_safe("<a href='%s'>删除</a>"%_url)
    
    
    
        # ModelForm组件渲染  list、增、删、改页面
        def get_modelform_class(self):
            """ModelForm组件"""
            if not self.modelform_class:
                from django.forms import ModelForm
                class ModelFormDemo(ModelForm):
                    class Meta:
                        model = self.model
                        fields = "__all__"
                return ModelFormDemo
            else:
                return self.modelform_class
    
        def new_list_play(self):
            """构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
            temp = []
            temp.append(ModelStark.checkbox)
            temp.extend(self.list_display)
            if not self.list_display_links:
                temp.append(ModelStark.edit)
            temp.append(ModelStark.deletes)
            return temp
    
    
        '''
        def list_view(self,request):
            ret1 = self.model.objects.filter(title__startswith='py')
            ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
            ret3 = self.model.objects.filter(price__range=[10,20])
            ret4 = self.model.objects.filter(title__contains='O')
            ret5 = self.model.objects.filter(title__icontains='O')
            return HttpResponse("过滤成功")
        '''
    
        def get_search_condition(self,request):
            """search模糊查询"""
            key_word = request.GET.get("q",'')
            self.key_word = key_word
            from django.db.models import Q   # 与或非
            search_connection = Q()
            if key_word:
                search_connection.connector = "or"
                for search_field in self.search_fields:
                    search_connection.children.append((search_field+"__contains", key_word))
    
            return search_connection
    
        def list_view(self, request):
            if request.method == 'POST':
                print('post',request.POST)
                action = request.POST.get("action")                     # action': ['patch_init'],
                if action:
                    selected_pk = request.POST.getlist('selected_pk')       # 'selected_pk': ['5']}>
                    action_func = getattr(self,action)  # 反射查询 action
    
                    queryset = self.model.objects.filter(pk__in=selected_pk)        # 查询
                    ret = action_func(request,queryset)    # 执行action()
                    # return ret
    
    
            # 获取search的Q对象
            search_connection = self.get_search_condition(request)
    
            # 筛选获取当前表所有数据
            data_list = self.model.objects.all().filter(search_connection)
    
            #按照showlist展示页面, 构建表头,表单
            show_list = ShowList(self,data_list,request)  # self=ModelSTark实例对象
    
            # 构建一个查看addurl
            add_url = self.get_add_url()
            return render(request,'list_view.html', locals())
    
    
        def add_view(self, request):
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo()
            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())
    
        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)
            return render(request, "delete_view.html", locals())
    
        def change_view(self, request, id):
            edit_obj = self.model.objects.filter(pk=id).first()
    
            ModelFormDemo=self.get_modelform_class()
            form = ModelFormDemo(instance=edit_obj)
            if request.method == "POST":
                form = ModelFormDemo(request.POST,instance=edit_obj)
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url())
    
            return render(request, "change_view.html",locals())
    
    
        #构造 add/delete/change
        def get_urls2(self):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            temp = []
            temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
            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)))
    
            return temp
    
        @property
        def urls2(self):
    
            return self.get_urls2(), None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self,model, stark_class=None):
            """注册"""
            if not stark_class:
                stark_class = ModelStark
    
            self._registry[model] = stark_class(model,self)
    
        def get_urls(self):
            """构造一层urls app01/book"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                print(model, 'stark_clas_obj', stark_class_obj)  # 不同的model模型表
                """
                 <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
                 <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
                 """
    
                app_label = model._meta.app_label     # app01
                model_name = model._meta.model_name   # book
                # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
                temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
    
            return temp
    
        @property
        def urls(self):
    
            # return [],None,None
            return self.get_urls(),None,None
    
    site = StarkSite()   # 单例对象
    View Code

    8、list_view.html

    {% extends 'base.html' %}
    
    {% block title %}
        <title>list页面</title>
    {% endblock %}
    
    {% block header %}
        <h3>list页面</h3>
    {% endblock %}
    {% block content %}
        <p><a class="btn btn-primary" href="{{ add_url }}">添加数据</a></p>
        {% if show_list.config.search_fields %}
            <form action="" method="get" class="pull-right">
                <input type="text" name="q" value="{{ show_list.config.key_word }}">
                <button>submit</button>
            </form>
        {% endif %}
    
    
        <form action="" method="post">
            {% csrf_token %}
    
            {% if show_list.get_action_list %}
                <select name="action" id="" style="display: inline-block; 200px;margin: 8px 8px 8px 0;height: 25px">
                    {% for item in show_list.get_action_list %}
                        <option value="">-------</option>
                        <option value="{{ item.name }}">{{ item.desc }}</option>
                    {% endfor %}
                </select>
                <button type="submit" class="btn btn-default">Go</button>
    
            {% endif %}
    
    
            <table class="table table-bordered table-striped">
                <tr>
                    {% for header in show_list.get_header %}
                        {#            {% for header in header_list %}#}
                        <th>{{ header }}</th>
                    {% endfor %}
                </tr>
    
                {% for data in show_list.get_body %}
                    {#        {% for data in new_data_list %}#}
                    <tr>
                        {% for item in data %}
                            <td>{{ item }}</td>
                        {% endfor %}
    
                    </tr>
                {% endfor %}
            </table>
        </form>
    
        <nav>
            <ul class="pagination">
                {{ show_list.pagination.page_html|safe }}
            </ul>
        </nav>
    
    {% endblock %}
    
    
    {% block javascript %}
        <script type="text/javascript">
            $('#choice').click(function () {
                if ($(this).prop('checked')) {   //对象自身属性中是否具有指定的属性
                    $('.choice_item').prop("checked", true)
                } else {
                    $('.choice_item').prop("checked", false)
                }
            })
        </script>
    {% endblock %}
    View Code

    4、总结

    1、分页知识点

    1.分页
    {{ showlist.pagination.page_html|safe }}

    2.page.py
        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:  最多显示的页码个数
                :param params:  ? 后面携带得参数 request.GET
                """
    
            ...
    
        注意:翻页时,http://127.0.0.1:8090/stark/app01/publish/?page=2&name=alice&age=18
            每页需带上之前的参数。
    
        import copy
        params = copy.deepcopy(params)
        params._mutable = True
        self.params = params  # self.params : {"page":77,"title":"python","nid":1}
    
        self.params["page"] = i
        self.params.urlencode()  将{"name":"alice","age":18} 转换成 name=alice&age=18
    
        temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)

    3.list_view 视图函数
      表头,表数据,分页... 内容太多,封装在一个类里面专门用来展示数据。
        # 展示数据
        showlist = ShowList(self, data_list, request)
        class ShowList(object):
            def __init__(self):
                pass
    
            def get_header(self):
                pass
    
            def get_body(self):
                pass
     

    2、search模糊查询

    1.判断用户是否配置,配置才显示search框, get查询
       search_fields = ['title', 'price']
    
        显示key_words{{ showlist.config.key_words }}
        {% if showlist.config.search_fields %}
            <form action="" class="pull-right">
                <input type="text" name="q" value="{{ showlist.config.key_words }}"><button>submit</button>
            </form>
        {% endif %}

    2.Q对象
     # 获取search得Q对象
        search_connection = self.get_search_condition(request)
    
        # print("connection:",search_connection)
        # connection: (or: ('title__contains', '3'), ('price__contains', '3'))
    
        # 筛选当前表得所有数据
        data_list = self.model.objects.all().filter(search_connection)


    3.Q查询
        两种方式,一种可以放str,就是下面这种,一种放字段;
    
        def get_search_condition(self, request):
            key_words = request.GET.get('q', "")
            self.key_words = key_words
    
            # self.search_fields   ['title','price']
    
            from django.db.models import Q
            search_connection = Q()
            if key_words:
                search_connection.connector = "or"
                for search_field in self.search_fields:
                    search_connection.children.append((search_field+"__contains", key_words))
    
            return search_connection

    4.模糊查询
      (title__contains)(price__contains)
        search_connection.children.append((search_field+"__contains", key_words))

    3、action批量初始化

    知识点

    1.用户可自定义配置
        def patch_init(self, request, queryset):
            # print("queryset",queryset)
            queryset.update(price=123)
    
            # return HttpResponse('批量初始化OK')
    
        patch_init.short_description = "批量初始化"
        actions = [patch_init]
    2.无论有没有配置,都会有一个默认得批量删除
        def patch_delete(self, request, queryset):
            queryset.delete()
        patch_delete.short_description = "批量删除"
    
        def new_actions(self):
            temp = []
            temp.append(ModelStark.patch_delete)
            temp.extend(self.actions)
    
            return temp
    3.展示页面 option
    传过去得数据:  __name__ (方法名传过去,做为value,为之后反射做准备)
        self.actions = self.config.new_actions()
    
        def get_action_list(self):
            temp = []
            for action in self.actions:
                temp.append({
                    "name": action.__name__,
                    "desc":action.short_description
                })
    
            return temp
    4.前端
     主要就是将:方法名赋值给option得value, form post请求,将值传到后台
        <select name="action" id="" style=" 200px; padding: 5px 8px; display: inline-block; ">
            <option value="">------------</option>
            {% for item in showlist.get_action_list %}
                <option value="{{ item.name }}">{{ item.desc }}</option>
            {% endfor %}
        </select>
    5.后台
      接收用户选中得数据,action selected_pk
        反射:action_func = getattr(self, action)
        过滤查询:queryset: queryset = self.model.objects.filter(pk__in=selected_pk)
        执行反射回来得函数: action_func(request, queryset)
    
        def list_view(self, request):
            if request.method == "POST":
                print("request.POST:",request.POST)
                # 'action': ['patch_init'], 'selected_pk': ['1', '2']
                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)  # 秒!!!
                ret = action_func(request, queryset)
                # return ret
    
            ...
  • 相关阅读:
    Evidence on the impact of sustained exposure to air pollution on life expectancy
    International Immunopharmacology/ Perinatal and early childhood environmental factors influencing allergic asthma immunopathogenesis
    Projections of the effects of climate change on allergic asthma: the contribution of aerobiology
    Word List 2
    GRE : TC21
    Grammar Mistake: What is a faulty tense sequence?
    Biology 02: Respiration
    127 super()方法详解
    128 类的多态和多态性
    126 菱形继承问题
  • 原文地址:https://www.cnblogs.com/geogre123/p/9790550.html
Copyright © 2020-2023  润新知