stark——查看页面编辑删除按钮
一、数据列表
设计查页面,主要展示两部分内容,表头部分和数据部分, 表头通过遍历list_display和默认要显示的编辑和删除字段。
1、数据构建
(1)service/stark.py,后台数据构建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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模板展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <! 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:
1 2 3 | # 自定义配置类 class UserConfig(ModelStark): # UserConfig是ModelStark的一个子类 list_display = [ "pk" , "name" , "age" ] |
根据父类子类关系,从调用者类里去找x,如果调用者中没有x,去父类找:
1 2 3 4 5 6 7 8 9 10 11 12 | class A( object ): x = 12 def func( self ): print ( self .x) class B(A): x = 5 b = B() b.func() # 5 |
(2)字符串找对象的属性,反射
1 2 3 4 5 6 7 8 9 10 11 | 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) |
字符串不是变量名称,无法进行点字符串操作。
1 2 3 4 5 6 7 8 9 10 | 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() # 单例对象

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)
注意:
(1)利用callable方法判断是函数还是属性
1 2 3 4 5 | if callable (field): # 用于判断是否是函数,可调用的是方法,不可调用的是属性 val = field( self ) else : val = getattr (obj, field) # 一定要是属性才能这么去调用, obj.name obj.age temp.append(val) |
(2)区分类的实例方法与函数调用及self参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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>转义
1 2 3 4 5 6 7 8 9 | 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也就是当前正在处理的记录对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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名+操作名可以保证别名不重复
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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方法以反向解析解析路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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)添加删除功能
1 2 3 4 5 6 7 8 9 10 11 12 | 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)添加复选框按钮
1 2 3 | def checkbox( self , obj): """复选框""" return mark_safe( "<input type='checkbox'>" ) |
显示效果:
二、构建表头并应用于所有列表对象
1、编辑编辑、删除、复选框函数,同时要实现每个表都能实现这些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 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代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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等函数, 因此需要返回新的列表。
1 2 3 4 5 6 7 8 9 10 11 | 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中调用新的的列表:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 | ##################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__方法使用,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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() # 单例对象

<!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>
(1)__name__
__name__是标识模块的名字的一个系统变量;__main__
一般作为函数的入口,类似于C语言,尤其在大型工程中,常常有if __name__ == "__main__":
来表明整个工程开始运行的入口。
1 2 3 4 | def foo(): return print (foo.__name__) # foo |
(2)将表头自定义函数显示改为中文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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。修改编辑、删除、选择函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # 删除、编辑,复选框 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)将普通字段修改为中文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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属性
1 2 3 4 5 6 7 8 9 10 | 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”的
1 2 3 4 5 6 7 8 9 10 11 | 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”的话,这个值也无法改为中文。
1 2 3 | class UserConfig(ModelStark): # UserConfig是ModelStark的一个子类 """自定义配置类""" list_display = [ "id" , "name" , "age" ] |
显示效果:
(4)复选框点击全选事件
将表头改为复选框,并给一个id:
1 2 3 4 5 6 7 | 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'>" ) |
复选框点击全选事件:
1 2 3 4 5 6 7 8 9 10 11 | <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())
不再拼接edit函数名,直接通过点击普通字段进入编辑页面。在构建表单数据时,判断字段是否在list_display_links中,如果在的话通过反向解析生成a标签指向的地址。
再在app01/stark.py的自定义配置类添加list_display_links:
1 2 3 4 5 6 7 8 9 10 11 12 | 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定义为函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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() # 单例对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术