zoukankan      html  css  js  c++  java
  • crm项目stark组件

    ###############  admin基本认识和常用的定制功能    ###############

    stark组件
    
    对admin的基本认识
    1,就是一个app,嵌入到了django里面,你可以在settings中看到
    2,就是一个web后台管理工具,使用它可以更加的方便
    3,通常我们在生成项目时会在 urls.py 中自动设置好url访问路径
    urlpatterns = [
        url(r'^admin/', admin.site.urls)
    ]
    4,启动开发服务器,然后在浏览器中访问 http://127.0.0.1:8000/admin/
    5,你通过命令 python manage.py createsuperuser 来创建超级用户
    6,使用的时候先注册数据模型:admin.site.register(models.UserInfo)
    7,点击进入会展示数据,默认就是把这个对象打印出来,复杂的,需要定制的,需要利用ModelAdmin进行操作
    class CourseConfig(admin.ModelAdmin):
        pass
    admin.site.register(Course,CourseConfig)
    
    
    #######################
    
    class UserInfoConfig(admin.ModelAdmin):
        list_display=["id","name","username","password","email","depart"]  # 定制显示的列。不能放多对多的字段
        list_display_links=["username"]  # 定制列可以点击跳转到详情页面,
        list_filter=["depart"]  # 定制右侧快速筛选。
        list_editable=["email"]  # 可以编辑的列,可以编辑就不能是list_display_links字段了,
        search_fields=["username"]  # 模糊搜索的功能
    
        # 定义action的函数
        def func(self,request,queryset):
            print(request,queryset)
            queryset.update(email="1212@qq.com")
        func.short_description = "批量初始化操作"
    
        actions=[func,]  # 定制action中的操作
        fields=["username"]  # 查看详情和新增页面,可以控制显示的字段
        ordering=["-id"]  # 数据排序规则,倒序在字段前面加符号,
    
    
    admin.site.register(UserInfo,UserInfoConfig)

    ###############  admin的url设计的基础知识点   ###############

    admin的url是怎么设计的,这是核心,
    urlpatterns = [
        url(r'^admin/', admin.site.urls),  # 为什么这一句能能够生成多条url,
    ]

    第一个知识点,url的嵌套使用

    def yuan(request):
        return HttpResponse("Yuan")
    
    
    def test01(request):
        return HttpResponse("test01")
    
    
    def test02(request):
        return HttpResponse("test02")
    
    
    def test03(request):
        return HttpResponse("test03")
    
    
    def test04(request):
        return HttpResponse("test04")
    
    
    def test05(request):
        return HttpResponse("test05")
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^yuan/', ([
                            url(r'^test01/', ([
                                                  url(r'^test04/', test04),  # http://127.0.0.1:8000/yuan/test01/test04/
                                                  url(r'^test05/', test05),
                                              ], None, None)),
                            url(r'^test02/', test02),
                            url(r'^test03/', test03),
                        ], None, None))
    ]

    第二个知识点:单例模式,

    # 单例模式
    
    # 一个类只允许实例一个对象
    
    # class Singleton(object):
    #     _instance = None
    #     def __new__(cls, *args, **kw):
    #         if not cls._instance:
    #             cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
    #         return cls._instance
    #
    # class MyClass(Singleton):
    #     a = 1
    #
    #
    # one = MyClass()
    # one.a=3
    #
    # two = MyClass()
    # print(two.a)  # 这个地方就是3,因为one和two指向的同一个内存空间,one改掉了a=3,所以two取值的时候就是3
    #
    # # print(one==two)
    # # print(id(one),id(two))
    
    
    
    # 第二种方法
    ###########################
    # 第一个文件
    class My_Singleton(object):
        x =12
        def foo(self):
            print(self.x)
    my_singleton = My_Singleton()  # 这是一个关键的一步
    
    print("OK")
    
    ###################
    # 第二个文件
    from mysingleton import my_singleton
    def foo():
        print(id(my_singleton))
    ############
    # 第三个文件
    from mysingleton import my_singleton,My_Singleton
    
    # a=My_Singleton()
    # b=My_Singleton()
    #
    # print(id(a))
    # print(id(b))  # 这是拿的类对象,而不是实例对象,所以,这两个不一样,
    
    print(id(my_singleton))
    from mysingleton import my_singleton
    print(id(my_singleton))
    from func import *
    foo()  # 这三次都是拿的实例对象,所以id的结果都是一样的,

    ############### admin的url设计    ###############

    第一个注册:

    # 注册
    
    self._registry = {}
    self._registry[model] = admin_class(model, self)
    # 注册的时候,是定义了一个字典,然后以model表为键,以对应的自定义类为值,生成对应的字典,

    第二个url设置

    def add(request):
        return HttpResponse("add")
    def delete(request,id):
        return HttpResponse("delete")
    def change(request,id):
        return HttpResponse("change")
    def list_view(request):
        return HttpResponse("list_view")
    
    
    def get_urls2():
    
        temp=[]
        temp.append(url(r"^add/",add))
        temp.append(url(r"^(\d+)/delete/",delete))
        temp.append(url(r"^(\d+)/change/",change))
        temp.append(url(r"^$",list_view))
        print("temp2",temp)
        # [
        # <RegexURLPattern None ^add/>,
        # <RegexURLPattern None ^(\d+)/delete/>,
        # <RegexURLPattern None ^(\d+)/change/>,
        # <RegexURLPattern None ^$>
        # ]
        return temp
    
    def get_urls():
    
    
        temp=[]
        print("_registry",admin.site._registry)
    
        for model,admin_class_obj in admin.site._registry.items():
             print("model",model) # 所有的注册模型表
    
             # < class 'app01.models.Book'>----->     "book"  "app01"
             # < class 'app01.models.Room'>----->     "room"  "app01"
             print("===>",model._meta.model_name)
             print("===>",model._meta.app_label)
    
             model_name=model._meta.model_name  # 对应的model表的名字
             app_label=model._meta.app_label  # 对应的app名字
             temp.append(url(r"%s/%s/"%(app_label,model_name),(get_urls2(),None,None)))
        print("temp",temp)
        """
        [
        <RegexURLResolver <RegexURLPattern list> (None:None) auth/group/>, 
        <RegexURLResolver <RegexURLPattern list> (None:None) auth/user/>, 
        <RegexURLResolver <RegexURLPattern list> (None:None) crm/userinfo/>
        ]
        """
    
        return temp
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^yuan/', (get_urls(), None, None))
    ]

    ###############  模仿admin-stark组件的url设计    ###############

    class ModelStark(object):
    
        def __init__(self,model,site):
            self.model=model  # 谁调用的就是那个表
            self.site=site
    
        def add_view(self, request):
            return HttpResponse("add_view")
    
        def change_view(self, request, id):
            return HttpResponse("change_view")
    
        def delete_view(self, request, id):
            return HttpResponse("delete_view")
    
        def list_view(self, request):
            return HttpResponse("list_view")
    
        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))
            temp.append(url(r"^(\d+)/delete/", self.delete_view))
            temp.append(url(r"^(\d+)/change/", self.change_view))
            temp.append(url(r"^$", self.list_view))
    
            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)  # 括号内的两个参数,就是ModelStark默认的两个参数,self就是site
    
    
        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
    
    site=StarkSite()  # 单例模式

    ##############  stark组件需要实现的功能    ###############

    在完成了注册和url设计之后,stark组件需要完成什么功能
    
    1,查询页面
    1.1 表头展示,可以定制展示的列,
    1.2 表内容展示,删除 编辑,复选框的功能
    1.3 查询功能,可以定义查询的字段,
    1.4 action功能,可以定制批量操作
    1.5 筛选功能,可以定制筛选的字段,
    1.6 分页功能
    这是最为复杂的部分,
    
    
    2,新增页面
    2.1 一个重要的pop功能,
    
    
    3,删除页面
    这个简单
    
    4,编辑页面,
    这个简单,和新增页面很相似,只需要把要编辑的数据带到页面展示,
    
    
    整个重写,使用到了
    1,django
    2,admin
    3,前端,js,html,bootstrap,jQuery,

    ##############  stark-service    ###############

    # by luffycity.com
    from django.conf.urls import url
    
    from django.shortcuts import HttpResponse,render,redirect
    from django.urls import reverse
    from django.db.models import Q
    from django.utils.safestring import mark_safe
    
    from stark.utils.page import  Pagination
    from django.db.models.fields.related import ManyToManyField,ForeignKey
    class ShowList(object):
        def __init__(self,config,data_list,request):
            self.config=config  # 这里的config就是用来接收传递的modelstark类的,下面就可以使用config调用modelstark里面的方法了,
            self.data_list=data_list  # 这个datalist是需要展示的数据
            self.request=request  # 为什么需要传递request?因为需要在这个里面获取page参数,是第几页
            #分页
            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=10, pager_count=11, )
            self.page_data=self.data_list[self.pagination.start:self.pagination.end]
    
            # actions
            self.actions=self.config.new_actions() # [patch_init,] # 获取modelstark中配置的action列表,
    
    
        def get_filter_linktags(self):
            print("list_filter:",self.config.list_filter)
            link_dic={}  # 格式是{筛选字段1:筛选值1,筛选字段2:筛选值2}
            import copy
    
            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)  # 这是获取到前端拼接的id,
    
                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)
    
                if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
                     data_list=filter_field_obj.rel.to.objects.all()# 【publish1,publish2...】
                     # filter_field_obj.rel.to,这种特殊写法,只有字段有关联表的时候才有意义,一对多,和多对多的,
                else:
                     data_list=self.config.model.objects.all().values("pk",filter_field)
                     print("data_list",data_list)
    
    
                temp=[]
                # 处理全部标签
                if params.get(filter_field):  # filter_field 这是筛选的字段,如果有筛选值,就删掉,
                    del params[filter_field]
                    temp.append("<a href='?%s'>全部</a>"%params.urlencode())
                else:
                    temp.append("<a  class='active' href='#'>全部</a>")
    
                # 处理数据标签
                for obj in data_list:
                    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"},....]
                        print("========")
                        pk=obj.get("pk")
                        text=obj.get(filter_field)
                        params[filter_field] =text  # 处理单表查询
    
    
                    _url=params.urlencode()
                    if cid==str(pk) or cid==text:  # 这是为了实现点击选中的标签,展示深蓝色,active
                         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
    
    
        def get_action_list(self):  # 拿到action操作,放到页面去渲染
            temp=[]
            for action in self.actions:  # 这是配置的action列表,循环这个列表,每一个action就是每一个函数,
               temp.append({
                   "name":action.__name__,  # 获取函数的名字,作为值
                   "desc":action.short_description  # 获取函数的描述,作为展示short_description,这是函数的一个动态属性
               })  #  [{"name":""patch_init,"desc":"批量初始化"}]
    
            print("temp",temp)
            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__)  # field.__name__函数的名字
                    val = field(self.config, header=True)  # header=True,header默认是false,这个再去拿值的之后就会拿到汉字了
                    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  # 这是获取到了表里面的字段,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):  # callable判断是否是一个可调用的,如果是一个字符串就是False,如果是一个方法就是true
                        print("obj-----:",obj)
                        val = filed(self.config, obj)
                    else:
                        try:
                            field_obj=self.config.model._meta.get_field(filed)
                            if isinstance(field_obj,ManyToManyField):  # 多对多的时候如何展示数据
                                ret = getattr(obj,filed).all()  # 这是获取到多对多的情况,可能会有多个值,
                                t=[]
                                for mobj in ret:
                                    t.append(str(mobj))
                                val=",".join(t)  # 拼成逗号隔开的样子,展示出来,
                            else:
                                print("====>",field_obj.choices)
                                if field_obj.choices:
                                    val = getattr(obj, "get_"+filed+"_display")  # 这个obj是每一条数据,filed是每一条数据应该显示的字段,
                                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))
    
                        except Exception as e:
                            val = getattr(obj, filed)
    
    
                    temp.append(val)
    
                new_data_list.append(temp)
            return new_data_list
    
    '''
            [
                [1,"alex",12],
                [1,"alex",12],
                [1,"alex",12],
                [1,"alex",12],
    
                     ]
    
            '''
    
    class ModelStark(object):
    
        list_display=["__str__",]
        list_display_links=[]
        modelform_class=None
        search_fields=[]
        actions = []
        list_filter=[]
    
    
        def patch_delete(self, request, queryset):
            """批量删除"""
            queryset.delete()
    
        patch_delete.short_description = "批量删除"
    
        def __init__(self,model,site):
            self.model=model
            self.site=site
    
    
        # 删除 编辑,复选框
        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">')
    
            return mark_safe('<input class="choice_item" type="checkbox" name="selected_pk" value="%s">'%obj.pk)
        # 这一步非常的重要,因为在配合action去取到选中的数据,
    
        def get_modelform_class(self):
            """如果客户定制了用客户定制的,如果没有没有定制使用默认的,"""
            if not self.modelform_class:
                from django.forms import ModelForm  # 这个涉及到了form表单的内容,
                from django.forms import widgets as wid
                class ModelFormDemo(ModelForm):  # 可以在每一个app中的stark里面,对每一个model进行重写这个类,就可以定制了
                    class Meta:
                        model = self.model
                        fields = "__all__"
                        labels={
                            ""
                        }  # 可以在每一个app中的stark里面,labels可以对字段进行设置汉字,格式是键:值的方式,
                return ModelFormDemo
            else:
                return self.modelform_class
    
        def get_new_form(self,form):
            """这是pop弹出的窗口对象的方法,"""
            for bfield in form:
                from django.forms.boundfield import BoundField
                print(bfield.field) # 字段对象
                print("name",bfield.name)  # 字段名(字符串)
                print(type(bfield.field)) # 字段类型
                from django.forms.models import ModelChoiceField
                if isinstance(bfield.field,ModelChoiceField):
                    bfield.is_pop=True  # 这是动态给多对多的字段加属性
                    # 怎么拿到关联表的名字,和它所属的APP呢,
                    print("=======>",bfield.field.queryset.model) # 一对多或者多对多字段的关联模型表
                    related_model_name=bfield.field.queryset.model._meta.model_name
                    related_app_label=bfield.field.queryset.model._meta.app_label
    
    
                    _url=reverse("%s_%s_add"%(related_app_label,related_model_name))  # 反向解析进入对应的添加页面,
                    bfield.url=_url+"?pop_res_id=id_%s"%bfield.name  # 动态加字段,字段名(字符串)
    
            return form
    
    
        def add_view(self, request):
            ModelFormDemo = self.get_modelform_class()  # 这是返回一个类
            form = ModelFormDemo()  # 使用这个类实例化一个对象出来,
    
            form=self.get_new_form(form)
    
            if request.method=="POST":  # 点击提交按钮要做的事情
                form = ModelFormDemo(request.POST)
                if form.is_valid():
                    obj=form.save()  # 这都是form表单的功能,校验通过就保存到数据库,
    
                    pop_res_id=request.GET.get("pop_res_id")
    
                    if pop_res_id:
                        res ={"pk":obj.pk,"text":str(obj),"pop_res_id":pop_res_id}
                        import json
                        return render(request, "pop.html", {"res":res})
                    else:
                        return redirect(self.get_list_url())
            print("locals()",locals())
            """
            {
            'form': <ModelFormDemo bound=False, valid=Unknown, fields=(qq;name;gender;education;graduation_school;major;experience;work_status;company;salary;source;referral_from;course;status;consultant;recv_date;last_consult_date)>,
             'ModelFormDemo': <class 'stark.service.stark.ModelStark.get_modelform_class.<locals>.ModelFormDemo'>, 
             'request': <WSGIRequest: GET '/stark/crm/customer/add/'>, 
             'self': <crm.stark.CusotmerConfig object at 0x000000000D1FBC18>
             }
            """
            return render(request, "add_view.html", locals())  # Python 的内建函数 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()  # 获取这个类,可以控制展示的字段等信息
            print("=====id",id)
            edit_obj = self.model.objects.filter(pk=id).first()
    
            if request.method=="POST":
                form = ModelFormDemo(request.POST,instance=edit_obj)  # 这个instance也是djangoform表单的功能,
                if form.is_valid():
                    form.save()
                    return redirect(self.get_list_url()) # 提交之后返回到列表页
    
                print("locals()",locals())
                return render(request, "change_view.html", locals())
    
            print("***********",edit_obj)
            form = ModelFormDemo(instance=edit_obj)  # 和新增页面一样,只需要加一个instance
            form = self.get_new_form(form)
    
            return render(request, "change_view.html", locals())
    
        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
    
        def new_actions(self):
            temp=[]
            temp.append(ModelStark.patch_delete)
            temp.extend(self.actions)  # 这个里面就可能会有自定义的action,这样组成一个新的action,
    
            return temp
    
    
        def get_change_url(self,obj):  # 这一个功能多个地方使用,所以封装到一个方法里面,
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            print("obj===========",obj)
            # from django.urls import reverse,这个是django中的一个工具
            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))  # 反向解析,args,是传入的id字段,
    
            return _url
    
        def get_delete_url(self, obj):
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))
    
            return _url
    
        def get_add_url(self):
    
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            _url = reverse("%s_%s_add" % (app_label, model_name))
    
            return _url
    
        def get_list_url(self):
    
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
    
            _url = reverse("%s_%s_list" % (app_label, model_name))
    
            return _url
    
        def get_serach_conditon(self,request):
            key_word = request.GET.get("q","")
            self.key_word=key_word  # 这是给modelstark加一个实例对象,然后在查询之后就可以直接把查询内容渲染到页面了,通过showlist.config.keyword
    
            search_connection = Q()  # 默认这个是空的条件
            if key_word:
                # self.search_fields # ["title","price"]
                search_connection.connector = "or"  # 这是orm使用q查询的另外一种方法,
                for search_field in self.search_fields:
                    search_connection.children.append((search_field + "__contains", key_word))
            print("search_connection",search_connection)
            return search_connection
    
    
        def get_filter_condition(self,request):
            filter_condition=Q()
    
            for filter_field,val in request.GET.items():# courserecord=2
                 if filter_field !="page":  # 把page这个去掉,不加入过滤
                    filter_condition.children.append((filter_field,val))
    
            return filter_condition
    
    
        def list_view(self, request):
            if request.method=="POST":  # 这个post请求,就是在处理action的提交(go)
                print("POST:",request.POST)  # 把input框的值传过来了,把select下面的选中的值传过来,可以在post中取到action和selected_pk
                action=request.POST.get("action") # patch_init
                selected_pk=request.POST.getlist("selected_pk")
                action_func=getattr(self,action)  # 反射,从self中去找action,action这是一个变量,是对应的点击的哪一个函数
                # self,是配置类,如果没有找到就去父类找,
                queryset=self.model.objects.filter(pk__in=selected_pk)
                ret=action_func(request,queryset)  # 调用对应的函数操作,
    
                #return ret
    
            # 获取serach的Q对象
            search_connection=self.get_serach_conditon(request)
    
            # 获取filter构建Q对象
    
            filter_condition=self.get_filter_condition(request)
    
            print("search_connection",search_connection,"filter_condition",filter_condition)
    
            # 筛选获取当前表所有数据
            data_list=self.model.objects.all().filter(search_connection).filter(filter_condition)            # 【obj1,obj2,....】
    
            print("data_list",data_list)
            # 按这ShowList展示页面
            showlist=ShowList(self,data_list,request)  # 实例化一个showlist,这个self就是现在的modelstark类,需要作为一个参数传递,
    
            # 构建一个查看URL
            add_url=self.get_add_url()
            return render(request, "list_view.html", locals())
    
    
    
        def extra_url(self):
    
            return []
    
        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)))  # 这个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)))
    
            # 扩展url
            temp.extend(self.extra_url())
    
            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)  # 括号内的两个参数,就是ModelStark默认的两个参数,self就是site
    
    
        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
    
    site=StarkSite()

    ###############  stark-分页      ###############

    """
    自定义分页组件
    
    """
    
    
    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)
    
    
    
    
    
    # class Pagination(object):
    #
    #     def __init__(self, data_num, current_page, url_prefix,params, per_page=10, max_show=4):
    #         """
    #         进行初始化.
    #         :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)
    #             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)

    ###############  查看列表页面    ###############

    <!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>
    {#搜索框,只有配置了search_fields才会展示#}
                {% if showlist.config.search_fields %}
    {#没有写method,默认是一个get请求#}
                         <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>
    {# get_action_list的结果:[{"name":""patch_init,"desc":"批量初始化"}]#}
    {#每一个item就是一个字段,#}
                            {% 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">
                {% if showlist.config.list_filter %}
                         <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>
                {% endif %}
    
    
            </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>

    ###############  修改页面    ###############

    <!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>
    
              input,select {
                display: block;
                 100%;
                height: 34px;
                padding: 6px 12px;
                font-size: 14px;
                line-height: 1.42857143;
                color: #555;
                background-color: #fff;
                background-image: none;
                border: 1px solid #ccc;
                border-radius: 4px;
                -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
                -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
                transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
            }
    
            .error{
                color: red;
            }
    
        </style>
    </head>
    <body>
    
    
    <h3>编辑页面</h3>
    
    {% include 'form.html' %}
    
    </body>
    </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">
    </head>
    <body>
    
    
    <h3>删除页面</h3>
    
    
    <form action="" method="post">
        {% csrf_token %}
        <button>确认删除?</button>
        <a href="{{ url }}">取消</a>
    </form>
    
    </body>
    </html>

    ###############  抽象form表单部分    ###############

    <div class="container">
        <div class="row">
            <div class="col-md-6 col-xs-8 col-md-offset-3">
                 <form action="" method="post" novalidate>
                    {% csrf_token %}
                    {% for field in form %}
                    <div style="position: relative">
                        <label for="">{{ field.label }}</label>
                        {{ field }} <span class=" error pull-right">{{ field.errors.0 }}</span>
    
                        {% if field.is_pop %}
    {#如果是一个一对多多对多的字段,需要在字段的右侧放一个加号,需要弹出新的页面,来添加数据#}
    {#position,设置标签的位置,父标签是相对定位,子标签是绝对定位,#}
    {#你怎么知道一个字段是一对多多对多的字段??,根据字段的类型,如果是一对多,多对多,加一个is_pop的字段为true#}
    {#绑定一个点击事件,点击要跳转到一个url,#}
                           <a onclick="pop('{{ field.url }}')" style="position: absolute;right: -30px;top: 20px"><span style="font-size: 28px">+</span></a>
                        {% endif %}
                    </div>
                    {% endfor %}
    
                     <button type="submit" class="btn btn-default pull-right">提交</button>
                 </form>
            </div>
        </div>
    </div>
    <script>
        function pop(url) {
            {#点击之后弹出一个窗口,路径是传入的url,#}
            window.open(url,"","width=600,height=400,top=100,left=100")
        {#top=100,left=100,控制弹出窗口的位置,大小,#}
        }
    </script>

    ###############  新增页面   ###############

    <!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>
    
              input,select {
                display: block;
                 100%;
                height: 34px;
                padding: 6px 12px;
                font-size: 14px;
                line-height: 1.42857143;
                color: #555;
                background-color: #fff;
                background-image: none;
                border: 1px solid #ccc;
                border-radius: 4px;
                -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
                -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
                transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
            }
    
            .error{
                color: red;
            }
    
        </style>
    </head>
    <body>
    
    
    <h3>添加页面</h3>
    
    {% include 'form.html' %}
    
    
    <script>
       function pop_response (pk,text,id) {
           {#添加内容之后,返回的时候能自动带回到页面,#}
           console.log(pk,text,id);
    
    
            // 选择哪一个select标签
            // option的文本值和value值
    
           var $option=$('<option>');  //  <option></option>
           $option.html(text); //  <option>南京出版社</option>
           $option.val(pk);     //  <option value=111>南京出版社</option>
           $option.attr("selected","selected") ;   //  <option value=111>南京出版社</option>
           $("#"+id).append($option)
    
       }
    </script>
    
    
    
    </body>
    </html>

    ###############  pop页面    ###############

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    
    <script>
    {#这个pop_response是自己定义的#}
        window.opener.pop_response('{{ res.pk }}',"{{ res.text }}",'{{ res.pop_res_id }}')
        window.close()
    </script>
    
    </body>
    </html>

    ###############  admin    ###############

    ###############  admin    ###############

  • 相关阅读:
    C算法编程题系列
    C算法编程题(七)购物
    C算法编程题(六)串的处理
    C算法编程题(五)“E”的变换
    C算法编程题(四)上三角
    C算法编程题(三)画表格
    C算法编程题(二)正螺旋
    C算法编程题(一)扑克牌发牌
    我的编程开始(C)
    T-Sql学习系列完结
  • 原文地址:https://www.cnblogs.com/andy0816/p/12157042.html
Copyright © 2011-2022 走看看