zoukankan      html  css  js  c++  java
  • crm04 action操作 和 多级过滤

    # -*- coding: utf-8 -*-
    # @Time    : 2019/4/12 11:51
    # @Author  : xxx
    # @Email   : xxx@admin.com
    # @File    : sites.py
    # @Software: PyCharm
    from django.urls import path,re_path
    from django.shortcuts import HttpResponse,render,redirect
    from app01.models import *
    from django.utils.safestring import mark_safe
    from django.core.exceptions import FieldDoesNotExist
    from django.urls import reverse
    from django.db.models import Q
    class ShowList(object):
        def __init__(self,request,config_obj,queryset):
            self.config_obj=config_obj
            self.queryset=queryset
            self.request=request
            self.pager_queryset=self.get_pager_queryset()
    
        def get_pager_queryset(self):
    
            from stark.utils.page import Pagination
            current_page = self.request.GET.get("page", 1)
            self.pagination = Pagination(self.request, current_page, self.queryset, per_page_num=self.config_obj.per_page_num or 5)
            queryset = self.queryset[self.pagination.start:self.pagination.end]
    
            return queryset
    
        def get_header(self):
            '''
            获取表头
            :return:
            '''
            #   构建表头
    
            header_list = []
            for field_or_func in self.config_obj.get_new_list_display():
                if callable(field_or_func):
                    val = field_or_func(self.config_obj, header=True)
                    header_list.append(val)
                    # header_list.append(field_or_func.__name__)
                else:
                    if field_or_func == "__str__":
                        val = self.config_obj.model._meta.model_name.upper()
                        print(val)
                    else:
                        field_obj = self.config_obj.model._meta.get_field(field_or_func)
                        val = field_obj.verbose_name
                    header_list.append(val)
    
            return header_list
    
        def get_body(self):
            '''
            获取标体
            :return:
            '''
            #  构建展示数据
            new_data = []
            for obj in self.pager_queryset:
                temp = []
    
                for field_or_func in self.config_obj.get_new_list_display():  # ["title","price","state","publish",show_authors]
                    if callable(field_or_func):
                        #  field:方法
                        val = field_or_func(self.config_obj, obj)
                    else:
                        try:
                            #  field:字符串
                            from django.db.models.fields.related import ManyToManyField
                            field_obj = self.config_obj.model._meta.get_field(field_or_func)
                            #  判断是否多对多字段
                            if type(field_obj) == ManyToManyField:
                                raise Exception("list_display不能是多对多字段!")
                            #  判断字段是否 拥有choices属性
                            if field_obj.choices:
                                val = getattr(obj, "get_%s_display" % field_or_func)()
                            else:
                                val = getattr(obj, field_or_func)
                                if field_or_func in self.config_obj.list_display_links:
                                    val = mark_safe("<a href='%s'>%s</a>" % (self.config_obj.get_change_url(obj), val))
    
                        except FieldDoesNotExist as e:
                            # val=obj
                            val = getattr(obj, field_or_func)()
    
                    temp.append(val)
                new_data.append(temp)
    
            print("new_data", new_data)  # [['python', Decimal('123.00')], ['java', Decimal('234.00')]]
    
            '''
            目标数据结构
            new_data=[
                ["python",123],
                ["java",234]
            ]
            '''
    
            return new_data
    
    class ModelStark(object):
        '''
        默认配置类
        '''
        list_display=("__str__",)
        list_display_links = []
        model_form_class=None
        per_page_num=None
        search_fields=[]
        search_val=None
        list_filter=[]
    
        def __init__(self,model):
            self.model=model
            self.model_name = self.model._meta.model_name
            self.app_label = self.model._meta.app_label
    
        # 反向解析当前访问表的增删改查URL
        def get_list_url(self):
            # 反向解析当前表的删除的URL
            list_url = reverse("%s_%s_list" % (self.app_label, self.model_name))
            return list_url
    
        def get_add_url(self):
            # 反向解析当前表的删除的URL
            add_url = reverse("%s_%s_add" % (self.app_label, self.model_name))
            return add_url
    
        def get_delete_url(self,obj):
            # 反向解析当前表的删除的URL
            delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,))
            return delete_url
    
        def get_change_url(self, obj):
            # 反向解析当前表的删除的URL
            change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,))
            return change_url
    
        # 三个默认列
        def show_checkbox(self, obj=None, header=False):
            if header:
                return mark_safe("<input type='checkbox'>")
            return mark_safe("<input name='_selected_action' value=%s type='checkbox'>"%obj.pk)
    
        def show_delbtn(self, obj=None, header=False):
            if header:
                return "删除"
    
            return mark_safe("<a href='%s'>删除</a>"%self.get_delete_url(obj))
    
        def show_editbtn(self, obj=None, header=False):
            if header:
                return "编辑"
            return mark_safe("<a href='%s'>编辑</a>" %self.get_change_url(obj))
    
        #  构建新的list_display
    
        def get_new_list_display(self):
            temp=[]
            temp.extend(self.list_display)
            temp.append(ModelStark.show_editbtn)
            temp.append(ModelStark.show_delbtn)
            temp.insert(0,ModelStark.show_checkbox)
    
            return temp
    
        def get_search_condition(self,request):
            val = request.GET.get("q")
    
    
            q = Q()
            if val:
                self.search_val = val
                q.connector = "or"
                for field in self.search_fields:  # ["title","price"]
                    print(field)
                    # queryset=queryset.filter(Q(title__contains=val)|Q(price__contains=val))
                    q.children.append((field + "__contains", val))
            else:
                self.search_val=None
    
            return q
    
        # def get_search_links(self):
        #     import copy
        #     params = copy.deepcopy(self.request.GET)  # {"publish":1,"authors":1}
        #     search_button = "<a class='btn btn-primary' href='?%s'>Search!</a>" % params.urlencode()
        #     return search_button
    
    
    
        ####################  action操作  ###############################
        # action参数
        def patch_delete(self,request,queryset): # [1,3]
            queryset.delete()
    
        patch_delete.desc="批量删除"
    
        actions=[]
        def get_new_actions(self):
            temp=[]
            temp.extend(self.actions)
            temp.append(self.patch_delete)
            return temp
    
        def get_action_dict(self):
            actions_list=[]
            for func in self.get_new_actions():
                actions_list.append({
                    "name":func.__name__,
                    "desc":func.desc,
                })
    
            return actions_list   # [{"name":"patch_delete","desc":"批量删除"}]
    
    
    
    ####################  多筛选操作  ###############################
        def get_list_filter_links(self):
    
            list_filter_links={}
    
            print(self.list_filter)  # ["publish","authors","state"]
    
            for filter_field in self.list_filter:
                import copy
                params = copy.deepcopy(self.request.GET)  # {"publish":1,"authors":1}
                current_field_val=params.get(filter_field)
                print('params--->',params)  #params---> <QueryDict: {}>  http://127.0.0.1:8000/stark/app01/book/
    
                filter_field_obj=self.model._meta.get_field(filter_field) #获取模型类的字段类对象  eg:state  = models.IntegerField(choices=[(1,"已出版"),(2,"未出版社")],default=1)
                print(">>>",type(filter_field_obj))  #["publish","authors","state"]---><class 'django.db.models.fields.related.ForeignKey'>,<class 'django.db.models.fields.related.ManyToManyField'>,<class 'django.db.models.fields.IntegerField'>
                from django.db.models.fields.related import ForeignKey,ManyToManyField
                # 针对一对多或者多对多过滤字段
                if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
                    print(filter_field_obj.remote_field)#["publish","authors","state"]---><ManyToOneRel: app01.book>,<ManyToManyRel: app01.book>,
                    print("____>",filter_field_obj.remote_field.model) #  eg:<class 'app01.models.Publish'>  找到 模型类的字段类对象 的那个字段类  eg:state--->IntegerField  publish---> Publish
                    #["publish","authors","state"]---><class 'app01.models.Publish'>,<class 'app01.models.Author'>,
                    data=filter_field_obj.remote_field.model.objects.all()  # eg:<QuerySet [<Publish: 苹果出版设>, <Publish: 橘子出版设>, <Publish: 西瓜出版社>]>
                    print(data)
                elif filter_field_obj.choices:
                    # print(filter_field_obj.remote_field)  None
                    # 针对choice字段类型
                    data=filter_field_obj.choices # eg:[(1,"已出版"),(2,"未出版社")]
                else:
                    raise Exception("过滤字段不能太普通!")
    
                #  为每一个数据构建成一个a标签
                temp = []
                # params2=copy.deepcopy(params)
                if params.get(filter_field):  #对list_filter_links和params.urlencode()的影响
                    del params[filter_field]
    
                all = "<a class='btn btn-default btn-sm' href='?%s'>全部</a>"%params.urlencode()  #用户点击时 所有的
                temp.append(all)
    
    
                for item in data:
                    if type(item)==tuple:
                        # 元组类型
                        pk,text = item
                    else:
                        # model对象类型
                        pk,text = item.pk,str(item)
    
                    params[filter_field]=pk            #  ***********
                    _url="?%s"%(params.urlencode())    #  ***********
                    print('url',_url)
                    if current_field_val==str(pk):
                         link="<a class='active btn btn-default btn-sm' href='%s'>%s</a>"%(_url,text)
                    else:
                         link = "<a class='btn btn-default btn-sm' href='%s'>%s</a>" % (_url, text)
    
                    temp.append(link)
    
                list_filter_links[filter_field]=temp
            # print('hahhahaha',list_filter_links)
            '''
            print('hahhahaha',list_filter_links)
            hahhahaha {
            'publish': ["<a class='btn btn-default btn-sm' href='?'>全部</a>", "<a class='btn btn-default btn-sm' href='?publish=1'>苹果出版设</a>", "<a class='btn btn-default btn-sm' href='?publish=2'>橘子出版设</a>", "<a class='btn btn-default btn-sm' href='?publish=3'>西瓜出版社</a>"], 
            'authors': ["<a class='btn btn-default btn-sm' href='?'>全部</a>", "<a class='btn btn-default btn-sm' href='?authors=1'>alex</a>", "<a class='btn btn-default btn-sm' href='?authors=2'>egon</a>"], 
            'state': ["<a class='btn btn-default btn-sm' href='?'>全部</a>", "<a class='btn btn-default btn-sm' href='?state=1'>已出版</a>", "<a class='btn btn-default btn-sm' href='?state=2'>未出版社</a>"]}
            '''
            return list_filter_links
    
        def get_list_filter_condition(self):
    
            q=Q()
            for filter_field,val in self.request.GET.items():
                if filter_field in ["page","q"]:continue
                q.children.append((filter_field,val))
    
            return q
    
    ###########################################################################################
    
        #  视图函数
        def list_view(self,request):
            '''
            self: 当前访问模型表对应的配置类对象
            self.model: 当前访问模型表
            :param request:
            :return:
            '''
            self.request=request
    
            if request.method=="POST":
                #  action操作
                action_func_str=request.POST.get("action")
                if  action_func_str:
                    action_func=getattr(self,action_func_str)
                    _selected_action=request.POST.getlist("_selected_action") # [1,3]
                    queryset=self.model.objects.filter(pk__in=_selected_action)
                    action_func(request,queryset)
    
    
            queryset=self.model.objects.all()
    
            # search过滤
            search_condition=self.get_search_condition(request)
            # list_filter多级过滤+
            list_filter_condition=self.get_list_filter_condition()
    
            queryset=queryset.filter(search_condition).filter(list_filter_condition)
    
            show_list=ShowList(request,self,queryset)
    
            #  相关变量
            table_name=self.model._meta.verbose_name
            add_url=self.get_add_url()
    
    
            return render(request,'stark/list_view.html',locals())
    
        def get_model_form(self):
            from django.forms import ModelForm
            class BaseModelForm(ModelForm):
                class Meta:
                    model = self.model
                    fields = "__all__"
    
            return self.model_form_class or BaseModelForm
    
        def add_view(self,request):
            BaseModelForm=self.get_model_form()
    
            if  request.method=="GET":
                form_obj=BaseModelForm()
                return render(request,"stark/add_view.html",locals())
            else:
                form_obj = BaseModelForm(request.POST)
                if form_obj.is_valid():
                    form_obj.save()
                    return redirect(self.get_list_url())
                else:
                    return render(request, "stark/add_view.html", locals())
    
        def change_view(self,request,id):
            BaseModelForm=self.get_model_form()
            edit_obj=self.model.objects.filter(pk=id).first()
            if  request.method=="GET":
                form_obj=BaseModelForm(instance=edit_obj)
                return render(request,"stark/change_view.html",locals())
            else:
                form_obj = BaseModelForm(request.POST,instance=edit_obj)
                if form_obj.is_valid():
                    form_obj.save()
                    return redirect(self.get_list_url())
                else:
                    return render(request, "stark/change_view.html", locals())
    
        def delete_view(self,request, id):
    
            if request.method=="POST":
                self.model.objects.filter(pk=id).delete()
                return redirect(self.get_list_url())
    
            list_url=self.get_list_url()
            return render(request,"stark/delete_view.html",locals())
    
        @property
        def get_urls(self):
    
            temp = [
                path("", self.list_view,name="%s_%s_list"%(self.app_label,self.model_name)),
                path("add/", self.add_view,name="%s_%s_add"%(self.app_label,self.model_name)),
                re_path("(d+)/change/", self.change_view,name="%s_%s_change"%(self.app_label,self.model_name)),
                re_path("(d+)/delete/", self.delete_view,name="%s_%s_delete"%(self.app_label,self.model_name)),
            ]
    
            return (temp, None, None)
    
    class StarkSite:
        '''
        stark全局类
        '''
        def __init__(self):
            self._registry = {}
    
        def register(self, model, admin_class=None, **options):
            admin_class = admin_class or ModelStark
            self._registry[model] = admin_class(model)
    
    
        def get_urls(self):
            #  动态为注册的模型类创建增删改查URL
            temp = []
            # {Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)}
            for model, config_obj in self._registry.items():
                print("---->", model, config_obj)
                model_name = model._meta.model_name
                app_label = model._meta.app_label
                temp.append(
                    path("%s/%s/" % (app_label,model_name),config_obj.get_urls)
                )
    
            '''
               path("stark/app01/book",BookConfig(Book).list_view)
               path("stark/app01/book/add",BookConfig(Book).add_view)      
               path("stark/app01/publish",ModelAdmin(Publish).list_view)
               path("stark/app01/publish/add",ModelAdmin(Publish).add_view)
            
            '''
    
            return temp
    
        @property
        def urls(self):
            return self.get_urls(),None,None
    
    site = StarkSite()
    stark/service/sites.py
    # -*- coding: utf-8 -*-
    # @Time    : 2019/4/12 11:47
    # @Author  : xxx
    # @Email   : xxx@admin.com
    # @File    : stark.py
    # @Software: PyCharm
    
    from stark.service.sites import site,ModelStark
    from .models import *
    from django.utils.safestring import mark_safe
    from django.forms import ModelForm
    class BookModelForm(ModelForm):
        class Meta:
            model=Book
            fields="__all__"
            error_messages={
               "title":{ "required":" 该字段不能为空!"}
            }
    
    
    class BookConfig(ModelStark):
    
        def show_authors(self,obj=None,header=False):
            if header:
                return "作者信息"
            return " ".join([author.name for author in obj.authors.all()])
    
    
        list_display=["title","price","state","publish",show_authors]
        list_display_links=["title","price"]
    
        model_form_class=BookModelForm
    
        per_page_num=3
    
        search_fields=["title","price"]
    
        # action参数
        def patch_init(self, request, queryset):
            queryset.update(price=0)
    
        patch_init.desc = "价格初始化"
    
        actions = [patch_init, ]
    
        list_filter=["publish","authors","state"]
    
    
    
    
    
    
    site.register(Book,BookConfig)
    site.register(Publish)
    # print(site._registry)
    app01/stark.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
        <style>
             .filter_body {
                padding: 16px;
                margin: 40px;
                margin-bottom: -20px;
            }
    
            .filter_body_item {
                margin-bottom: 10px;
            }
    
            .filter_body .active {
                background-color: #000;
                color: white;
            }
        </style>
    </head>
    <body>
    <h3>查看数据</h3>
    
    <div class="container">
    
       <div class="row">
    
    
           <div class="panel panel-info">
    
            <div class="panel-heading">
                <h3 class="panel-title"></h3>
            </div>
          <div class="panel-body">
              <a href="{{ add_url }}" class="btn btn-primary">添加{{ table_name }}</a>
              {% if show_list.config_obj.search_fields %}
                  <form action="" method="get">
                      <div class="input-group pull-right" style=" 400px">
                          <input value="{{ show_list.config_obj.search_val|default:'' }}" type="text" name="q" class="form-control" placeholder="Search for...">
                          <span class="input-group-btn">
                            <button class="btn btn-primary">Search!</button>
    
                          </span>
                        </div>
                  </form>
              {% endif %}
    
            <div>
                  <div class="panel-default filter_body">
    
                    {% for field,links in show_list.config_obj.get_list_filter_links.items %}
                        <div class="filter_body_item">
                            <span class="btn btn-default btn-sm" style=" 100px">按{{ field }}筛选</span>
                            {% for link in links %}
                                {{ link|safe }}
                            {% endfor %}
                        </div>
                    {% endfor %}
    
                </div>
            </div>
    
          </div>
        </div>
    
    
    
    
    
    
           <form action="" method="post">
               {% csrf_token %}
                <div class="action">
                  <select class="form-control" name="action" id="" style=" 250px;display: inline-block;vertical-align: -2px;">
                         <option value="">-------------------------------------------</option>
                          {% for action in show_list.config_obj.get_action_dict %}
                              <option value="{{ action.name }}">{{ action.desc }}</option>
                          {% endfor %}
                          
                  </select>
                  <button class="btn btn-primary" style="margin-left: -4px">Go!</button>
              </div>
                <table class="table table-striped">
                <thead>
                     <tr>
                         {% for item in show_list.get_header %}
                            <th>{{ item }}</th>
                          {% endfor %}
                     </tr>
    
                </thead>
                <tbody>
                      {% for item in show_list.get_body %}
                      <tr>
                          {% for info in item %}
                          <td>{{ info }}</td>
                          {% endfor %}
                      </tr>
                      {% endfor %}
    
    
                </tbody>
           </table>
           </form>
    
           <div class="pull-right">
               {{ show_list.pagination.page_html|safe }}
           </div>
       </div>
    
    </div>
    
    </body>
    
    </html>
    stark/templates/stark/list_view.html
  • 相关阅读:
    原生小程序音频播放
    Vue定义全局过滤器filter
    系统扩展性之引入外部包
    oracle update join
    OAuth2
    oracle pl/sql
    MySQL同步工具otter的使用介绍(一)
    python批量安装apk
    mac brew安装redis
    antd 修改Modal的底部按钮颜色
  • 原文地址:https://www.cnblogs.com/linux985/p/11149397.html
Copyright © 2011-2022 走看看