• 1、构建批量删除按钮
  • 2、filter过滤
  • 3、总结+coding代码

1、构建批量删除按钮

1、admin中每个页面默认都有

2、stark之构建批量删除

3、coding

  1. {% extends 'base.html' %}
  2.  
  3. {% block title %}
  4. <title>list页面</title>
  5. {% endblock %}
  6.  
  7. {% block header %}
  8. <h3>list页面</h3>
  9. {% endblock %}
  10. {% block content %}
  11. <a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
  12.  
  13. {% if show_list.config.search_fields %}
  14. <form action="" method="get">
  15. <input type="text" class="form-control" style="width: 30%;display: inline-block;margin-top: 8px" name="q" value="{{ show_list.config.key_word }}">
  16. <button class="btn btn-success">submit</button>
  17. </form>
  18. {% endif %}
  19.  
  20. <form action="" method="post">
  21. {% csrf_token %}
  22. <select name="action" class="form-control" style="display: inline-block;width: 200px;margin: 8px 8px 8px 0;height: 35px;vertical-align: -2px">
  23. <option value="">-------</option>
  24. {% for item in show_list.get_action_list %}
  25. <option value="{{ item.name }}">{{ item.desc }}</option>
  26. {% endfor %}
  27. </select>
  28. <button type="submit" class="btn btn-primary">Go</button>
  29.  
  30. <table class="table table-bordered table-striped">
  31. <tr>
  32. {% for header in show_list.get_header %}
  33. {# {% for header in header_list %}#}
  34. <th>{{ header }}</th>
  35. {% endfor %}
  36. </tr>
  37.  
  38. {% for data in show_list.get_body %}
  39. {# {% for data in new_data_list %}#}
  40. <tr>
  41. {% for item in data %}
  42. <td>{{ item }}</td>
  43. {% endfor %}
  44.  
  45. </tr>
  46. {% endfor %}
  47. </table>
  48. </form>
  49.  
  50. <nav>
  51. <ul class="pagination">
  52. {{ show_list.pagination.page_html|safe }}
  53. </ul>
  54. </nav>
  55.  
  56. {% endblock %}
  57.  
  58. {% block javascript %}
  59. <script type="text/javascript">
  60. $('#choice').click(function () {
  61. if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
  62. $('.choice_item').prop("checked", true)
  63. } else {
  64. $('.choice_item').prop("checked", false)
  65. }
  66. })
  67. </script>
  68. {% endblock %}

list_view.html

  1. from django.shortcuts import HttpResponse
  2. from stark.service import stark
  3. from .models import *
  4. from django.forms import ModelForm
  5.  
  6. class AuthorConfig(stark.ModelStark):
  7. list_display = ['nid', 'name', 'age']
  8. list_display_links = ['name','age']
  9.  
  10. class BookModelForm(ModelForm):
  11. class Meta:
  12. model = Book
  13. fields = "__all__"
  14.  
  15. labels = {
  16. "authors":"作者",
  17. "publishDate":"出版日期",
  18. }
  19.  
  20. class BookConfig(stark.ModelStark):
  21. list_display = ['nid', 'title', 'price']
  22. modelform_class = BookModelForm
  23. search_fields = ['title','price']
  24.  
  25. # 批量修改数据
  26. def patch_init(self,request,queryset):
  27. queryset.update(price=111)
  28.  
  29. # return HttpResponse("批量初始化OK")
  30.  
  31. patch_init.short_description = "批量初始化"
  32.  
  33. actions = [patch_init]
  34.  
  35. stark.site.register(Book,BookConfig)
  36. stark.site.register(Publish)
  37. stark.site.register(Author,AuthorConfig)
  38. stark.site.register(AuthorDetail)
  39.  
  40. print(stark.site._registry)
  41.  
  42. """
  43. {<class 'app01.models.Book'>: <stark.service.stark.ModelStark object at 0x0000003AA7439630>,
  44. <class 'app01.models.Publish'>: <stark.service.stark.ModelStark object at 0x0000003AA7439668>,
  45. <class 'app01.models.Author'>: <stark.service.stark.ModelStark object at 0x0000003AA74396A0>,
  46. <class 'app01.models.AuthorDetail'>: <stark.service.stark.ModelStark object at 0x0000003AA7439940>}
  47. """

starkadmin

  1. # -*- coding: utf-8 -*-
  2. # @Time : 2018/08/17 0017 14:46
  3. # @Author : Venicid
  4. from django.conf.urls import url
  5. from django.shortcuts import HttpResponse,render,redirect
  6.  
  7. from django.utils.safestring import mark_safe
  8. from django.urls import reverse
  9.  
  10. from stark.utils.page import Pagination
  11. class ShowList(object):
  12. def __init__(self,config, data_list,request):
  13. self.config = config # MOdelStark实例对象
  14. self.data_list = data_list # 数据
  15. self.request =request
  16.  
  17. # 分页
  18. data_count = self.data_list.count()
  19. current_page = int(self.request.GET.get('page',1))
  20. base_path = self.request.path
  21. self.pagination = Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=10, pager_count=11,)
  22.  
  23. # 分页后的数据
  24. self.page_data = self.data_list[self.pagination.start:self.pagination.end]
  25.  
  26. # actions 批量初始化,字段
  27. # self.actions = self.config.actions # [patch_init]
  28. self.actions = self.config.new_actions() # [pathch_delete,patch_init,]
  29. # 构建数据[{'name':'path_init',"desc":'xxxxx'}]
  30.  
  31. def get_action_list(self):
  32. """action批量初始化,构架数据"""
  33. temp = []
  34. for action in self.actions:
  35. temp.append(
  36. {'name':action.__name__, # class的类名
  37. "desc":action.short_description # class的属性
  38. }
  39. )
  40. return temp
  41.  
  42. def get_header(self):
  43. # 构建表头
  44. header_list = [] # # header_list = ['选择','pk',...'操作','操作']
  45. for field in self.config.new_list_play():
  46. if callable(field):
  47. # header_list.append(field.__name__)
  48. val = field(self.config, header=True)
  49. header_list.append(val)
  50. else:
  51. if field == "__str__":
  52. header_list.append(self.config.model._meta.model_name.upper())
  53. else:
  54. val = self.config.model._meta.get_field(field).verbose_name # 中文名称
  55. header_list.append(val)
  56.  
  57. return header_list
  58.  
  59. def get_body(self):
  60. # 构建表单
  61. new_data_list = []
  62. for obj in self.page_data: #分页后的数据 # Book表模型,Author表模型
  63. temp = []
  64. for field in self.config.new_list_play(): # ['name','age']
  65. if callable(field): # edit() 可调用的
  66. print(obj,99999999999999999)
  67. val = field(self.config,obj) # 直接调用edit()函数
  68. print('val--------->',val)
  69. else:
  70. val = getattr(obj,field) # 反射 obj是实例对象,name是方法
  71.  
  72. # list_display_links 按钮
  73. if field in self.config.list_display_links:
  74. model_name = self.config.model._meta.model_name
  75. app_label = self.config.model._meta.app_label
  76. _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
  77. # print(_url)
  78. val = mark_safe("<a href='%s'>%s</a>"%(_url,field))
  79.  
  80. temp.append(val)
  81.  
  82. new_data_list.append(temp)
  83.  
  84. print('new_data_list',new_data_list) # 构造数据 [['jack', 44], ['mark', 33]]
  85.  
  86. return new_data_list
  87.  
  88. class ModelStark(object):
  89. list_display = ["__str__"] # 子类中没有,直接用父类自己的
  90. list_display_links = []
  91. modelform_class = []
  92. search_fields = [] # 模糊查询字段
  93. actions = []
  94.  
  95. # 批量删除
  96. def patch_delete(self,request,queryset):
  97. queryset.delete()
  98.  
  99. patch_delete.short_description = "Delete selected "
  100.  
  101. def __init__(self,model, site):
  102. self.model = model
  103. self.site = site
  104.  
  105. # 增删改查url
  106. def get_add_url(self):
  107. model_name = self.model._meta.model_name
  108. app_label = self.model._meta.app_label
  109. _url = reverse("%s_%s_add" %(app_label,model_name))
  110. return _url
  111.  
  112. def get_list_url(self):
  113. model_name = self.model._meta.model_name
  114. app_label = self.model._meta.app_label
  115. _url = reverse("%s_%s_list" %(app_label,model_name))
  116. return _url
  117.  
  118. # 复选框,编辑,删除
  119. def checkbox(self,obj=None, header=False):
  120. if header:
  121. return mark_safe("<input id='choice' type='checkbox'>")
  122. return mark_safe("<input class='choice_item' type='checkbox' name='selected_pk' value='%s'>"%obj.pk)
  123.  
  124. def edit(self,obj=None, header=False):
  125. if header:
  126. return "操作"
  127. # 方案1:固定url
  128. # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
  129. # 方案2:拼接url
  130. # return mark_safe("<a href='%s/change'>编辑</a>")
  131.  
  132. # 方案3:反向解析
  133. model_name = self.model._meta.model_name
  134. app_label = self.model._meta.app_label
  135. _url = reverse("%s_%s_change"%(app_label,model_name),args=(obj.pk,))
  136. # print("_url",_url)
  137. return mark_safe("<a href='%s'>编辑</a>"%_url)
  138.  
  139. def deletes(self,obj=None, header=False):
  140. if header:
  141. return "操作"
  142. model_name = self.model._meta.model_name
  143. app_label = self.model._meta.app_label
  144. _url = reverse("%s_%s_delete"%(app_label,model_name),args=(obj.pk,))
  145. return mark_safe("<a href='%s'>删除</a>"%_url)
  146.  
  147. # ModelForm组件渲染 list、增、删、改页面
  148. def get_modelform_class(self):
  149. """ModelForm组件"""
  150. if not self.modelform_class:
  151. from django.forms import ModelForm
  152. class ModelFormDemo(ModelForm):
  153. class Meta:
  154. model = self.model
  155. fields = "__all__"
  156. return ModelFormDemo
  157. else:
  158. return self.modelform_class
  159.  
  160. def new_list_play(self):
  161. """构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
  162. temp = []
  163. temp.append(ModelStark.checkbox)
  164. temp.extend(self.list_display)
  165. if not self.list_display_links:
  166. temp.append(ModelStark.edit)
  167. temp.append(ModelStark.deletes)
  168. return temp
  169.  
  170. # action = ['delete',...]
  171. def new_actions(self):
  172. temp = []
  173. temp.append(ModelStark.patch_delete) # delete添加
  174. temp.extend(self.actions) # 如果定义新的,就扩展到temp中
  175. return temp
  176.  
  177. '''
  178. def list_view(self,request):
  179. ret1 = self.model.objects.filter(title__startswith='py')
  180. ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
  181. ret3 = self.model.objects.filter(price__range=[10,20])
  182. ret4 = self.model.objects.filter(title__contains='O')
  183. ret5 = self.model.objects.filter(title__icontains='O')
  184. return HttpResponse("过滤成功")
  185. '''
  186.  
  187. def get_search_condition(self,request):
  188. """search模糊查询"""
  189. key_word = request.GET.get("q",'')
  190. self.key_word = key_word
  191. from django.db.models import Q # 与或非
  192. search_connection = Q()
  193. if key_word:
  194. search_connection.connector = "or"
  195. for search_field in self.search_fields:
  196. search_connection.children.append((search_field+"__contains", key_word))
  197.  
  198. return search_connection
  199.  
  200. def list_view(self, request):
  201. if request.method == 'POST':
  202. print('post',request.POST)
  203. action = request.POST.get("action") # action': ['patch_init'],
  204. if action:
  205. selected_pk = request.POST.getlist('selected_pk') # 'selected_pk': ['5']}>
  206. action_func = getattr(self,action) # 反射查询 action # 取出实例方法
  207.  
  208. queryset = self.model.objects.filter(pk__in=selected_pk) # 查询
  209. ret = action_func(request,queryset) # 执行action() # 执行实例方法()
  210. # return ret
  211.  
  212. # 获取search的Q对象
  213. search_connection = self.get_search_condition(request)
  214.  
  215. # 筛选获取当前表所有数据
  216. data_list = self.model.objects.all().filter(search_connection)
  217.  
  218. #按照showlist展示页面, 构建表头,表单
  219. show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象
  220.  
  221. # 构建一个查看addurl
  222. add_url = self.get_add_url()
  223. return render(request,'list_view.html', locals())
  224.  
  225. def add_view(self, request):
  226. ModelFormDemo=self.get_modelform_class()
  227. form = ModelFormDemo()
  228. if request.method == "POST":
  229. form = ModelFormDemo(request.POST)
  230. if form.is_valid():
  231. form.save()
  232. return redirect(self.get_list_url())
  233.  
  234. return render(request, "add_view.html",locals())
  235.  
  236. def delete_view(self, request, id):
  237. url = self.get_list_url()
  238. if request.method == "POST":
  239. self.model.objects.filter(pk=id).delete()
  240. return redirect(url)
  241. return render(request, "delete_view.html", locals())
  242.  
  243. def change_view(self, request, id):
  244. edit_obj = self.model.objects.filter(pk=id).first()
  245.  
  246. ModelFormDemo=self.get_modelform_class()
  247. form = ModelFormDemo(instance=edit_obj)
  248. if request.method == "POST":
  249. form = ModelFormDemo(request.POST,instance=edit_obj)
  250. if form.is_valid():
  251. form.save()
  252. return redirect(self.get_list_url())
  253.  
  254. return render(request, "change_view.html",locals())
  255.  
  256. #构造 add/delete/change
  257. def get_urls2(self):
  258. model_name = self.model._meta.model_name
  259. app_label = self.model._meta.app_label
  260.  
  261. temp = []
  262. temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
  263. temp.append(url(r'^add/', self.add_view, name='%s_%s_add'%(app_label,model_name)))
  264. temp.append(url(r'^(\d+)/delete/', self.delete_view, name='%s_%s_delete'%(app_label,model_name)))
  265. temp.append(url(r'^(\d+)/change/', self.change_view, name='%s_%s_change'%(app_label,model_name)))
  266.  
  267. return temp
  268.  
  269. @property
  270. def urls2(self):
  271.  
  272. return self.get_urls2(), None, None
  273.  
  274. class StarkSite(object):
  275. """site单例类"""
  276. def __init__(self):
  277. self._registry = {}
  278.  
  279. def register(self,model, stark_class=None):
  280. """注册"""
  281. if not stark_class:
  282. stark_class = ModelStark
  283.  
  284. self._registry[model] = stark_class(model,self)
  285.  
  286. def get_urls(self):
  287. """构造一层urls app01/book"""
  288. temp = []
  289. for model, stark_class_obj in self._registry.items():
  290. print(model, 'stark_clas_obj', stark_class_obj) # 不同的model模型表
  291. """
  292. <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
  293. <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
  294. """
  295.  
  296. app_label = model._meta.app_label # app01
  297. model_name = model._meta.model_name # book
  298. # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
  299. temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
  300. """
  301. path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
  302. path('app01/book/',ModelStark(Book,site).urls2),
  303. """
  304.  
  305. return temp
  306.  
  307. @property
  308. def urls(self):
  309.  
  310. # return [],None,None
  311. return self.get_urls(),None,None
  312.  
  313. site = StarkSite() # 单例对象

stark/service/stark.py

2、filter过滤

1、admin之过滤

2、多对多字段:data_list = filter_field_obj.remote_field.model.objects.all()

1.封装好一个Q对象

  1. # 得到过滤的字段,封装成一个"和"关系的Q对象返回。
  2. def get_filter_condition(self,request):
  3. from django.db.models import Q
  4. filter_condition=Q()
  5. for filter_field,val in request.GET.items():
  6. if filter_field in self.list_filter:
  7. filter_condition.children.append((filter_field,val))
  8. return filter_condition

2.调用函数,传入request,然后加一个filter条件就可以了。

3、页面生成表单数据:多对多

4、filter过滤字段

5、filter字段的href动态变化

6、加入普通字段的过滤字段

7、list_view视图获取数据

8、html模板层

3、总结+coding代码

1、总结

  1. 1.配置得显示Filter,不配置就不显示了
  1. list_filter = ['title','publish', 'authors']
  1. 2.前端显示
  1. 后端返回 字典
  2. eg:{"publish":["<a href=''>全部</a>","<a href=''>南京出版社</a>","<a href=''>上海出版社</a>"]
  3. "authors":["<a href=''>全部</a>""<a href=''>yuan</a>","<a href=''>egon</a>"]
  4. }
  5.  
  6. {% if showlist.config.list_filter %}
  7. <h4>Filter</h4>
  8. {% for filter_field, linktags in showlist.get_filter_linktags.items %}
  9. <div class="well">
  10. <p>{{ filter_field.upper }}</p>
  11. {% for link in linktags %}
  12. <p>{{ link|safe }}</p>
  13. {% endfor %}
  14.  
  15. </div>
  16. {% endfor %}
  17. {% endif %}
  1. 3.get_filter_linktags 返回 字典
    知识:
    1.根据字段 str 取到模型得字段对象
  1. filter_field_obj = self.config.model._meta.get_field(filter_field)
  2. model_name = self.config.model._meta.model_name # 模型名 book
  3. app_label = self.config.model._meta.app_label # app名 app01
  1. 2.一对多,多对多,
  1. #就是 ForeignKey ManyToManyField 得对象
  2. app01.Book.publish
  3. <class 'django.db.models.fields.related.ForeignKey'>
  4. app01.Book.authors
  5. <class 'django.db.models.fields.related.ManyToManyField'>
  1. 3.根据一对多,多对多得对象 找关联得模型表,数据
  1. print("rel...", filter_field_obj.rel.to.objects.all())
  2.     data_list = filter_field_obj.remote_field.model.objects.all()
  3. rel... <QuerySet [<Publish: 南京出版社>, <Publish: 上海出版社>, <Publish: 河北出版社>]>
  4. rel... <QuerySet [<Author: yuan>, <Author: egon>, <Author: alex>]>
  1. 4.取数据,普通字段,和关联字段分开取
  1. if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
  2. data_list = filter_field_obj.rel.to.objects.all() # 关联对象 适用 一对多,多对多
  3. else: # 普通字段
  4. data_list = self.config.model.objects.all().values('pk', filter_field)
  1. 5.处理全部标签时
  1. 注意:url 上面已经有了该field, 全部,就取消该field, del params[filter_field]
  2. url 上面没有,那就没有
  3. temp = []
  4. if params.get(filter_field):
  5. del params[filter_field]
  6. temp.append("<a href='?%s'>全部</a>" % (params.urlencode()))
  7. else:
  8. temp.append("<a href='#' class='active'>全部</a>")
  1. 6.处理数据标签
  1.     注意:分开处理关联字段和普通字段
  2. params = copy.deepcopy(self.request.GET)
  3. url加一个params
  4. params[filter_field] = pk
  5. params[filter_field] = text
  6.  
  7. 每一次取数据都要保留 正在访问得 url 并加上正在访问得field
  8.  
  9. _url = params.urlencode()
  10. link_tag = "<a href='?%s'>%s</a>" % (_url, text)
  11.  
  12. 正在点击得,得加上样式 active
  13. if cid == str(pk) or cid == text:
  14. link_tag = "<a class='active' href='?%s'>%s</a>" % (_url, text)
  15. else:
  16. link_tag = "<a href='?%s'>%s</a>" % (_url, text)
  1.  
  1. 7、获取页面的url中的filter字段,后面进行delactive样式
  1. def get_filter_linktags(self):
  2. link_dic = {}
  3. for filter_field in self.config.list_filter: # ['title','publish','authors']
  4. # 1.获取url中的相关字段,后面比较
  5. current_id = self.request.GET.get(filter_field,0)
  6. pararms = copy.deepcopy(self.request.GET)
  1. 4.Q查询 and
  1. def list_view(self, request):
  2. ...
  3. ...
  4. # 获取filter得Q对象
  5. filter_condition = self.get_filter_condition(request)
  6.  
  7. # 筛选当前表得所有数据
  8. data_list = self.model.objects.all().filter(search_connection).filter(filter_condition)
  9. ...
  10. ...
  11.  
  12. # Q对象
  13. def get_filter_condition(self, request):
  14. filter_condition = Q() # 默认是 and 不是 or, 根据str,查找val
  15. for filter_field, val in request.GET.items():
  16. if filter_field in self.list_filter:
  17. filter_condition.children.append((filter_field, val))
  18.  
  19. return filter_condition
  1. 补充:
    Q查询根据字段
  1. bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))
  1. Q查询根据str
  1. filter_condition = Q()
  2. filter_consition.connector = "or" # 如果不写默认是 and
  3. filter_condition.children.append(("title","yuan"))
  4. filter_condition.children.append(("date","2018-12-12"))
  5.  
  6. Book.object.filter(filter_condition)

2、starkadmin.py

  1. from django.shortcuts import HttpResponse
  2. from stark.service import stark
  3. from .models import *
  4. from django.forms import ModelForm
  5.  
  6. class AuthorConfig(stark.ModelStark):
  7. list_display = ['nid', 'name', 'age']
  8. list_display_links = ['name','age']
  9.  
  10. class BookModelForm(ModelForm):
  11. class Meta:
  12. model = Book
  13. fields = "__all__"
  14.  
  15. labels = {
  16. "authors":"作者",
  17. "publishDate":"出版日期",
  18. }
  19.  
  20. class BookConfig(stark.ModelStark):
  21. list_display = ['title', 'price','publish','authors']
  22. list_display_links = ['title']
  23. modelform_class = BookModelForm
  24. search_fields = ['title','price']
  25. list_filter = ['title','publish','authors'] # 一对多,多对多字段
  26.  
  27. # 批量修改数据
  28. def patch_init(self,request,queryset):
  29. queryset.update(price=111)
  30.  
  31. # return HttpResponse("批量初始化OK")
  32.  
  33. patch_init.short_description = "批量初始化"
  34.  
  35. actions = [patch_init]
  36.  
  37. stark.site.register(Book,BookConfig)
  38. stark.site.register(Publish)
  39. stark.site.register(Author,AuthorConfig)
  40. stark.site.register(AuthorDetail)
  41.  
  42. # print(stark.site._registry)

3、stark/service/stark.py

  1. # -*- coding: utf-8 -*-
  2. # @Time : 2018/08/17 0017 14:46
  3. # @Author : Venicid
  4. from django.conf.urls import url
  5. from django.shortcuts import HttpResponse,render,redirect
  6.  
  7. from django.utils.safestring import mark_safe
  8. from django.urls import reverse
  9. from django.db.models import Q # 与或非
  10. from django.db.models.fields.related import ForeignKey
  11. from django.db.models.fields.related import ManyToManyField
  12. import copy
  13.  
  14. from stark.utils.page import Pagination
  15. class ShowList(object):
  16. def __init__(self,config, data_list,request):
  17. self.config = config # MOdelStark实例对象
  18. self.data_list = data_list # 数据
  19. self.request =request
  20.  
  21. # 分页
  22. data_count = self.data_list.count()
  23. current_page = int(self.request.GET.get('page',1))
  24. base_path = self.request.path
  25. self.pagination = Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=10, pager_count=11,)
  26.  
  27. # 分页后的数据
  28. self.page_data = self.data_list[self.pagination.start:self.pagination.end]
  29.  
  30. # actions 批量初始化,字段
  31. # self.actions = self.config.actions # [patch_init]
  32. self.actions = self.config.new_actions() # [pathch_delete,patch_init,]
  33. # 构建数据[{'name':'path_init',"desc":'xxxxx'}]
  34.  
  35. # filter的tag如何生成的
  36. def get_filter_linktags(self):
  37. link_dic = {}
  38. for filter_field in self.config.list_filter: # ['title','publish','authors']
  39. # 1.获取url中的相关字段,后面比较
  40. current_id = self.request.GET.get(filter_field,0)
  41. pararms = copy.deepcopy(self.request.GET)
  42.  
  43. # 2 页面生成 各种字段
  44. filter_field_obj = self.config.model._meta.get_field(filter_field)
  45. print(filter_field_obj,type(filter_field_obj))
  46. # app01.Book.publish < class 'django.db.models.fields.related.ForeignKey'>
  47. # app01.Book.authors < class 'django.db.models.fields.related.ManyToManyField'>
  48.  
  49. # print('rel...',filter_field_obj.re) # <ManyToOneRel: app01.book>
  50. # print('rel...',filter_field_obj.re.to.objects.all()) # <QuerySet [<Publish: 南京出版社>, <Publish: 北京出版社>]>
  51.  
  52. # 解决步骤
  53. # print('rel...',filter_field_obj.__dict__)
  54. # print('rel...',filter_field_obj.remote_field)
  55. # print('rel...',filter_field_obj.remote_field.__dict__)
  56. # print("rel...", filter_field_obj.remote_field.model.objects.all())
  57. # <QuerySet [<Publish: 南京出版社>, <Publish: 北京出版社>]>
  58. # <QuerySet [<Author: jack>, <Author: tom>]>
  59.  
  60. # 一对一字段or一对多字段
  61. if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
  62. data_list = filter_field_obj.remote_field.model.objects.all()
  63. else:
  64. # 普通字段
  65. data_list = self.config.model.objects.all().values('pk',filter_field)
  66.  
  67. # 3、 生成标签的href
  68. temp = []
  69. if pararms.get(filter_field):
  70. del pararms[filter_field]
  71. temp.append("<a href='?%s'>全部</a>"%pararms.urlencode())
  72. else:
  73. temp.append("<a href='#' class='active'>全部</a>")
  74.  
  75. # 处理filter字段的href
  76. for obj in data_list:
  77. # print(data_list)
  78. # 一对一,一对多字段
  79. if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
  80. pk = obj.pk
  81. text = str(obj)
  82. pararms[filter_field] = pk
  83. else:
  84. # 普通字段
  85. pk = obj.get('pk')
  86. text = obj.get(filter_field)
  87. pararms[filter_field] = text
  88.  
  89. _url = pararms.urlencode()
  90. # print(type(current_id),type(pk),type(text))
  91. if str(current_id) == str(pk) or str(current_id) ==str(text):
  92. link_tag = "<a href='?%s' class='active'>%s</a>"%(_url,text)
  93. else:
  94. link_tag = "<a href='?%s'>%s</a>"%(_url,text)
  95. temp.append(link_tag)
  96. link_dic[filter_field] = temp
  97.  
  98. return link_dic
  99.  
  100. def get_action_list(self):
  101. """action批量初始化,构架数据"""
  102. temp = []
  103. for action in self.actions:
  104. temp.append(
  105. {'name':action.__name__, # class的类名
  106. "desc":action.short_description # class的属性
  107. }
  108. )
  109. return temp
  110.  
  111. def get_header(self):
  112. # 构建表头
  113. header_list = [] # # header_list = ['选择','pk',...'操作','操作']
  114. for field in self.config.new_list_play():
  115. if callable(field):
  116. # header_list.append(field.__name__)
  117. val = field(self.config, header=True)
  118. header_list.append(val)
  119. else:
  120. if field == "__str__":
  121. header_list.append(self.config.model._meta.model_name.upper())
  122. else:
  123. val = self.config.model._meta.get_field(field).verbose_name # 中文名称
  124. header_list.append(val)
  125.  
  126. return header_list
  127.  
  128. def get_body(self):
  129. # 构建表单
  130. new_data_list = []
  131. for obj in self.page_data: #分页后的数据 # Book表模型,Author表模型
  132. temp = []
  133. for field in self.config.new_list_play(): # ['name','age']
  134. if callable(field): # edit() 可调用的
  135. # print(obj,99999999999999999)
  136. val = field(self.config,obj) # 直接调用edit()函数
  137. # print('val--------->',val)
  138. else:
  139. from django.db.models.fields.related import ManyToManyField
  140. field_obj = self.config.model._meta.get_field(field)
  141. if isinstance(field_obj,ManyToManyField):
  142. ret = getattr(obj,field).all() # 反射 obj是实例对象,name是方法
  143. t = []
  144. for obj in ret:
  145. t.append(str(obj))
  146. val = ','.join(t)
  147.  
  148. else:
  149. val = getattr(obj, field)
  150. # list_display_links 按钮
  151. if field in self.config.list_display_links:
  152. model_name = self.config.model._meta.model_name
  153. app_label = self.config.model._meta.app_label
  154. _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
  155. # print(_url)
  156. val = mark_safe("<a href='%s'>%s</a>"%(_url,val))
  157.  
  158. temp.append(val)
  159.  
  160. new_data_list.append(temp)
  161.  
  162. # print('new_data_list',new_data_list) # 构造数据 [['jack', 44], ['mark', 33]]
  163.  
  164. return new_data_list
  165.  
  166. class ModelStark(object):
  167. list_display = ["__str__"] # 子类中没有,直接用父类自己的
  168. list_display_links = []
  169. modelform_class = []
  170. search_fields = [] # 模糊查询字段
  171. actions = []
  172. list_filter = [] # 过滤字段
  173.  
  174. # 批量删除
  175. def patch_delete(self,request,queryset):
  176. queryset.delete()
  177.  
  178. patch_delete.short_description = "Delete selected "
  179.  
  180. def __init__(self,model, site):
  181. self.model = model
  182. self.site = site
  183.  
  184. # 增删改查url
  185. def get_add_url(self):
  186. model_name = self.model._meta.model_name
  187. app_label = self.model._meta.app_label
  188. _url = reverse("%s_%s_add" %(app_label,model_name))
  189. return _url
  190.  
  191. def get_list_url(self):
  192. model_name = self.model._meta.model_name
  193. app_label = self.model._meta.app_label
  194. _url = reverse("%s_%s_list" %(app_label,model_name))
  195. return _url
  196.  
  197. # 复选框,编辑,删除
  198. def checkbox(self,obj=None, header=False):
  199. if header:
  200. return mark_safe("<input id='choice' type='checkbox'>")
  201. return mark_safe("<input class='choice_item' type='checkbox' name='selected_pk' value='%s'>"%obj.pk)
  202.  
  203. def edit(self,obj=None, header=False):
  204. if header:
  205. return "操作"
  206. # 方案1:固定url
  207. # return mark_safe("<a href=/stark/app01/userinfo/%s/change>编辑</a>")
  208. # 方案2:拼接url
  209. # return mark_safe("<a href='%s/change'>编辑</a>")
  210.  
  211. # 方案3:反向解析
  212. model_name = self.model._meta.model_name
  213. app_label = self.model._meta.app_label
  214. _url = reverse("%s_%s_change"%(app_label,model_name),args=(obj.pk,))
  215. # print("_url",_url)
  216. return mark_safe("<a href='%s'>编辑</a>"%_url)
  217.  
  218. def deletes(self,obj=None, header=False):
  219. if header:
  220. return "操作"
  221. model_name = self.model._meta.model_name
  222. app_label = self.model._meta.app_label
  223. _url = reverse("%s_%s_delete"%(app_label,model_name),args=(obj.pk,))
  224. return mark_safe("<a href='%s'>删除</a>"%_url)
  225.  
  226. # ModelForm组件渲染 list、增、删、改页面
  227. def get_modelform_class(self):
  228. """ModelForm组件"""
  229. if not self.modelform_class:
  230. from django.forms import ModelForm
  231. class ModelFormDemo(ModelForm):
  232. class Meta:
  233. model = self.model
  234. fields = "__all__"
  235. return ModelFormDemo
  236. else:
  237. return self.modelform_class
  238.  
  239. def new_list_play(self):
  240. """构建 ['checkbox','pk', 'name', 'age', edit,'delete']"""
  241. temp = []
  242. temp.append(ModelStark.checkbox)
  243. temp.extend(self.list_display)
  244. if not self.list_display_links:
  245. temp.append(ModelStark.edit)
  246. temp.append(ModelStark.deletes)
  247. return temp
  248.  
  249. # action = ['delete',...]
  250. def new_actions(self):
  251. temp = []
  252. temp.append(ModelStark.patch_delete) # delete添加
  253. temp.extend(self.actions) # 如果定义新的,就扩展到temp中
  254. return temp
  255.  
  256. '''
  257. def list_view(self,request):
  258. ret1 = self.model.objects.filter(title__startswith='py')
  259. ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
  260. ret3 = self.model.objects.filter(price__range=[10,20])
  261. ret4 = self.model.objects.filter(title__contains='O')
  262. ret5 = self.model.objects.filter(title__icontains='O')
  263. return HttpResponse("过滤成功")
  264. '''
  265.  
  266. def get_search_condition(self,request):
  267. """search模糊查询"""
  268. key_word = request.GET.get("q",'')
  269. self.key_word = key_word
  270.  
  271. search_connection = Q()
  272. if key_word:
  273. search_connection.connector = "or"
  274. for search_field in self.search_fields:
  275. search_connection.children.append((search_field+"__contains", key_word))
  276.  
  277. return search_connection
  278.  
  279. def get_filter_condition(self,request):
  280. """filter过滤处理"""
  281. filter_condition = Q() # 并且
  282. for filter_field,val in request.GET.items():
  283. if filter_field in self.list_filter: # list_filter = ['publish','authors']
  284. filter_condition.children.append((filter_field,val))
  285. return filter_condition
  286.  
  287. def list_view(self, request):
  288. if request.method == 'POST':
  289. # print('post',request.POST)
  290. action = request.POST.get("action") # action': ['patch_init'],
  291. if action:
  292. selected_pk = request.POST.getlist('selected_pk') # 'selected_pk': ['5']}>
  293. action_func = getattr(self,action) # 反射查询 action # 取出实例方法
  294.  
  295. queryset = self.model.objects.filter(pk__in=selected_pk) # 查询
  296. ret = action_func(request,queryset) # 执行action() # 执行实例方法()
  297. # return ret
  298.  
  299. # 获取search的Q对象
  300. search_connection = self.get_search_condition(request)
  301.  
  302. # 获取filter构建Q对象
  303. filter_condition = self.get_filter_condition(request)
  304.  
  305. # 筛选获取当前表所有数据
  306. # data_list = self.model.objects.all().filter(search_connection)
  307. data_list = self.model.objects.all().filter(search_connection).filter(filter_condition)
  308.  
  309. #按照showlist展示页面, 构建表头,表单
  310. show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象
  311.  
  312. # 构建一个查看addurl
  313. add_url = self.get_add_url()
  314. return render(request,'list_view.html', locals())
  315.  
  316. def add_view(self, request):
  317. ModelFormDemo=self.get_modelform_class()
  318. form = ModelFormDemo()
  319. if request.method == "POST":
  320. form = ModelFormDemo(request.POST)
  321. if form.is_valid():
  322. form.save()
  323. return redirect(self.get_list_url())
  324.  
  325. return render(request, "add_view.html",locals())
  326.  
  327. def delete_view(self, request, id):
  328. url = self.get_list_url()
  329. if request.method == "POST":
  330. self.model.objects.filter(pk=id).delete()
  331. return redirect(url)
  332. return render(request, "delete_view.html", locals())
  333.  
  334. def change_view(self, request, id):
  335. edit_obj = self.model.objects.filter(pk=id).first()
  336.  
  337. ModelFormDemo=self.get_modelform_class()
  338. form = ModelFormDemo(instance=edit_obj)
  339. if request.method == "POST":
  340. form = ModelFormDemo(request.POST,instance=edit_obj)
  341. if form.is_valid():
  342. form.save()
  343. return redirect(self.get_list_url())
  344.  
  345. return render(request, "change_view.html",locals())
  346.  
  347. #构造 add/delete/change
  348. def get_urls2(self):
  349. model_name = self.model._meta.model_name
  350. app_label = self.model._meta.app_label
  351.  
  352. temp = []
  353. temp.append(url(r'^$', self.list_view, name='%s_%s_list'%(app_label,model_name)))
  354. temp.append(url(r'^add/', self.add_view, name='%s_%s_add'%(app_label,model_name)))
  355. temp.append(url(r'^(\d+)/delete/', self.delete_view, name='%s_%s_delete'%(app_label,model_name)))
  356. temp.append(url(r'^(\d+)/change/', self.change_view, name='%s_%s_change'%(app_label,model_name)))
  357.  
  358. return temp
  359.  
  360. @property
  361. def urls2(self):
  362.  
  363. return self.get_urls2(), None, None
  364.  
  365. class StarkSite(object):
  366. """site单例类"""
  367. def __init__(self):
  368. self._registry = {}
  369.  
  370. def register(self,model, stark_class=None):
  371. """注册"""
  372. if not stark_class:
  373. stark_class = ModelStark
  374.  
  375. self._registry[model] = stark_class(model,self)
  376.  
  377. def get_urls(self):
  378. """构造一层urls app01/book"""
  379. temp = []
  380. for model, stark_class_obj in self._registry.items():
  381. # print(model, 'stark_clas_obj', stark_class_obj) # 不同的model模型表
  382. """
  383. <class 'app01.models.UserInfo'> ----> <app01.starkadmin.UserConfig object at 0x00000072DDB65198>
  384. <class 'app01.models.Book'> ----> <stark.service.stark.ModelStark object at 0x00000072DDB65240>
  385. """
  386.  
  387. app_label = model._meta.app_label # app01
  388. model_name = model._meta.model_name # book
  389. # temp.append(url(r'^%s/%s'%(app_label, model_name),([],None,None)))
  390. temp.append(url(r'^%s/%s/'%(app_label, model_name),stark_class_obj.urls2))
  391. """
  392. path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
  393. path('app01/book/',ModelStark(Book,site).urls2),
  394. """
  395.  
  396. return temp
  397.  
  398. @property
  399. def urls(self):
  400.  
  401. # return [],None,None
  402. return self.get_urls(),None,None
  403.  
  404. site = StarkSite() # 单例对象

4、list_view.html

  1. {% extends 'base.html' %}
  2.  
  3. {% block title %}
  4. <title>list页面</title>
  5. {% endblock %}
  6.  
  7. {% block css %}
  8. <style type="text/css">
  9. .active {
  10. color: red !important;
  11. }
  12.  
  13. .filter a {
  14. text-decoration: none;
  15. color: grey;
  16. }
  17. </style>
  18. {% endblock %}
  19. {% block content %}
  20. <div class="col-md-9">
  21.  
  22. <a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
  23.  
  24. {% if show_list.config.search_fields %}
  25. <form action="" method="get">
  26. <input type="text" class="form-control" style="width: 30%;display: inline-block;margin-top: 8px"
  27. name="q"
  28. value="{{ show_list.config.key_word }}">
  29. <button class="btn btn-success">submit</button>
  30. </form>
  31. {% endif %}
  32.  
  33. <form action="" method="post">
  34. {% csrf_token %}
  35. <select name="action" class="form-control"
  36. style="display: inline-block;width: 200px;margin: 8px 8px 8px 0;height: 35px;vertical-align: -2px">
  37. <option value="">-------</option>
  38. {% for item in show_list.get_action_list %}
  39. <option value="{{ item.name }}">{{ item.desc }}</option>
  40. {% endfor %}
  41. </select>
  42. <button type="submit" class="btn btn-primary">Go</button>
  43.  
  44. <table class="table table-bordered table-striped">
  45. <tr>
  46. {% for header in show_list.get_header %}
  47. {# {% for header in header_list %}#}
  48. <th>{{ header }}</th>
  49. {% endfor %}
  50. </tr>
  51.  
  52. {% for data in show_list.get_body %}
  53. {# {% for data in new_data_list %}#}
  54. <tr>
  55. {% for item in data %}
  56. <td>{{ item }}</td>
  57. {% endfor %}
  58.  
  59. </tr>
  60. {% endfor %}
  61. </table>
  62. </form>
  63.  
  64. <nav>
  65. <ul class="pagination">
  66. {{ show_list.pagination.page_html|safe }}
  67. </ul>
  68. </nav>
  69. </div>
  70. <div class="col-md-3">
  71. <div class="filter">
  72. {% for filter_field, linktags in show_list.get_filter_linktags.items %}
  73.  
  74. <div class="well">
  75. <p>{{ filter_field.upper }}</p>
  76.  
  77. {% for link in linktags %}
  78. <p>{{ link|safe }}</p>
  79. {% endfor %}
  80.  
  81. </div>
  82.  
  83. {% endfor %}
  84.  
  85. </div>
  86. </div>
  87. {% endblock %}
  88.  
  89. {% block javascript %}
  90. <script type="text/javascript">
  91. $('#choice').click(function () {
  92. if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
  93. $('.choice_item').prop("checked", true)
  94. } else {
  95. $('.choice_item').prop("checked", false)
  96. }
  97. })
  98. </script>
  99. {% endblock %}

stark组件之delete按钮、filter过滤的更多相关文章

  1. 11 stark组件之delete按钮、filter过滤

    1.构建批量删除按钮 1.admin中每个页面默认都有 2.stark之构建批量删除 3.coding {% extends 'base.html' %} {% block title %} < ...

  2. stark组件之pop页面,按钮,url,页面

      1.Window open() 方法 2.admin的pop添加按钮 3.stark之pop功能 3.知识点总结 4.coding代码 1.Window open() 方法 效果图   2.adm ...

  3. 12 stark组件之pop,按钮,url,页面

    1.Window open() 方法 http://www.runoob.com/jsref/met-win-open.html 效果图   2.admin的pop添加按钮 3.stark之pop功能 ...

  4. day 69crm(6) stark组件 action 和 多层过滤效果

      前情提要: 今天学的是stark 组件的 action  和多层过效果 一: action (自定制函数多选功能效果) 1: 学习 观点明确:     2: 多选效果前端和后端进行的操作   2& ...

  5. 【django之stark组件】

    一.需求 仿照django的admin,开发自己的stark组件.实现类似数据库客户端的功能,对数据进行增删改查. 二.实现 1.在settings配置中分别注册这三个app # Applicatio ...

  6. django 之 stark组件

    ----------------------------------------------------------------烦恼没完没了,内心动荡不安,呜呼哀哉. 一.有个特殊的需求,需要用sta ...

  7. stark组件的分页,模糊查询,批量删除

    1.分页组件高阶 2.整合展示数据showlist类 3.stark组件之分页 3.stark组件之search模糊查询 4.action批量处理数据 4.总结 1.分页组件高阶 1.分页的class ...

  8. stark组件之创建

    stark组件之需求 仿照Django中的admin , 开发了自己的stark组件,实现类似数据库客户端的功能,对数据进行增删改查 . stark之创建 1.在项目中 创建stark应用,app01 ...

  9. crm项目-stark组件

    ###############  admin基本认识和常用的定制功能    ############### stark组件 对admin的基本认识 1,就是一个app,嵌入到了django里面,你可以 ...

随机推荐

  1. centOS7docker安装oracle

    1.拉取oracle 11g 的镜像: 用root登陆服务器,输入下面的命令,拉取oracle 11g的镜像,有点大,6.8G多: docker pull registry.cn-hangzhou.a ...

  2. June 18. 2018, Week 25th. Monday

    Health and cheerfulness naturally beget each other. 安康喜乐,相生相成. From Joseph Addison. Good health is a ...

  3. Spring的AOP基于AspectJ的注解方式开发3

    上上偏博客介绍了@Aspect,@Before 上篇博客介绍了spring的AOP开发的注解通知类型:@Before,@AfterThrowing,@After,@AfterReturning,@Ar ...

  4. js格式化输入框内金额、银行卡号[转]

    这篇文章主要介绍了js格式化输入框内金额.银行卡号,采用“keyup”事件处理格式化,每4位数一组中间空格隔开,如何格式化输入框内金额.银行卡号,需要了解的朋友可以参考一下 我们在项目中经常遇到需要格 ...

  5. D. Equalize Them All Codeforces Round #550 (Div. 3)

    D. Equalize Them All time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  6. django ORM的总结

    1.django分表的方案:   https://mp.weixin.qq.com/s?__biz=MjM5NjA3Nzk3Ng==&mid=2648154502&idx=1& ...

  7. centos7下如何隐藏nginx的版本号

    我们在访问nginx的时候会暴露nginx的版本号,如何将这些版本号隐藏呢? 其实隐藏版本号非常简单 在nginx的配置文件中添加一个server——tokens  off:参数就可以了,下面进行操作 ...

  8. P1553 数字反转(升级版)(模拟)

    花了2个小时,写的..mmp只想说,还是我太菜了. #include<iostream> #include<cstring> using namespace std; ]; i ...

  9. Nginx 反向代理 -- 一路上的坑转载

    个人学习之用转子https://www.cnblogs.com/xjbBill/p/7477825.html 前些天刚过来新公司上班,公司的项目都挺多的,只不过项目都是第三方公司团队开发的,现在本公司 ...

  10. 【vue】vue +element prop用法

    简单demo 父组件:index.vue <template> <div class="app-container"> <vue-props-demo ...