• stark——查看页面编辑删除按钮


    一、数据列表

      设计查页面,主要展示两部分内容,表头部分和数据部分, 表头通过遍历list_display和默认要显示的编辑和删除字段。

    1、数据构建

    (1)service/stark.py,后台数据构建

    class ModelStark(object):
        """定制配置类"""
        list_display = []
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
        '''省略其他代码'''
    
        def list_view(self, request):
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            new_data_list = []
            for obj in data_list:   # 所查询表中的一个个对象
                temp = []
                for field in self.list_display:  # field为一个个字段字符串
                    val = getattr(obj, field)   # obj.name  obj.age
                    temp.append(val)
              new_data_list.append(temp)
    
            return render(request, "list_view.html", locals())
            
        '''省略其他代码'''
    

    (2)list_view.html模板展示

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    </head>
    <body>
    <h4>数据列表</h4>
    <div class="container">
        <div class="row">
            <div class="col-md-9">
                <table class="table table-bordered table-striped">
                    <thead></thead>
                    <tbody>
                        {% for data in new_data_list %}
                            <tr>
                                {% for item in data %}
                                    <td>{{ item }}</td>
                                {% endfor %}
                            </tr>
                        {% endfor %}
    
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    </body>
    </html>
    

      显示效果:

      

    注意:

    (1)由于UserConfig类是ModelStark类的子类,且两边都有list_display变量。

      如果list_display有值就按里面的字段展示,如果没有值按照默认的obj展示。

    app01/stark.py:

    # 自定义配置类
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        list_display = ["pk", "name", "age"]
    

      根据父类子类关系,从调用者类里去找x,如果调用者中没有x,去父类找:

    class A(object):
        x = 12
    
        def func(self):
            print(self.x)
    
    class B(A):
        x = 5
    
    
    b = B()
    b.func()  # 5
    

    (2)字符串找对象的属性,反射

    data_list = self.model.objects.all()  # 拿到对应表所有的对象
    new_data_list = []
    for obj in data_list:   # 所查询表中的一个个对象
        temp = []
        for field in self.list_display:  # field为一个个字段字符串
            val = getattr(obj, field)   # obj.name  obj.age
    
            temp.append(val)
    
      new_data_list.append(temp)
     

      字符串不是变量名称,无法进行点字符串操作。

    class Person(object):
        def __init__(self, name):
            self.name = name
    
    alex = Person("alex")
    
    s = "name"
    
    # 直接alex.s  或者alex."name"都是取不到值的
    print(getattr(alex, s))   # alex
    

    2、编辑按钮构建

    from django.conf.urls import url
    from django.shortcuts import HttpResponse,render
    
    
    class ModelStark(object):
        """定制配置类"""
        list_display = []
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        def add(self, request):
            return HttpResponse("add")
    
        def delete(self, request, id):
            return HttpResponse("delete")
    
        def change(self, request, id):
            return HttpResponse("change")
    
        def list_view(self, request):
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
    
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']
    
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            new_data_list = []
            for obj in data_list:   # 所查询表中的一个个对象
                temp = []
                for field in self.list_display:  # field为一个个字段字符串  ['pk', 'name', 'age', edit]
                    if callable(field):   # 用于判断是否是函数,可调用的是方法,不可调用的是属性
                        val = field(self, obj)   # edit(self, obj)  obj是当前正在处理的这个记录
                    else:
                        val = getattr(obj, field)   # 一定要是属性才能这么去调用, obj.name  obj.age
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return render(request, "list_view.html", locals())
    
        def get_urls_2(self):
            temp = []
    
            # 用name取别名app名+model名+操作名可以保证别名不会重复
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
            temp.append(url(r"^(d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
            temp.append(url(r"^(d+)/change/", self.change, 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):
            return self.get_urls_2(), None, None  # [], None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self, model, stark_class=None, **options):
            """注册"""
            if not stark_class:
                # 如果注册的时候没有自定义配置类,执行
                stark_class = ModelStark   # 配置类
    
            # 将配置类对象加到_registry字典中,键为模型类
            self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}
    
        def get_urls(self):
            """构造一层url"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                # model:一个模型表
                # stark_class_obj:当前模型表相应的配置类对象
    
                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))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
            return temp
    
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    
    site = StarkSite()    # 单例对象
    /stark/service/stark.py
    from app01 import models
    from stark.service.stark import site, ModelStark
    from django.utils.safestring import mark_safe
    from django.urls import reverse
    
    
    # 自定义配置类
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
    
        def edit(self, obj):
            # 方法一:
            # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>编辑</a>" % obj.pk)
            # 方法二:前面不加/就是和前面的路径拼接
            # return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
            # 方法三:反向解析
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            # _url = reverse("%s_%s_add" % (app_label, model_name))
            # print("_url", _url)   # _url /stark/app01/userinfo/add/
    
            # stark/app01/userinfo/(/d+)/change
            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
            print("_url", _url)  # _url /stark/app01/userinfo/3/change/
            return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
        def deletes(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, ))
            print("_url", _url)  # _url /stark/app01/userinfo/3/change/
            return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
    
        list_display = ["pk", "name", "age", edit, deletes]
    
    
    site.register(models.UserInfo, UserConfig)
    site.register(models.Book)
    
    print("_registry", site._registry)
    app01/stark.py

    注意:

    (1)利用callable方法判断是函数还是属性

    if callable(field):   # 用于判断是否是函数,可调用的是方法,不可调用的是属性
        val = field(self)
    else:
        val = getattr(obj, field)   # 一定要是属性才能这么去调用, obj.name  obj.age
    temp.append(val)
    

    (2)区分类的实例方法与函数调用及self参数

    class Person(object):
        def __init__(self, name):
            self.name = name
    
        def eat(self):
            print(self)
            print("eat.....")
    
    # 实例方法
    egon = Person("egon")
    egon.eat()
    """
    <__main__.Person object at 0x10401ae48>
    eat.....
    """
    
    # 函数
    Person.eat(123)
    """
    123
    eat.....
    """
    

    (3)阻止<a>编辑</a>转义

    from django.utils.safestring import mark_safe
    
    # 自定义配置类
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
    
        def edit(self):
            return mark_safe("<a>编辑</a>")
    
        list_display = ["pk", "name", "age", edit]
    

       显示效果:

      

    (4)实现点击编辑进入编辑页面

      startk/service/stark.py中的list_view函数中,在判断filed是函数时,给这个函数还传入一个obj也就是当前正在处理的记录对象:

    class ModelStark(object):
        def list_view(self, request):
            for obj in data_list:   # 所查询表中的一个个对象
                temp = []
                for field in self.list_display:  # field为一个个字段字符串  ['pk', 'name', 'age', edit]
                    if callable(field):   # 用于判断是否是函数,可调用的是方法,不可调用的是属性
                        val = field(self, obj)   # edit(self, obj)  obj是当前正在处理的这个记录
                    else:
                        val = getattr(obj, field)   # 一定要是属性才能这么去调用, obj.name  obj.age
    
                    temp.append(val)
    
                new_data_list.append(temp)
    

       前面已经实现实现了编辑按钮,现在需要在app01/stark.py中为edit方法返回值配好返回的a标签的href路径:

    from app01 import models
    from stark.service.stark import site, ModelStark
    from django.utils.safestring import mark_safe
    
    # 自定义配置类
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        def edit(self, obj):
            # 方法一:
            # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>编辑</a>" % obj.pk)
            # 方法二:前面不加/就是和前面的路径拼接
            return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
        list_display = ["pk", "name", "age", edit]
    

      显示效果:

      

    (5)用反向解析实现路径返回

       https://www.cnblogs.com/yuanchenqi/articles/7629939.html

      首先给urls用name添加别名:app名+model名+操作名可以保证别名不重复

    class ModelStark(object):
        """定制配置类"""
        '''省略内容'''
        def get_urls_2(self):
            temp = []
    
            # 用name取别名app名+model名+操作名可以保证别名不会重复
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
            temp.append(url(r"^(d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
            temp.append(url(r"^(d+)/change/", self.change, 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
    

      路由效果如下所示:

      

      再在app01/stark.py中edit方法以反向解析解析路径:

    from app01 import models
    from stark.service.stark import site, ModelStark
    from django.utils.safestring import mark_safe
    from django.urls import reverse
    
    # 自定义配置类
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        def edit(self, obj):
            # 方法一:
            # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>编辑</a>" % obj.pk)
            # 方法二:前面不加/就是和前面的路径拼接
            # return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
            # 方法三:反向解析
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            # _url = reverse("%s_%s_add" % (app_label, model_name))
            # print("_url", _url)   # _url /stark/app01/userinfo/add/
    
            # stark/app01/userinfo/(/d+)/change
            _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
            print("_url", _url)  # _url /stark/app01/userinfo/3/change/
            return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
        list_display = ["pk", "name", "age", edit]
    
    site.register(models.UserInfo, UserConfig)
    

      点击按钮显示效果同上。

    (6)添加删除功能

    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
    
        def edit(self, obj):...
    
        def deletes(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, ))
            print("_url", _url)  # _url /stark/app01/userinfo/3/change/
            return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
    
        list_display = ["pk", "name", "age", edit, deletes]
    

      显示效果如下:

      

    (7)添加复选框按钮

    def checkbox(self, obj):
        """复选框"""
        return mark_safe("<input type='checkbox'>")
    

       显示效果:

      

    二、构建表头并应用于所有列表对象

    1、编辑编辑、删除、复选框函数,同时要实现每个表都能实现这些操作

    class ModelStark(object):
        """默认类,定制配置类"""
        list_display = ["__str__",]
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        # 删除、编辑,复选框
        def edit(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, ))
            print("_url", _url)
            return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
        def deletes(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, ))
            print("_url", _url)
            return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
    
        def checkbox(self, obj):
            """复选框"""
            return mark_safe("<input type='checkbox'>")
    
        '''代码省略'''
    
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
            temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    
        def list_view(self, request):
            """循环展示"""
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
    
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']
    
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            """构建表单数据"""
            new_data_list = []
    
            for obj in data_list:
                temp = []
    
                for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
    
                    if callable(field):
                        val = field(self, obj)
                    else:
                        val = getattr(obj, field)
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return render(request, "list_view.html", locals())
    

    (1)不同的表都需要有这些按钮功能

      将这些函数从自定义配置类(app01/stark.py里的UserConfig)剪切到默认类(stark/service/stark.py里的ModelStark),剩下的app01/stark.py代码如下所示:

    from app01 import models
    from stark.service.stark import site, ModelStark
    
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        """自定义配置类"""
        list_display = ["pk", "name", "age"]
    
    site.register(models.UserInfo, UserConfig)
    
    
    class BookConfig(ModelStark):
        list_display = ['pk', 'title']
    
    site.register(models.Book)
    
    print("_registry", site._registry)
    

    (2)self.list_display里现在只剩下普通字段,需要拼接出新的列表

      可以注意到自定义配置类的list_display已经没有了edit,delete等函数, 因此需要返回新的列表。

    class ModelStark(object):
        '''省略代码''''
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
            temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    

      在list_view中调用新的的列表:

    def list_view(self, request):
        """构建表单数据"""
        new_data_list = []
        for obj in data_list:
            temp = []
            for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
                if callable(field):
                    val = field(self, obj)
                else:
                    val = getattr(obj, field)
                temp.append(val)
            new_data_list.append(temp)
        return render(request, "list_view.html", locals())
    

    (3)不同的表具有不同的自定义配置类,每个的list_display都不相同,对应表取对应的list_display

    ##################stark/service/stark.py###############
    class ModelStark(object):
        """默认类,定制配置类"""
        list_display = ["__str__",]
    
    
    ##################app01/stark.py##################
    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        """自定义配置类"""
        list_display = ["pk", "name", "age"]
    
    class BookConfig(ModelStark):
        list_display = ['pk', 'title']
    

      这里涉及到类的__str__方法使用,示例如下:

    class Persoon(object):
    
        def __init__(self, name):
            self.name = name
    
        def __str__(self):
            return self.name
    
    
    alex = Persoon("alex")
    print(alex.__str__)
    print(alex.__str__())
    print(str(alex))
    """'
    <bound method Persoon.__str__ of <__main__.Persoon object at 0x10401ae48>>
    alex
    alex
    """
    

    (4)根据models.py中模型是否具有def __str__(self),页面上字段显示不同

      

      

    2、构建表头

    # -*- coding:utf-8 -*-
    __author__ = 'Qiushi Huang'
    
    
    from django.conf.urls import url
    from django.shortcuts import HttpResponse, render
    from django.utils.safestring import mark_safe
    from django.urls import reverse
    
    
    class ModelStark(object):
        """默认类,定制配置类"""
        list_display = ["__str__",]
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        # 删除、编辑,复选框
        def edit(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_change" % (app_label, model_name), args=(obj.pk, ))
            print("_url", _url)
            return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
        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, ))
            print("_url", _url)
            return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
    
        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 add(self, request):
            return HttpResponse("add")
    
        def delete(self, request, id):
            return HttpResponse("delete")
    
        def change(self, request, id):
            return HttpResponse("change")
    
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
            temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    
        def list_view(self, request):
            """循环展示"""
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
    
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']
    
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            """构建表头"""
            header_list = []
            print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
    
            for field in self.new_list_display():
    
                if callable(field):
                    # 如果是函数
                    val = field(self, header=True)
                    header_list.append(val)
    
                else:
                    # 如果是字符串
                    if field == "__str__":
                        header_list.append(self.model._meta.model_name.upper())  # 当前模型表名
                    else:
                        # 如果不是"__str__"
                        # header_list.append(field)
                        val = self.model._meta.get_field(field).verbose_name
                        header_list.append(val)
    
    
            """构建表单数据"""
            new_data_list = []
    
            for obj in data_list:
                temp = []
    
                for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
    
                    if callable(field):
                        val = field(self, obj)
                    else:
                        val = getattr(obj, field)
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return render(request, "list_view.html", locals())
    
        def get_urls_2(self):
            temp = []
    
            # 用name取别名app名+model名+操作名可以保证别名不会重复
            model_name = self.model._meta.model_name
            app_label = self.model._meta.app_label
            temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
            temp.append(url(r"^(d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
            temp.append(url(r"^(d+)/change/", self.change, 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):
            return self.get_urls_2(), None, None  # [], None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self, model, stark_class=None, **options):
            """注册"""
            if not stark_class:
                # 如果注册的时候没有自定义配置类,执行
                stark_class = ModelStark   # 配置类
    
            # 将配置类对象加到_registry字典中,键为模型类
            self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}
    
        def get_urls(self):
            """构造一层url"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                # model:一个模型表
                # stark_class_obj:当前模型表相应的配置类对象
    
                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))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
            return temp
    
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    
    site = StarkSite()    # 单例对象
    service/stark.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
        <script src="/static/js/jquery-1.12.4.min.js"></script>
    </head>
    <body>
    <h4>数据列表</h4>
    <div class="container">
        <div class="row">
            <div class="col-md-9">
                <table class="table table-bordered table-striped">
                    <thead>
                        <tr>
                            {% for item in header_list %}
                                <th>{{ item }}</th>
                            {% endfor %}
                        </tr>
                    </thead>
                    <tbody>
                        {% for data in new_data_list %}
                            <tr>
                                {% for item in data %}
                                    <td>{{ item }}</td>
                                {% endfor %}
                            </tr>
                        {% endfor %}
    
                    </tbody>
                </table>
            </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>
    list_view.html

    (1)__name__

      __name__是标识模块的名字的一个系统变量;__main__一般作为函数的入口,类似于C语言,尤其在大型工程中,常常有if __name__ == "__main__":来表明整个工程开始运行的入口。

    def foo():
        return
    
    print(foo.__name__)   # foo
    

    (2)将表头自定义函数显示改为中文

    def list_view(self, request):
    
        """构建表头"""
        header_list = []
        print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
    
        for field in self.new_list_display():
    
            if callable(field):
                # 如果是函数
                val = field(self, header=True)
                header_list.append(val)
    
            else:
                # 如果是字符串
                if field == "__str__":
                    header_list.append(self.model._meta.model_name.upper())  # 当前模型表名
                else:
                    # 如果不是"__str__"
                    header_list.append(field)
    

       当callable判断field是函数时,给函数传参数header=True。修改编辑、删除、选择函数:

    # 删除、编辑,复选框
    def edit(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_change" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>编辑</a>" % obj.pk)
    
    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, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
    
    def checkbox(self, obj=None, header=False):
        """复选框"""
        if header:
            # 如果是表头显示操作
            return "选择"
    
        return mark_safe("<input type='checkbox'>")
    

      显示效果:

      

    (3)将普通字段修改为中文

    def list_view(self, request):
        """构建表头"""
        header_list = []
        print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
        for field in self.new_list_display():
            if callable(field):
                # 如果是函数
                val = field(self, header=True)
                header_list.append(val)
            else:
                # 如果是字符串
                if field == "__str__":
                    header_list.append(self.model._meta.model_name.upper())  # 当前模型表名
                else:
                    # 如果不是"__str__"
                    # header_list.append(field)
                    val = self.model._meta.get_field(field).verbose_name
                    header_list.append(val)
    

      然后在models.py中为字段添加verbose_name属性

    class UserInfo(models.Model):
        name = models.CharField(verbose_name="姓名", max_length=32)
        age = models.IntegerField(verbose_name="年龄")
        def __str__(self):
            return self.name
    
    class Book(models.Model):
        title = models.CharField(verbose_name="书名",max_length=32)
        def __str__(self):
            return self.title
    

      显示效果:

      

      注意在这里app01/stark.py中的list_display是不能添加“pk”的

    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        """自定义配置类"""
        list_display = ["name", "age"]
    
    site.register(models.UserInfo, UserConfig)
    
    class BookConfig(ModelStark):
        list_display = ['title']
    
    site.register(models.Book)
    print("_registry", site._registry)
    

      因为它的主键是"id",“pk”只能是在查询的时候使用。且如果添加“id”的话,这个值也无法改为中文。

    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        """自定义配置类"""
        list_display = ["id", "name", "age"]
    

       显示效果:

      

    (4)复选框点击全选事件

      将表头改为复选框,并给一个id:

    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'>")
    

      复选框点击全选事件:

    <script>
        // 复选框全选
        $("#choice").click(function () {
            if($(this).prop("checked")) {
                // 如果是选中状态
                $(".choice_item").prop("checked", true);
            } else {
                $(".choice_item").prop("checked", false)
            }
        })
    </script>
    

      注意这里使用js中的prop()方法来查看复选框是否选中,或设置复选框为选中或未选中状态。

      

    三、设计list_display_links

    1、定制列可以点击跳转

    class ModelStark(object):
        '''其他代码省略'''
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
    
            if not self.list_display_links:
                # 如果没有值
                temp.append(ModelStark.edit)
    
            # temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    
        def list_view(self, request):
            """循环展示"""
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
    
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']
    
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            """构建表头"""
            header_list = []
            print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
    
            for field in self.new_list_display():
    
                if callable(field):
                    # 如果是函数
                    val = field(self, header=True)
                    header_list.append(val)
    
                else:
                    # 如果是字符串
                    if field == "__str__":
                        header_list.append(self.model._meta.model_name.upper())  # 当前模型表名
                    else:
                        # 如果不是"__str__"
                        # header_list.append(field)
                        val = self.model._meta.get_field(field).verbose_name
                        header_list.append(val)
    
            """构建表单数据"""
            new_data_list = []
    
            for obj in data_list:
                temp = []
    
                for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
    
                    if callable(field):
                        val = field(self, obj)
                    else:
                        val = getattr(obj, field)
                        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,))
    
                            val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return render(request, "list_view.html", locals())
    service/stark.py改动的部分

      不再拼接edit函数名,直接通过点击普通字段进入编辑页面。在构建表单数据时,判断字段是否在list_display_links中,如果在的话通过反向解析生成a标签指向的地址。

      再在app01/stark.py的自定义配置类添加list_display_links:

    class UserConfig(ModelStark):   # UserConfig是ModelStark的一个子类
        """自定义配置类"""
        list_display = ["id", "name", "age"]
        list_display_links = ["name"]
    
    
    site.register(models.UserInfo, UserConfig)
    
    
    class BookConfig(ModelStark):
        list_display = ['title']
        list_display_links = ["title"]
    

      显示效果:

      

    2、将获取的应用名、模型名组成url定义为函数

    class ModelStark(object):
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
    
            if not self.list_display_links:
                # 如果没有值
                temp.append(ModelStark.edit)
    
            # temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    
        def get_change_url(self,obj):
            model_name = 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
    
        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):.....
    

      将删除、编辑、复选框等函数内的url拼接代码替换后:

    # -*- coding:utf-8 -*-
    __author__ = 'Qiushi Huang'
    
    
    from django.conf.urls import url
    from django.shortcuts import HttpResponse, render
    from django.utils.safestring import mark_safe
    from django.urls import reverse
    
    
    class ModelStark(object):
        """默认类,定制配置类"""
        list_display = ["__str__",]
        list_display_links = []
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        # 删除、编辑,复选框
        def edit(self, obj=None, header=False):
            """编辑"""
            if header:
                # 如果是表头显示操作
                return "操作"
    
            _url = self.get_change_url(obj)
            return mark_safe("<a href='%s'>编辑</a>" % _url)
    
        def deletes(self, obj=None, header=False):
            """删除"""
            if header:
                # 如果是表头显示操作
                return "操作"
    
            _url = self.get_delete_url(obj)
            # return mark_safe("<a href='%s/change'>删除</a>" % obj.pk)
            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'>")
    
        def add_view(self, request):
            return HttpResponse("add")
    
        def delete_view(self, request, id):
            return HttpResponse("delete")
    
        def change_view(self, request, id):
            return HttpResponse("change")
    
        def new_list_display(self):
            """返回新的列表"""
            temp = []
            temp.append(ModelStark.checkbox)  # 在列表中放一个checkbox名字
            temp.extend(self.list_display)  # 扩展进一个列表["pk","name","age"]
    
            if not self.list_display_links:
                # 如果没有值
                temp.append(ModelStark.edit)
    
            # temp.append(ModelStark.edit)    # edit函数名
            temp.append(ModelStark.deletes)   # deletes函数名
    
            return temp   # 返回新的列表
    
        def get_change_url(self,obj):
            model_name = 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
    
        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 list_view(self, request):
            """循环展示"""
            print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
    
            print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']
    
            data_list = self.model.objects.all()  # 拿到对应表所有的对象
    
            """构建表头"""
            header_list = []
            print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
    
            for field in self.new_list_display():
    
                if callable(field):
                    # 如果是函数
                    val = field(self, header=True)
                    header_list.append(val)
    
                else:
                    # 如果是字符串
                    if field == "__str__":
                        header_list.append(self.model._meta.model_name.upper())  # 当前模型表名
                    else:
                        # 如果不是"__str__"
                        # header_list.append(field)
                        val = self.model._meta.get_field(field).verbose_name
                        header_list.append(val)
    
    
            """构建表单数据"""
            new_data_list = []
    
            for obj in data_list:
                temp = []
    
                for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
    
                    if callable(field):
                        val = field(self, obj)
                    else:
                        val = getattr(obj, field)
                        if field in self.list_display_links:
                            # _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                            _url = self.get_change_url(obj)
    
                            val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
                # 构建一个查看url
                add_url = self.get_add_url()
    
            return render(request, "list_view.html", locals())
    
        def get_urls_2(self):
            temp = []
    
            # 用name取别名app名+model名+操作名可以保证别名不会重复
            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):
            return self.get_urls_2(), None, None  # [], None, None
    
    
    class StarkSite(object):
        """site单例类"""
        def __init__(self):
            self._registry = {}
    
        def register(self, model, stark_class=None, **options):
            """注册"""
            if not stark_class:
                # 如果注册的时候没有自定义配置类,执行
                stark_class = ModelStark   # 配置类
    
            # 将配置类对象加到_registry字典中,键为模型类
            self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}
    
        def get_urls(self):
            """构造一层url"""
            temp = []
            for model, stark_class_obj in self._registry.items():
                # model:一个模型表
                # stark_class_obj:当前模型表相应的配置类对象
    
                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))
                """
                   path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
                   path('app01/book/',ModelStark(Book,site).urls2),
                """
    
            return temp
    
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    
    site = StarkSite()    # 单例对象
    service/stark.py
  • 相关阅读:
    10大开源文档管理系统,知识管理系统
    okhttp原理,okhttp为什么好?
    开放式创新对程序开发有什么深远的影响?
    TypeScript中文手册【从入门到精通】
    CentoOS6 32停更了,如何继续用yum源【解决方案】
    electronic为什么要用JavaScript开发桌面应用
    统一身份认证登录入口,统一用户认证和单点登录解决方案
    PHP数组如何倒叙 array_reverse
    Windows electron开发实例大全
    AI深度学习的基础上处理自然语言
  • 原文地址:https://www.cnblogs.com/xiugeng/p/9503937.html
Copyright © 2020-2023  润新知