- 1、分页组件高阶
- 2、整合展示数据showlist类
- 3、stark组件之分页
- 3、stark组件之search模糊查询
- 4、action批量处理数据
- 4、总结
1、分页组件高阶
1、分页的class形式(有bug,请看下面的)
"""
自定义分页组件 """ class Pagination(object):
# def __init__(self, data_num, current_page, url_prefix, params, per_page=10, max_show=3):
def __init__(self, data_num, current_page, url_prefix,per_page=10, max_show=3):
"""
进行初始化.
:param data_num: 数据总数
:param current_page: 当前页
:param url_prefix: 生成的页码的链接前缀
:param per_page: 每页显示多少条数据
:param max_show: 页面最多显示多少个页码
"""
self.data_num = data_num
self.per_page = per_page
self.max_show = max_show
self.url_prefix = url_prefix # 把页码数算出来
self.page_num, more = divmod(data_num, per_page)
if more:
self.page_num += 1 try:
self.current_page = int(current_page)
except Exception as e:
self.current_page = 1
# 如果URL传过来的页码数是负数
if self.current_page <= 0:
self.current_page = 1
# 如果URL传过来的页码数超过了最大页码数
elif self.current_page > self.page_num:
self.current_page = self.page_num # 默认展示最后一页 # 页码数的一半 算出来
self.half_show = max_show // 2 # 页码最左边显示多少
if self.current_page - self.half_show <= 1:
self.page_start = 1
self.page_end = self.max_show
elif self.current_page + self.half_show >= self.page_num: # 如果右边越界
self.page_end = self.page_num
self.page_start = self.page_num - self.max_show
else:
self.page_start = self.current_page - self.half_show
# 页码最右边显示
self.page_end = self.current_page + self.half_show # import copy
# self.params = copy.deepcopy(params) # {"page":"12","title_startwith":"py","id__gt":"5"} @property
def start(self):
# 数据从哪儿开始切
return (self.current_page - 1) * self.per_page @property
def end(self):
# 数据切片切到哪儿
return self.current_page * self.per_page def page_html(self):
# 生成页码
l = []
# 加一个首页
l.append('<li><a href="{}?page=1">首页</a></li>'.format(self.url_prefix))
# 加一个上一页
if self.current_page == 1:
l.append('<li class="disabled" ><a href="#">«</a></li>'.format(self.current_page))
else:
l.append('<li><a href="{}?page={}">«</a></li>'.format(self.url_prefix, self.current_page - 1)) # {"page":"12","title_startwith":"py","id__gt":"5"} # "page=12&title_startwith=py&id__gt=5"
# print(self.params.urlencode()) for i in range(self.page_start, self.page_end + 1):
# self.params["page"] = i # {"page":"7","title_startwith":"py","id__gt":"5"} # "page=7&title_startwith=py&id__gt=5"
if i == self.current_page:
tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
else:
# tmp = '<li><a href="{0}?{1}">{2}</a></li>'.format(self.url_prefix, self.params.urlencode(), i)
tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
l.append(tmp) # 加一个下一页
if self.current_page == self.page_num:
l.append('<li class="disabled"><a href="#">»</a></li>'.format(self.current_page))
else:
l.append('<li><a href="{}?page={}">»</a></li>'.format(self.url_prefix, self.current_page + 1))
# 加一个尾页
l.append('<li><a href="{}?page={}">尾页</a></li>'.format(self.url_prefix, self.page_num))
return "".join(l)
from django.shortcuts import render,HttpResponse # Create your views here. from .models import *
def index(request):
'''
# 生成假数据
book_list=[]
for i in range(500):
book_obj=Book(title="book_%s"%i,price=i*i)
book_list.append(book_obj)
Book.objects.bulk_create(book_list)
'''
base_url = request.path # /index/ # 当前url路径
current_page=request.GET.get("page",1) # 获取当前url中的page
all_count=Book.objects.all().count() # 所有book数据多少条 # 分页器
from app01.utils.page import Pagination pagination=Pagination(all_count,int(current_page),base_url,per_page=10, max_show=11)
# pagination=Pagination(all_count,int(current_page),base_url,request.GET,per_page=10, max_show=11)
# 所有数据条数,当前页的page=3,当前url路径,request.GET请求,每页显示数据,分页器最大展示几个项目 print(pagination.start)
print(pagination.end) book_list =Book.objects.all()[pagination.start:pagination.end] # 对数据进行切片 from django.http.request import QueryDict
# dic = QueryDict(mutable=True)
# dic["info"] = 123 # print(type(request.GET))
# request.GET["info"]=123 import copy
params=copy.deepcopy(request.GET)
params["xxx"]=123 return render(request,"index.html",locals())
Views
from django.db import models # Create your models here. class Book(models.Model):
title=models.CharField(max_length=32)
price=models.DecimalField(max_digits=8,decimal_places=2) def __str__(self):
return self.title
models
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body> <ul>
{% for foo in book_list %}
<li>{{ foo }}</li>
{% endfor %} </ul>
<nav>
<ul class="pagination">
{{ pagination.page_html|safe }}
</ul>
</nav> </body>
</html>
index.html
扩展分页组件:
分页的是一个一个固定URL的a标签。
class Pagination(object):
def __init__():
在分页内加一个request.GET的参数.
在视图使用分分页器的时候,加一个request.GET参数
分页器内加一个形参params 接受request.GET import copy
self.params=copy.deepcopy(params)
应该把传过来的request.GET(是一个键值对),变成urlencode.
通过{{ }}动态的传入前端a标签的href. self.params["page"] ==i 把循环的页面赋值给这个request.GET
首先要做的是把list_view的函数进行一下封装,因为内容太多了。
2、如何扩展分页
2、整合展示数据showlist类
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]] # 构建一个addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals())
list_view函数形式
showlist类
def list_view(self, request):
# print(self.model) # <class 'app01.models.Book'> 用户访问的模型表
data_list = self.model.objects.all() # [obj1,obj2,...] # 构建表头,表单
show_list = ShowList(self,data_list) # self=ModelSTark实例对象 # 构建一个addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals())
class ShowList(object):
def __init__(self,config, data_list):
self.config = config # MOdelStark实例对象
self.data_list = data_list # 数据 def get_header(self):
# 构建表头
header_list = [] # # header_list = ['选择','pk',...'操作','操作']
for field in self.config.new_list_play():
if callable(field):
# header_list.append(field.__name__)
val = field(self.config,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.data_list: # Book表模型,Author表模型
temp = []
for field in self.config.new_list_play(): # ['name','age']
if callable(field): # edit() 可调用的
val = field(self.config,obj) # 直接调用edit()函数
print('val--------->',val)
else:
val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮
if field in self.config.list_display_links:
model_name = self.config.model._meta.model_name
app_label = self.config.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 new_data_list
3、stark组件之分页
stark/service/stark.py
# -*- coding: utf-8 -*-
# @Time : 2018/08/17 0017 14:46
# @Author : Venicid
from django.conf.urls import url
from django.shortcuts import HttpResponse,render,redirect from django.utils.safestring import mark_safe
from django.urls import reverse from stark.utils.page import Pagination
class ShowList(object):
def __init__(self,config, data_list,request):
self.config = config # MOdelStark实例对象
self.data_list = data_list # 数据
self.request =request # 分页
data_count = self.data_list.count()
current_page = int(self.request.GET.get('page',1))
base_path = self.request.path
self.pagination = Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=1, pager_count=11,) # 分页后的数据
self.page_data = self.data_list[self.pagination.start:self.pagination.end] def get_header(self):
# 构建表头
header_list = [] # # header_list = ['选择','pk',...'操作','操作']
for field in self.config.new_list_play():
if callable(field):
# header_list.append(field.__name__)
val = field(self.config,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: #分页后的数据 # Book表模型,Author表模型
temp = []
for field in self.config.new_list_play(): # ['name','age']
if callable(field): # edit() 可调用的
val = field(self.config,obj) # 直接调用edit()函数
print('val--------->',val)
else:
val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮
if field in self.config.list_display_links:
model_name = self.config.model._meta.model_name
app_label = self.config.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 new_data_list class ModelStark(object):
list_display = ["__str__"] # 子类中没有,直接用父类自己的
list_display_links = [] modelform_class = [] def __init__(self,model, site):
self.model = model
self.site = site # 增删改查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 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) # ModelForm组件渲染 list、增、删、改页面
def get_modelform_class(self):
"""ModelForm组件"""
if not self.modelform_class:
from django.forms import ModelForm
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class 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'> 用户访问的模型表
data_list = self.model.objects.all() # [obj1,obj2,...] # 构建表头,表单
show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象 # 构建一个addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals()) def add_view(self, request):
ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo()
if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "add_view.html",locals()) def delete_view(self, request, id):
url = self.get_list_url()
if request.method == "POST":
self.model.objects.filter(pk=id).delete()
return redirect(url)
return render(request, "delete_view.html", locals()) def change_view(self, request, id):
edit_obj = self.model.objects.filter(pk=id).first() ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo(instance=edit_obj)
if request.method == "POST":
form = ModelFormDemo(request.POST,instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "change_view.html",locals()) #构造 add/delete/change
def get_urls2(self):
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_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))) 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() # 单例对象
stark/utils/page.py(自定义分页,新版本)【旧的有bug】
"""
自定义分页组件
""" class Pagination(object):
def __init__(self, current_page, all_count, base_url,params, per_page_num=8, pager_count=11, ):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param base_url: 分页中显示的URL前缀
:param pager_count: 最多显示的页码个数
""" try:
current_page = int(current_page)
except Exception as e:
current_page = 1 if current_page < 1:
current_page = 1 self.current_page = current_page self.all_count = all_count
self.per_page_num = per_page_num self.base_url = base_url # 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager self.pager_count = pager_count # 最多显示页码数
self.pager_count_half = int((pager_count - 1) / 2) import copy
params = copy.deepcopy(params)
params._mutable = True
self.params = params # self.params : {"page":77,"title":"python","nid":1} @property
def start(self):
return (self.current_page - 1) * self.per_page_num @property
def end(self):
return self.current_page * self.per_page_num def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示(11-1)/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1 # 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_start = self.all_pager - self.pager_count + 1
pager_end = self.all_pager + 1 else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1 page_html_list = []
self.params["page"] = 1
first_page = '<li><a href="%s?%s">首页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(first_page) if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
self.params["page"] = self.current_page - 1
prev_page = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.params.urlencode(),) page_html_list.append(prev_page) for i in range(pager_start, pager_end):
# self.params : {"page":77,"title":"python","nid":1} self.params["page"] = i # {"page":72,"title":"python","nid":1}
if i == self.current_page:
temp = '<li class="active"><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)
else:
temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)
page_html_list.append(temp) if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
self.params["page"] = self.current_page + 1
next_page = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(next_page) self.params["page"] = self.all_pager
last_page = '<li><a href="%s?%s">尾页</a></li>' % (self.base_url, self.params.urlencode(),)
page_html_list.append(last_page) return ''.join(page_html_list)
list_view.html
{% extends 'base.html' %} {% block title %}
<title>list页面</title>
{% endblock %} {% block header %}
<h3>list页面</h3>
{% endblock %}
{% block content %}
<a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
<table class="table table-bordered table-striped">
<tr>
{% for header in show_list.get_header %}
{# {% for header in header_list %}#}
<th>{{ header }}</th>
{% endfor %}
</tr> {% for data in show_list.get_body %}
{# {% for data in new_data_list %}#}
<tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %}
</table>
<nav>
<ul class="pagination">
{{ show_list.pagination.page_html|safe }}
</ul>
</nav> {% endblock %} {% block javascript %}
<script type="text/javascript">
$('#choice').click(function () {
if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
$('.choice_item').prop("checked", true)
} else {
$('.choice_item').prop("checked", false)
}
})
</script>
{% endblock %}
全部封装在一个类里:
class ShowList(object):
'''
将展示页面的表头和数据封装到这个类中,分别调用方法返回列表
'''
def __init__(self,config,data_list,request):
self.config=config #这个就是那个modelStark的实例对象。拥有modelstark所有属性和方法
self.data_list=data_list #需要展示的数据
self.request=request #加入分页器
data_count=self.data_list.count() #数据个数
current_page=int(self.request.GET.get("page",1)) #当前页数
base_path=self.request.path
self.pagination=Pagination(current_page,data_count,base_path,self.request.GET, per_page_num=4, pager_count=11,) #将数据进行分页,调用原有的分页器。
self.page_Data=self.data_list[self.pagination.start:self.pagination.end] #将数据进行一个切片。 #actions
self.actions=self.config.actions #首先拿到自定制的action列表 def get_action_list(self):
temp=[]
for action in self.actions:
temp.append({
"name":action.__name__,
"desc":action.short_description
}) #上诉方法把action做成这个样子,一个是取到方法名一个是取到中文描述
#[{"name":patch_init,"desc":"批量初始化"}]
return temp 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:
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))
temp.append(val) new_data_list.append(temp)
return new_data_list
3、stark组件之search模糊查询
1、orm中的模糊查询
2、orm中的Q查询 与或非
3、stark组件之模糊查询
def list_view(self, request):
# print(self.model) # <class 'app01.models.Book'> 用户访问的模型表 # 模糊查询过滤
key_word = request.GET.get("q")
from django.db.models import Q # 与或非
search_connection = Q()
if key_word:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_word)) data_list = self.model.objects.all().filter(search_connection) #按照showlist展示页面, 构建表头,表单
show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象 # 构建一个查看addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals())
4、解耦
如果没有在starkadmin定义search_fields字段,就不显示search按钮
6、代码
# -*- coding: utf-8 -*-
# @Time : 2018/08/17 0017 14:46
# @Author : Venicid
from django.conf.urls import url
from django.shortcuts import HttpResponse,render,redirect from django.utils.safestring import mark_safe
from django.urls import reverse from stark.utils.page import Pagination
class ShowList(object):
def __init__(self,config, data_list,request):
self.config = config # MOdelStark实例对象
self.data_list = data_list # 数据
self.request =request # 分页
data_count = self.data_list.count()
current_page = int(self.request.GET.get('page',1))
base_path = self.request.path
self.pagination = Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=11, pager_count=11,) # 分页后的数据
self.page_data = self.data_list[self.pagination.start:self.pagination.end] def get_header(self):
# 构建表头
header_list = [] # # header_list = ['选择','pk',...'操作','操作']
for field in self.config.new_list_play():
if callable(field):
# header_list.append(field.__name__)
val = field(self.config,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: #分页后的数据 # Book表模型,Author表模型
temp = []
for field in self.config.new_list_play(): # ['name','age']
if callable(field): # edit() 可调用的
val = field(self.config,obj) # 直接调用edit()函数
print('val--------->',val)
else:
val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮
if field in self.config.list_display_links:
model_name = self.config.model._meta.model_name
app_label = self.config.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 new_data_list class ModelStark(object):
list_display = ["__str__"] # 子类中没有,直接用父类自己的
list_display_links = []
modelform_class = []
search_fields = [] # 模糊查询字段 def __init__(self,model, site):
self.model = model
self.site = site # 增删改查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 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) # ModelForm组件渲染 list、增、删、改页面
def get_modelform_class(self):
"""ModelForm组件"""
if not self.modelform_class:
from django.forms import ModelForm
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class 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):
ret1 = self.model.objects.filter(title__startswith='py')
ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
ret3 = self.model.objects.filter(price__range=[10,20])
ret4 = self.model.objects.filter(title__contains='O')
ret5 = self.model.objects.filter(title__icontains='O')
return HttpResponse("过滤成功")
''' def get_search_condition(self,request):
"""search模糊查询"""
key_word = request.GET.get("q",'')
self.key_word = key_word
from django.db.models import Q # 与或非
search_connection = Q()
if key_word:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_word)) return search_connection def list_view(self, request):
# 获取search的Q对象
search_connection = self.get_search_condition(request) # 筛选获取当前表所有数据
data_list = self.model.objects.all().filter(search_connection) #按照showlist展示页面, 构建表头,表单
show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象 # 构建一个查看addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals()) def add_view(self, request):
ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo()
if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "add_view.html",locals()) def delete_view(self, request, id):
url = self.get_list_url()
if request.method == "POST":
self.model.objects.filter(pk=id).delete()
return redirect(url)
return render(request, "delete_view.html", locals()) def change_view(self, request, id):
edit_obj = self.model.objects.filter(pk=id).first() ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo(instance=edit_obj)
if request.method == "POST":
form = ModelFormDemo(request.POST,instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "change_view.html",locals()) #构造 add/delete/change
def get_urls2(self):
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_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))) 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() # 单例对象
stark/service/stark.py
from stark.service import stark
from .models import *
from django.forms import ModelForm class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__" labels = {
"authors":"作者",
"publishDate":"出版日期",
} class BookConfig(stark.ModelStark):
list_display = ['nid', 'title', 'price']
modelform_class = BookModelForm
# search_fields = ['title','price'] class AuthorConfig(stark.ModelStark):
list_display = ['nid', 'name', 'age']
list_display_links = ['name','age'] stark.site.register(Book,BookConfig)
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>}
"""
starkadmin.py
{% extends 'base.html' %} {% block title %}
<title>list页面</title>
{% endblock %} {% block header %}
<h3>list页面</h3>
{% endblock %}
{% block content %}
<a class="btn btn-primary" href="{{ add_url }}">添加数据</a>
{% if show_list.config.search_fields %}
<form action="" method="get" class="pull-right">
<input type="text" name="q" value="{{ show_list.config.key_word }}">
<button>submit</button>
</form>
{% endif %} <table class="table table-bordered table-striped">
<tr>
{% for header in show_list.get_header %}
{# {% for header in header_list %}#}
<th>{{ header }}</th>
{% endfor %}
</tr> {% for data in show_list.get_body %}
{# {% for data in new_data_list %}#}
<tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %}
</table>
<nav>
<ul class="pagination">
{{ show_list.pagination.page_html|safe }}
</ul>
</nav> {% endblock %} {% block javascript %}
<script type="text/javascript">
$('#choice').click(function () {
if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
$('.choice_item').prop("checked", true)
} else {
$('.choice_item').prop("checked", false)
}
})
</script>
{% endblock %}
list_view.html
代码解析:
#设定一个search_fields=[],用户自定义好字段后,进行下一步。
{% if showlist.config.serach_fields %}
<form action="" class="pull-right">
<input type="text" name="q" value="{{ showlist.config.key_word }}" class="form-control">
<button class="btn btn-default pull-right">搜索</button>
</form>
{% endif %}
#首先在前端加一个框,然后在将提交的name设为q。
第二步:
#下面函数取到get请求过来的数据。
def get_serach_conditon(self,request):
key_word = request.GET.get("q","") #从前端拿到q
self.key_word=key_word #然后赋给self.
from django.db.models import Q
search_connection = Q() #生成一个Q()对象
if key_word: #如果请求有值,表示真实搜索。
# self.search_fields # ["title","price"]
search_connection.connector = "or" #Q对象使用“或”查询。
#在这里组建一个Q对象,需要将列表内的字符串把引号去掉,并且这个Q对象是或的关系,最后返回
for search_field in self.serach_fields: #遍历每一个字段,加上__contains
search_connection.children.append((search_field + "__contains", key_word))
return search_connection
#之所以这么麻烦的创建Q对象,创建或关系,是因为model查询的是price=123,而search_fields是字符串,只有这样才能把字符串去掉。
第三部:
#视图中获取Q对象:
search_connection=self.get_serach_conditon(request) #获取当前表筛选之后的数据,没有筛选条件则为全部
data_list = self.model.objects.all().filter(search_connection) #按这个类的方法进行展示
showlist=ShowList(self,data_list,request)
#前端模板全部使用showlist.config.key_word,showlist.get_header,showlist.get_body,{{ showlist.pagination.page_html|safe }}这种的去进行渲染。 #然后通过字段__contains可以模糊匹配到值,并且展示。
4、action批量处理数据
0、必备知识
1、admin的批量初始化
3、starkadmin之actions
老样子,自定义一个列表,放入需要执行的函数名。
self.actions=self.config.actions
4、构建actions数据
def get_action_list(self):
temp=[]
for action in self.actions:
temp.append({
"name":action.__name__,
"desc":action.short_description
})
#[{"name":patch_init,"desc":"批量初始化"}]
return temp
#在ShowList这个类中对这个列表进行修改,变成如上一样列表套字典的结构。
5、前端的按钮checkbox,提交数据
#这样在前端模板中使用:
<select name="action" id="" style="width:150px;margin-top: 10px;margin-bottom: 10px ;padding: 4px 8px;display: inline-block">
<option value="">--------------</option>
{% for item in showlist.get_action_list %}
<option value="{{ item.name }}">{{ item.desc }}</option>
{% endfor %}
</select>
进行一波渲染,将这个列表渲染进去。这样选中某个方法,前端传回到后端一个action的列表,
取到这个列表即可知道你选的哪个。
return mark_safe("<input class='choice_item' value='%s' type='checkbox' name='selected_pk'>"%obj.pk)
在checkbox中加入一个name,和每个字段的主键值,这样选中后上传到后台的是一个
'selected_pk': ['', '']这种类型的列表。
6、post提交处理 数据
#最后这个form表单不同于搜索的是,这个是post请求,所以在视图函数中需要处理的是post请求。
if request.method == "POST":
print(request.POST)
action=request.POST.get("action")
select_pk=request.POST.getlist("selected_pk")
queryset=self.model.objects.filter(pk__in=select_pk)
action_func=getattr(self,action)
action_func(request,queryset)
#首先取到方法名字,然后取到选中的主键值,这里注意需要用到gellist,不然只会取到一个。
# 然后利用queryset=self.model.objects.filter(pk__in=select_pk),利用In可以取到一个
queryset。#将这个queryset以后,传入需要执行的函数作为参数以后,方法执行update或者delete
#等等各种操作就非常容易了。这样就可以进行批量的修改了。
6、starkadmin.py
from django.shortcuts import HttpResponse
from stark.service import stark
from .models import *
from django.forms import ModelForm class AuthorConfig(stark.ModelStark):
list_display = ['nid', 'name', 'age']
list_display_links = ['name','age'] class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__" labels = {
"authors":"作者",
"publishDate":"出版日期",
} class BookConfig(stark.ModelStark):
list_display = ['nid', 'title', 'price']
modelform_class = BookModelForm
search_fields = ['title','price'] # 批量修改数据
def patch_init(self,request,queryset):
queryset.update(price=111) # return HttpResponse("批量初始化OK") patch_init.short_description = "批量初始化" actions = [patch_init] stark.site.register(Book,BookConfig)
stark.site.register(Publish)
stark.site.register(Author,AuthorConfig)
stark.site.register(AuthorDetail) print(stark.site._registry)
7、stark/service /stark
# -*- coding: utf-8 -*-
# @Time : 2018/08/17 0017 14:46
# @Author : Venicid
from django.conf.urls import url
from django.shortcuts import HttpResponse,render,redirect from django.utils.safestring import mark_safe
from django.urls import reverse from stark.utils.page import Pagination
class ShowList(object):
def __init__(self,config, data_list,request):
self.config = config # MOdelStark实例对象
self.data_list = data_list # 数据
self.request =request # 分页
data_count = self.data_list.count()
current_page = int(self.request.GET.get('page',1))
base_path = self.request.path
self.pagination = Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=11, pager_count=11,) # 分页后的数据
self.page_data = self.data_list[self.pagination.start:self.pagination.end] # actions 批量初始化,字段
self.actions = self.config.actions # [patch_init]
# 构建数据[{'name':'path_init',"desc":'xxxxx'}] def get_action_list(self):
"""action批量初始化,构架数据"""
temp = []
for action in self.actions:
temp.append(
{'name':action.__name__, # class的类名
"desc":action.short_description # class的属性
}
)
return temp def get_header(self):
# 构建表头
header_list = [] # # header_list = ['选择','pk',...'操作','操作']
for field in self.config.new_list_play():
if callable(field):
# header_list.append(field.__name__)
val = field(self.config, 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: #分页后的数据 # Book表模型,Author表模型
temp = []
for field in self.config.new_list_play(): # ['name','age']
if callable(field): # edit() 可调用的
print(obj,99999999999999999)
val = field(self.config,obj) # 直接调用edit()函数
print('val--------->',val)
else:
val = getattr(obj,field) # 反射 obj是实例对象,name是方法 # list_display_links 按钮
if field in self.config.list_display_links:
model_name = self.config.model._meta.model_name
app_label = self.config.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 new_data_list class ModelStark(object):
list_display = ["__str__"] # 子类中没有,直接用父类自己的
list_display_links = []
modelform_class = []
search_fields = [] # 模糊查询字段
actions = [] def __init__(self,model, site):
self.model = model
self.site = site # 增删改查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 checkbox(self,obj=None, header=False):
if header:
return mark_safe("<input id='choice' type='checkbox'>")
return mark_safe("<input class='choice_item' type='checkbox' name='selected_pk' value='%s'>"%obj.pk) 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) # ModelForm组件渲染 list、增、删、改页面
def get_modelform_class(self):
"""ModelForm组件"""
if not self.modelform_class:
from django.forms import ModelForm
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
return ModelFormDemo
else:
return self.modelform_class 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):
ret1 = self.model.objects.filter(title__startswith='py')
ret2 = self.model.objects.filter(price__in=[11,22,33,44,55])
ret3 = self.model.objects.filter(price__range=[10,20])
ret4 = self.model.objects.filter(title__contains='O')
ret5 = self.model.objects.filter(title__icontains='O')
return HttpResponse("过滤成功")
''' def get_search_condition(self,request):
"""search模糊查询"""
key_word = request.GET.get("q",'')
self.key_word = key_word
from django.db.models import Q # 与或非
search_connection = Q()
if key_word:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_word)) return search_connection def list_view(self, request):
if request.method == 'POST':
print('post',request.POST)
action = request.POST.get("action") # action': ['patch_init'],
if action:
selected_pk = request.POST.getlist('selected_pk') # 'selected_pk': ['5']}>
action_func = getattr(self,action) # 反射查询 action queryset = self.model.objects.filter(pk__in=selected_pk) # 查询
ret = action_func(request,queryset) # 执行action()
# return ret # 获取search的Q对象
search_connection = self.get_search_condition(request) # 筛选获取当前表所有数据
data_list = self.model.objects.all().filter(search_connection) #按照showlist展示页面, 构建表头,表单
show_list = ShowList(self,data_list,request) # self=ModelSTark实例对象 # 构建一个查看addurl
add_url = self.get_add_url()
return render(request,'list_view.html', locals()) def add_view(self, request):
ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo()
if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "add_view.html",locals()) def delete_view(self, request, id):
url = self.get_list_url()
if request.method == "POST":
self.model.objects.filter(pk=id).delete()
return redirect(url)
return render(request, "delete_view.html", locals()) def change_view(self, request, id):
edit_obj = self.model.objects.filter(pk=id).first() ModelFormDemo=self.get_modelform_class()
form = ModelFormDemo(instance=edit_obj)
if request.method == "POST":
form = ModelFormDemo(request.POST,instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "change_view.html",locals()) #构造 add/delete/change
def get_urls2(self):
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_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))) 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() # 单例对象
8、list_view.html
{% extends 'base.html' %} {% block title %}
<title>list页面</title>
{% endblock %} {% block header %}
<h3>list页面</h3>
{% endblock %}
{% block content %}
<p><a class="btn btn-primary" href="{{ add_url }}">添加数据</a></p>
{% if show_list.config.search_fields %}
<form action="" method="get" class="pull-right">
<input type="text" name="q" value="{{ show_list.config.key_word }}">
<button>submit</button>
</form>
{% endif %} <form action="" method="post">
{% csrf_token %} {% if show_list.get_action_list %}
<select name="action" id="" style="display: inline-block;width: 200px;margin: 8px 8px 8px 0;height: 25px">
{% for item in show_list.get_action_list %}
<option value="">-------</option>
<option value="{{ item.name }}">{{ item.desc }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-default">Go</button> {% endif %} <table class="table table-bordered table-striped">
<tr>
{% for header in show_list.get_header %}
{# {% for header in header_list %}#}
<th>{{ header }}</th>
{% endfor %}
</tr> {% for data in show_list.get_body %}
{# {% for data in new_data_list %}#}
<tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %}
</table>
</form> <nav>
<ul class="pagination">
{{ show_list.pagination.page_html|safe }}
</ul>
</nav> {% endblock %} {% block javascript %}
<script type="text/javascript">
$('#choice').click(function () {
if ($(this).prop('checked')) { //对象自身属性中是否具有指定的属性
$('.choice_item').prop("checked", true)
} else {
$('.choice_item').prop("checked", false)
}
})
</script>
{% endblock %}
4、总结
1、分页知识点
1.分页
{{ showlist.pagination.page_html|safe }}
2.page.py
class Pagination(object):
def __init__(self, current_page, all_count, base_url,params, per_page_num=8, pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param base_url: 分页中显示的URL前缀
:param pager_count: 最多显示的页码个数
:param params: ? 后面携带得参数 request.GET
""" ... 注意:翻页时,http://127.0.0.1:8090/stark/app01/publish/?page=2&name=alice&age=18
每页需带上之前的参数。 import copy
params = copy.deepcopy(params)
params._mutable = True
self.params = params # self.params : {"page":77,"title":"python","nid":1} self.params["page"] = i
self.params.urlencode() 将{"name":"alice","age":18} 转换成 name=alice&age=18 temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.params.urlencode(), i,)
3.list_view 视图函数
表头,表数据,分页... 内容太多,封装在一个类里面专门用来展示数据。
# 展示数据
showlist = ShowList(self, data_list, request)
class ShowList(object):
def __init__(self):
pass def get_header(self):
pass def get_body(self):
pass
2、search模糊查询
1.判断用户是否配置,配置才显示search框, get查询
search_fields = ['title', 'price'] 显示key_words{{ showlist.config.key_words }}
{% if showlist.config.search_fields %}
<form action="" class="pull-right">
<input type="text" name="q" value="{{ showlist.config.key_words }}"><button>submit</button>
</form>
{% endif %}
2.Q对象
# 获取search得Q对象
search_connection = self.get_search_condition(request) # print("connection:",search_connection)
# connection: (or: ('title__contains', '3'), ('price__contains', '3')) # 筛选当前表得所有数据
data_list = self.model.objects.all().filter(search_connection)
3.Q查询
两种方式,一种可以放str,就是下面这种,一种放字段; def get_search_condition(self, request):
key_words = request.GET.get('q', "")
self.key_words = key_words # self.search_fields ['title','price'] from django.db.models import Q
search_connection = Q()
if key_words:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_words)) return search_connection
4.模糊查询
(title__contains)(price__contains)
search_connection.children.append((search_field+"__contains", key_words))
3、action批量初始化
知识点
1.用户可自定义配置
def patch_init(self, request, queryset):
# print("queryset",queryset)
queryset.update(price=123) # return HttpResponse('批量初始化OK') patch_init.short_description = "批量初始化"
actions = [patch_init]
2.无论有没有配置,都会有一个默认得批量删除
def patch_delete(self, request, queryset):
queryset.delete()
patch_delete.short_description = "批量删除" def new_actions(self):
temp = []
temp.append(ModelStark.patch_delete)
temp.extend(self.actions) return temp
3.展示页面 option
传过去得数据: __name__ (方法名传过去,做为value,为之后反射做准备)
self.actions = self.config.new_actions() def get_action_list(self):
temp = []
for action in self.actions:
temp.append({
"name": action.__name__,
"desc":action.short_description
}) return temp
4.前端
主要就是将:方法名赋值给option得value, form post请求,将值传到后台
<select name="action" id="" style="width: 200px; padding: 5px 8px; display: inline-block; ">
<option value="">------------</option>
{% for item in showlist.get_action_list %}
<option value="{{ item.name }}">{{ item.desc }}</option>
{% endfor %}
</select>
5.后台
接收用户选中得数据,action selected_pk
反射:action_func = getattr(self, action)
过滤查询:queryset: queryset = self.model.objects.filter(pk__in=selected_pk)
执行反射回来得函数: action_func(request, queryset) def list_view(self, request):
if request.method == "POST":
print("request.POST:",request.POST)
# 'action': ['patch_init'], 'selected_pk': ['1', '2']
action = request.POST.get('action')
selected_pk = request.POST.getlist('selected_pk')
action_func = getattr(self, action) # 反射
queryset = self.model.objects.filter(pk__in=selected_pk) # 秒!!!
ret = action_func(request, queryset)
# return ret ...