• 10.19stark组件开发(三)


      2018-10-19 15:42:15

    2018-10-19 18:21:33

    我觉得现在主要是学一种解决问题的思路,也就是逻辑或者说是算法!!!!

    要有对代码的感触!要用面向对象对类进行封装!!Django源码写的就是很6

    明天看完stark 然后整理Django !!周末啦!

    过不久还得回学校!!!难得的在家清静!珍惜吧!

    越努力,越幸运!!!永远不要高估自己!!

    .model._meta的用法!

    通过字段获取QuerySet对象

    通过字段获取 app和表的名字!

    model_name = self.model._meta.model_name
    app_label = self.model._meta.app_label

    这次新增了自定义过滤功能!
    新学了上面两个知识点!
    在源码上都有相应的注释!很好看懂!
    不难就是有点绕!!

    server/stark.py
    from django.conf.urls import url
    from django.shortcuts import render, redirect
    from django.urls import reverse
    from django.utils.safestring import mark_safe
    from django.forms import ModelForm
    from stark.utils.page import Pagination
    from django.db.models import Q
    from django.db.models.fields.related import ForeignKey
    from django.db.models.fields.related import ManyToManyField
    import copy
    
    
    class ShowList(object):
        # 这是一个配置类的对象初始化
        def __init__(self, config, data_list, request):
            self.config = config
            self.data_list = data_list
            self.request = request
            # 分页
            data_count = self.data_list.count()
            current_page = int(self.request.GET.get("page", 1))
            base_path = self.request.path
            self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=3, pager_count=11,)
            self.page_data = self.data_list[self.pagination.start:self.pagination.end]
            # actions   获取actions这个配置类的列表
            self.actions = self.config.actions  # [patch_init,]
    
        # 处理filter字段连接
        def get_filter_linktags(self):
            """用了两次for循环,在算法上有点缀余!不过可以用类或函数封装只是懒-.-能力欠缺!"""
            print("list_filter:", self.config.list_filter)
            link_dic = {}
            for filter_field in self.config.list_filter:  # ["title","publish","authors",]
                params = copy.deepcopy(self.request.GET)
                cid = self.request.GET.get(filter_field, 0)
                print("filter_field", filter_field)  # "publish"
                # 通过_meta.get_field方法,获取该表名对象
                filter_field_obj = self.config.model._meta.get_field(filter_field)
    
                print("filter_field_obj", filter_field_obj)
                print(type(filter_field_obj))
                # print("rel...",filter_field_obj.rel.to.objects.all())
    
                # 判断一下 如果是多对多或一对多类型的
                if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                    # 拿到表的所有QuerySet对象
                    data_list = filter_field_obj.rel.to.objects.all()  # 【publish1,publish2...】
                else:
                    # 这个则是自定义过滤字段
                    data_list = self.config.model.objects.all().values("pk", filter_field)
                    print("data_list", data_list)
    
                temp = []
                # 处理 全部标签
                if params.get(filter_field):
                    # 如果url如果存在参数 则del
                    del params[filter_field]
                    temp.append("<a href='?%s'>全部</a>" % params.urlencode())
                else:
                    # 反之加上class 增加颜色
                    temp.append("<a  class='active' href='#'>全部</a>")
    
                # 处理 数据标签
                for obj in data_list:
                    # 循环列表中每个QuerySet的对象然后取到相应的值
                    if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                        pk = obj.pk
                        text = str(obj)
                        params[filter_field] = pk
                    else:  # data_list= [{"pk":1,"title":"go"},....]
                        pk = obj.get("pk")
                        text = obj.get(filter_field)
                        params[filter_field] = text
    
                    _url = params.urlencode()
                    if cid == str(pk) or cid == text:
                        link_tag = "<a class='active' href='?%s'>%s</a>" % (_url, text)
                    else:
                        link_tag = "<a href='?%s'>%s</a>" % (_url, text)
                    temp.append(link_tag)
    
                link_dic[filter_field] = temp
            return link_dic
    
        # 获取下拉框 用户配置的action_list
        def get_action_list(self):
            temp = []
            for action in self.actions:
                #  [{"name":""patch_init,"desc":"批量初始化"}]
               temp.append({
                   "name": action.__name__,
                   "desc": action.short_description
               })
            return temp
    
        # 构建表头
        def get_header(self):
            header_list = []
            print("header", self.config.new_list_play())
            # [checkbox,"pk","name","age",edit ,deletes]     【checkbox ,"__str__", edit ,deletes】
            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:
                        # header_list.append(field)
                        val = self.config.model._meta.get_field(field).verbose_name
                        header_list.append(val)
            return header_list
    
        # 构建表单数据
        def get_body(self):
            # 构建表单数据
            new_data_list = []
            for obj in self.page_data:
                temp = []
                for filed in self.config.new_list_play():  # ["__str__",]      ["pk","name","age",edit]
                    if callable(filed):
                        val = filed(self.config, obj)
                    else:
                        field_obj = self.config.model._meta.get_field(filed)
                        if isinstance(field_obj, ManyToManyField):
                            # getattr()仅取到Object, 然后.all() 则可以取到对象
                            ret = getattr(obj, filed).all()
                            t = []
                            for obj in ret:
                                t.append(str(obj))
                            val = ",".join(t)
    
                        else:
                            val = getattr(obj, filed)
                            if filed in self.config.list_display_links:
                                # "app01/userinfo/(d+)/change"
                                _url = self.config.get_change_url(obj)
                                val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
    
                    temp.append(val)
    
                new_data_list.append(temp)
            return new_data_list
    
    
    class ModelStark(object):
        # 默认的list_play[]
        list_display = ["__str__", ]
        list_display_links = []
        modelform_class = None
        search_fields = []
        actions = []
        list_filter = []
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        # 默认的批量删除action
        def patch_delete(self, request, queryset):
            queryset.delete()
        patch_delete.short_description = "批量删除"
    
        # 配置表头: 删除 编辑,复选框
        def edit(self, obj=None, header=False):
            """编辑"""
            if header:
                return "操作"
            # return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
            _url = self.get_change_url(obj)
            return mark_safe("<a href='%s'>编辑</a>" % _url)
    
        def deletes(self, obj=None, header=False):
            """删除"""
            if header:
                return "操作"
            # return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
            _url = self.get_delete_url(obj)
            return mark_safe("<a href='%s'>删除</a>" % _url)
    
        def checkbox(self, obj=None, header=False):
            """复选框"""
            if header:
                return mark_safe('<input id="choice" type="checkbox">')
            # value的值不能写死,
            return mark_safe('<input class="choice_item" type="checkbox" name="selected_pk" value="%s">' % obj.pk)
    
        # 获取配置类的表头信息
        def get_modelform_class(self):
            """获取表的配置类"""
            if not self.modelform_class:
                # 如果表的配置类为空
                class ModelFormDemo(ModelForm):
                    class Meta:
                        model = self.model
                        fields = "__all__"
                        labels = {
                            ""
                        }
                return ModelFormDemo
            else:
                return self.modelform_class
    
        # 添加的视图函数
        def add_view(self, request):
            ModelFormDemo = self.get_modelform_class()
            if request.method == "POST":
                form = ModelFormDemo(request.POST)
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url())
    
                return render(request, "add_view.html", locals())
    
            form = ModelFormDemo()
    
            return render(request, "add_view.html", locals())
    
        # 删除的视图函数
        def delete_view(self, request, id):
            url = self.get_list_url()
            if request.method == "POST":
                self.model.objects.filter(pk=id).delete()
                return redirect(url)
            return render(request, "delete_view.html", locals())
    
        # 编辑的视图函数
        def change_view(self, request, id):
            ModelFormDemo = self.get_modelform_class()
            edit_obj = self.model.objects.filter(pk=id).first()
            if request.method == "POST":
                form = ModelFormDemo(request.POST, instance=edit_obj)
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url())
                return render(request, "add_view.html", locals())
            form = ModelFormDemo(instance=edit_obj)
            return render(request, "change_view.html", locals())
    
        # 搜索的视图函数
        def get_serach_conditon(self, request):
            key_word = request.GET.get("q", "")
            self.key_word = key_word
            search_connection = Q()
            if key_word:
                # self.search_fields # ["title","price"]
                search_connection.connector = "or"
                # 用Q的这种添加方法可以添加字符串
                for search_field in self.search_fields:
                    # search_field+"__contains"  ---->  title__contains="o"   就是title字段里面包含字母o的
                    search_connection.children.append((search_field + "__contains", key_word))
            return search_connection
    
        # 过滤filter的视图函数
        def get_filter_condition(self, request):
            filter_condition = Q()
            for filter_field, val in request.GET.items():
                if filter_field in self.list_filter:
                    filter_condition.children.append((filter_field, val))
            return filter_condition
    
        # 查看的视图函数
        def list_view(self, request):
            if request.method == "POST":  # action
                print("POST:", request.POST)
                action = request.POST.get("action")  # patch_init
                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
            # 获取search的Q对象
            search_connection = self.get_serach_conditon(request)
    
            # 获取filter构建Q对象
            filter_condition = self.get_filter_condition(request)
    
            # 筛选获取当前表所有数据
            data_list = self.model.objects.all().filter(search_connection).filter(filter_condition)  # 【obj1,obj2,....】
    
            # 按这ShowList展示页面
            showlist = ShowList(self, data_list, request)
    
            # 构建一个查看URL
            add_url = self.get_add_url()
            return render(request, "list_view.html", locals())
    
        #  获取用户配置类里面的list_play[]
        def new_list_play(self):
            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
    
        # 获取用户配置类里面的actions 这个列表
        def new_actions(self):
            temp=[]
            temp.append(ModelStark.patch_delete)
            temp.extend(self.actions)
            return temp
    
        """把url进行反向解析,解耦到各自的函数中,函数中直接返回了对应的url"""
        # 获取修改页面的url
        def get_change_url(self, obj):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
    
            return _url
    
        # 获删除改页面的url
        def get_delete_url(self, obj):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))
    
            return _url
    
        # 获取添加页面的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
    
        # 获取查看页面的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
    
        # 二级url分发函数
        def get_urls_2(self):
            temp = []
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name)))
            temp.append(url(r"^(d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name)))
            temp.append(url(r"^(d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name)))
            temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
            return temp
    
        @property
        def urls_2(self):
            print(self.model)
            return self.get_urls_2(), None, None
    
    
    class StarkSite(object):
        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)
    
        # 一级分发url函数
        def get_urls(self):
            temp = []
            for model, stark_class_obj in self._registry.items():
                model_name = model._meta.model_name
                app_label = model._meta.app_label
                # 分发增删改查
                temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))
    
                '''
                url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
                url(r"^app01/book/",ModelStark(Book).urls_2), 
    
    
                '''
            return temp
    
        @property
        def urls(self):
    
            return self.get_urls(), None, None
    
    
    # 创建stark的一个单例对象
    site = StarkSite()

    app01/stark.py

    from stark.service.stark import site,ModelStark
    
    from django.urls import reverse
    from .models import *
    
    
    from django.utils.safestring import mark_safe
    
    from django.forms import ModelForm
    from django.forms import widgets as wid
    
    
    class BookModelForm(ModelForm):
        class Meta:
            model = Book
            fields = "__all__"
    
            labels={
                "title":"书籍名称",
                "price":"价格"
            }
    
    from django.shortcuts import HttpResponse
    
    class BookConfig(ModelStark):
        # 自定义展示列表
        list_display = ["title","price","publishDate","publish","authors"]
        # 自定义设置字段为连接
        list_display_links = ["title"]
        modelform_class=BookModelForm
        # 自定义搜索字段
        search_fields=["title","price"]
    
        def patch_init(self, request, queryset):
            print(queryset)
            queryset.update(price=123)
    
            return HttpResponse("批量初始化OK")
    
        patch_init.short_description = "批量初始化"
    
        # 自定义处理函数
        actions = [patch_init]
    
        # 自定义筛选字段
        list_filter=["title","publish","authors",]
    
    
    site.register(Book,BookConfig)
    
    
    
    
    
    
    site.register(Publish)
    site.register(Author)
    site.register(AuthorDetail)

    list.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
        <script src="/static/js/jquery-1.12.4.min.js"></script>
    
        <style>
            .filter a{
                text-decoration: none;
                color: grey;
            }
    
            .active{
                color: rebeccapurple!important;
            }
        </style>
    </head>
    <body>
    
    <h4>数据列表</h4>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-9">
                <a href="{{ add_url }}" class="btn btn-primary">添加数据</a>
    
                {% if showlist.config.search_fields %}
                         <form action="" class="pull-right">
                            <input class="form-control" style="display: inline-block;200px" type="text" name="q" value="{{ showlist.config.key_word }}"><button class="btn btn-default">search</button>
                        </form>
                {% endif %}
    
                <form action="" method="post">
                        {% csrf_token %}
                        <select name="action"  class="form-control" id="" style=" 200px;margin: 8px 2px;display: inline-block;vertical-align: -1px">
                             <option value="">---------------</option>
                            {% for item in showlist.get_action_list %}
                                <option value="{{ item.name }}">{{ item.desc }}</option>
                            {% endfor %}
    
                        </select><button type="submit" class="btn btn-success">Go</button>
                        <table class="table table-bordered table-striped">
                            <thead>
                                 <tr>
                                     {% for item in showlist.get_header %}
                                       <th>{{ item }}</th>
                                     {% endfor %}
    
                                 </tr>
    
                            </thead>
                            <tbody>
                                 {% for data in showlist.get_body %}
    
                                  <tr>
                                      {% for item in data %}
                                       <td>{{ item }}</td>
                                      {% endfor %}
    
                                  </tr>
                                 {% endfor %}
    
                            </tbody>
                        </table>
                            <nav class="pull-right">
                                <ul class="pagination">
                                   {{ showlist.pagination.page_html|safe }}
                                </ul>
                            </nav>
    
                </form>
            </div>
    
            <div class="col-md-3">
                <div class="filter">
                    <h4 style="">Filter</h4>
                    {% for filter_field,linktags in showlist.get_filter_linktags.items %}
                       <div class="well">
                             <p>By {{ filter_field.upper }}</p>
                             {% for link in linktags %}
                             <p>{{ link|safe }}</p>
                             {% endfor %}
                       </div>
                    {% endfor %}
    
    
                </div>
            </div>
        </div>
    </div>
    
    
    
    <script>
    
       $("#choice").click(function () {
    
         if($(this).prop("checked")){
               $(".choice_item").prop("checked",true)
         }else {
               $(".choice_item").prop("checked",false)
         }
    
       })
    
    </script>
    </body>
    </html>

    贴上笔记

    stark
    
    
       分页
           分页组件
           保存搜索条件
       
       search
           
       action
       
       
       filter:
          
          
                print("filter_field",filter_field) # "publish"
                filter_field_obj=self.config.model._meta.get_field(filter_field)
                print("filter_field_obj",filter_field_obj)
                print(type(filter_field_obj))
                from django.db.models.fields.related import ForeignKey
                from django.db.models.fields.related import ManyToManyField
                print("rel...",filter_field_obj.rel.to.objects.all())
    self.config.model._meta.get_field(filter_field) 通过字符串找到拿到该名字表的对象
    只要属性里面有 (to=) 就可以用
    filter_field_obj.rel.to 拿到关联表 class对象
  • 相关阅读:
    一个简单实现的string类
    Python基础(二)
    Python基础(一)
    区块链初探
    某电商平台开发记要——客服系统
    某电商平台开发记要
    Upload files to aliyunOSS with bootstrap-fileinput
    jquery.validate[.unobtrusive]和Bootstrap实现tooltip错误提示
    PostgreSQL笔记
    天冷了,那些树还好吗?
  • 原文地址:https://www.cnblogs.com/zhen1996/p/9818049.html
Copyright © 2020-2023  润新知