1、编辑按钮构建完成
1、必备知识预习
第一个会打印5.
第二个输出alex
alex是person类的实例对象,getattr()的用法就是alex拥有s方法的话,那么就执行。这里s是字符串用一个反射把字符串变成方法。
第三个是输出123,并且eat... 这里类可以直接调用自己的方法。不一定非得是实例对象。
第四个
第一个调用本身的__str__方法返回名字。
alex
第二个却是将alex这个对象变成字符串。
<__main__.Person object at 0x0000016951BDD5F8>
这里补充7个注意点:
注意点1: from django.utils.safestring import mark_safe 这样的话,django就不会去给你转义了。 return mark_safe("<a href="">编辑</a>") 注意点2: 在modelStark中: self.model:用户当前访问的表 注意点3: class Person(object): def __init__(self,name): self.name=name alex=Person("alex") s="name" print(getattr(alex,s)) 通过反射可以取值,而直接.一个字符串会报错。 注意点4: callable(field) #可以判断传入的是否是函数,是True,否则返回False 注意点5: class Person(object): def __init__(self,name): self.name=name def __str__(self): return self.name alex=Person("alex") print(alex) #"alex" alex.__str__() == str(alex) 注意点6: #可以通过这些获取到表名,项目名,以及每个字段的值。 model_name=Book._meta.model_name app_label=Book._meta.app_label title=Book._meta.get_field("title") title.max_length #32 注意点7: def foo(): return print(foo.__name__) #foo
2、mark_safe模块:将html标签安全传输
from django.utils.safestring import mark_safe #这样的话,django就不会去给你转义了。 return mark_safe("<a href="">编辑</a>")
3、构造表单数据
4、反向解析
https://www.cnblogs.com/yuanchenqi/articles/7629939.html
反向解析: def get_urls2(self): temp=[] model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp.append(url(r"^add/",self.add_view,name="%s_%s_add"%(app_label,model_name))) temp.append(url(r"^$", self.list_view,name="%s_%s_list"%(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))) return temp
里面用到的_url利用了URL的反向解析。 直接封装成下面的4个方向解析方法,得到最终的URL即可,到时候直接调用这些函数返回URL。 def get_change_url(self, obj): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) return _url 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
5、编辑按钮构造
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# -*- coding: utf-8 -*- # @Time : 2018/08/17 0017 14:52 # @Author : Venicid from stark.service import stark from .models import * from django.utils.safestring import mark_safe from django.urls import reverse class AuthorConfig(stark.ModelStark): def edit(self,obj): # return mark_safe("<a>编辑</a>") # 方案1:固定url # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>") # 方案2:拼接url # return mark_safe("<a href='%s/change'>编辑</a>") # 方案3:反向解析 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'>编辑</a>"%_url) list_display = ['pk', 'name', 'age', edit] stark.site.register(Book) stark.site.register(Publish) stark.site.register(Author,AuthorConfig) stark.site.register(AuthorDetail) print(stark.site._registry) """ {<class 'app01.models.Book'>: <stark.service.stark.ModelStark object at 0x0000003AA7439630>, <class 'app01.models.Publish'>: <stark.service.stark.ModelStark object at 0x0000003AA7439668>, <class 'app01.models.Author'>: <stark.service.stark.ModelStark object at 0x0000003AA74396A0>, <class 'app01.models.AuthorDetail'>: <stark.service.stark.ModelStark object at 0x0000003AA7439940>} """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# -*- coding: utf-8 -*- # @Time : 2018/08/17 0017 14:46 # @Author : Venicid from django.conf.urls import url from django.shortcuts import HttpResponse,render class ModelStark(object): list_display = ["__str__"] # 子类中没有,直接用父类自己的 def __init__(self,model, site): self.model = model self.site = site def list_view(self, request): print(self.model) # <class 'app01.models.Book'> 用户访问的模型表 print('list_display',self.list_display) # 获取data_list data_list = self.model.objects.all() # [obj1,obj2,...] new_data_list = [] for obj in data_list: # Book表模型,Author表模型 temp = [] for filed in self.list_display: # ['name','age'] if callable(filed): # edit() 可调用的 val = filed(self,obj) # 直接调用edit()函数 else: val = getattr(obj,filed) # 反射 obj是实例对象,name是方法 temp.append(val) new_data_list.append(temp) print('new_data_list',new_data_list) # 构造数据 [['jack', 44], ['mark', 33]] return render(request,'list_view.html', locals()) def add(self, request): return HttpResponse('add') def delete(self, request, id): return HttpResponse('delete') def change(self, request, id): return HttpResponse('change') def get_urls2(self): """构造 add/delete/change""" model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp = [] temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name))) 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))) return temp @property def urls2(self): return self.get_urls2(), None, None class StarkSite(object): """site单例类""" 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) def get_urls(self): """构造一层urls app01/book""" temp = [] for model, stark_class_obj in self._registry.items(): print(model, 'stark_clas_obj', stark_class_obj) # 不同的model模型表 """ <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198> <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240> """ app_label = model._meta.app_label # app01 model_name = model._meta.model_name # book # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None))) temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2)) """ path('app01/userinfo/',UserConfig(Userinfo,site).urls2), path('app01/book/',ModelStark(Book,site).urls2), """ return temp @property def urls(self): # return [],None,None return self.get_urls(),None,None site = StarkSite() # 单例对象
2、构造表头,删除,checkbox,links编辑
1、必备小知识
2、list_display显示表头
3、verbose_name显示中文
# 构建表头数据 def get_header(self): header_list=[] for field in self.config.new_list_display(): if callable(field): val=field(self,header=True) header_list.append(val) else: if field =="__str__": header_list.append(self.config.model._meta.model_name.upper()) else: val=self.config.model._meta.get_field(field).verbose_name header_list.append(val) return header_list # 构建表单数据 def get_body(self): new_data_list = [] for obj in self.page_Data: temp = [] for field in self.config.new_list_display(): if callable(field): val = field(self.config, obj) else: try: val = getattr(obj, field) if field in self.config.list_display_links: _url = self.config.get_change_url(obj) val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) except Exception as e: val = getattr(obj, field) temp.append(val) new_data_list.append(temp) return new_data_list
4、list_display_links编辑link构造
3、代码+总结
1、总结
完成
(list_display)
(list_display_links)
1.根据str,拿字段对象,取中文
val = self.model._meta.get_field(field).verbose_name
2.模型名称,app名称
model_name = self.model._meta.model_name
app_lable = self.model._meta.app_label
3.判断是否可调用
if callable(field): val = field(self, header = True)
4.字符串找对象得属性,反射
val = getattr(data, field)
5.返回标签
return mark_safe("<input id='choice' type='checkbox'>")
6.插入数组[]
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
7.反向解析,含正则
_url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,)) _url = reverse("%s_%s_add" % (app_label, model_name))
8.复选框,全选/全不选
$('#choice').click(function () { if($(this).prop('checked')){ $('.choice_item').prop('checked',true) }else{ $('.choice_item').prop('checked',false) } })
2、stark.py
from stark.service import stark from .models import * class AuthorConfig(stark.ModelStark): list_display = ['nid', 'name', 'age'] list_display_links = ['name','age'] stark.site.register(Book) stark.site.register(Publish) stark.site.register(Author,AuthorConfig) stark.site.register(AuthorDetail) print(stark.site._registry)
3、stark/server/stark.py
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 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 edit(self,obj=None, header=False): if header: return "操作" # 方案1:固定url # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>") # 方案2:拼接url # return mark_safe("<a href='%s/change'>编辑</a>") # 方案3:反向解析 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'>编辑</a>"%_url) 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,)) return mark_safe("<a href='%s'>删除</a>"%_url) def new_list_play(self): """构建 ['checkbox','pk', 'name', 'age', edit,'delete']""" 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 list_view(self, request): print(self.model) # <class 'app01.models.Book'> 用户访问的模型表 # 构建表头 header_list = [] # # header_list = ['选择','pk',...'操作','操作'] for field in self.new_list_play(): if callable(field): # header_list.append(field.__name__) val = field(self,header=True) header_list.append(val) else: if field == "__str__": header_list.append(self.model._meta.model_name.upper()) else: val = self.model._meta.get_field(field).verbose_name # 中文名称 header_list.append(val) # 构建表单 data_list = self.model.objects.all() # [obj1,obj2,...] new_data_list = [] for obj in data_list: # Book表模型,Author表模型 temp = [] for field in self.new_list_play(): # ['name','age'] if callable(field): # edit() 可调用的 val = field(self,obj) # 直接调用edit()函数 print('val--------->',val) else: val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮 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,)) # print(_url) val = mark_safe("<a href='%s'>%s</a>"%(_url,field)) temp.append(val) new_data_list.append(temp) print('new_data_list',new_data_list) # 构造数据 [['jack', 44], ['mark', 33]] return render(request,'list_view.html', locals()) def add(self, request): return HttpResponse('add') def delete(self, request, id): return HttpResponse('delete') def change(self, request, id): return HttpResponse('change') def get_urls2(self): """构造 add/delete/change""" model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp = [] temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name))) 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))) return temp @property def urls2(self): return self.get_urls2(), None, None class StarkSite(object): """site单例类""" 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) def get_urls(self): """构造一层urls app01/book""" temp = [] for model, stark_class_obj in self._registry.items(): print(model, 'stark_clas_obj', stark_class_obj) # 不同的model模型表 """ <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198> <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240> """ app_label = model._meta.app_label # app01 model_name = model._meta.model_name # book # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None))) temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2)) """ path('app01/userinfo/',UserConfig(Userinfo,site).urls2), path('app01/book/',ModelStark(Book,site).urls2), """ return temp @property def urls(self): # return [],None,None return self.get_urls(),None,None site = StarkSite() # 单例对象
4、模板层
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <script src="/static/jQuery/jquery-3.2.1.min.js"></script> </head> <body> <h3>list页面</h3> <div class="container"> <div class="row"> <div class="col-md-9 col-lg-offset-1"> <table class="table table-bordered table-striped"> <tr> {% for header in header_list %} <th>{{ header }}</th> {% endfor %} </tr> {% for data in new_data_list %} <tr> {% for item in data %} <td>{{ item }}</td> {% endfor %} </tr> {% endfor %} </table> </div> </div> </div> <script type="text/javascript"> $('#choice').click(function () { if ($(this).prop('checked')){ //对象自身属性中是否具有指定的属性 $('.choice_item').prop("checked",true) }else{ $('.choice_item').prop("checked",false) } }) </script> </body> </html>
最后附上核心代码注释:
最难的查看页面: def list_view(self,request): data_list=self.model.objects.all() #首先肯定是取到所有的对象 # 1.构建表头数据 header_list=[] for field in self.new_list_display(): if callable(field): val=field(self,header=True) #这里是表头返回的"操作",和按个checkbox header_list.append(val) else: #如果是str,返回表名的大写字母 if field =="__str__": header_list.append(self.model._meta.model_name.upper()) else: #这里表示获取到每个字段的verbose_name(可中文) val=self.model._meta.get_field(field).verbose_name header_list.append(val) # 2.构建表单数据 new_data_list=[] for obj in data_list: #1.取到每一个数据对象 temp=[] for field in self.new_list_display(): #2.从list_display取到字段 if callable(field): val=field(self,obj) #如果是可调用的话,那么这个数据就是a标签或者checkbox else: val=getattr(obj,field) # 3.如果是每个数据的话,利用反射,取到对应的值,相当于(obj.field)。 if field in self.list_display_links: #当然这里判定一下是否设置的点击编辑的选项! _url = self.get_change_url(obj) val=mark_safe("<a href='%s'>%s</a>"%(_url,val)) #如果给某个字段设置了,改为a标签 temp.append(val) new_data_list.append(temp) #构建一个查看URL add_url=self.get_add_url() #在添加数据的时候需要在后面追加add,利用URL反向解析,不要写死。 return render(request,"list_view.html",locals())