1.自动生称有多级关系的 HTML 标签
class Create_Multistage_Html(object):
"""
用于创建多级 HTML 标签,比如: 多级评论,基于权限管理的多级菜单
利用了递归函数功能。
使用方法:
需要导入一下:
from create_multistage_html import Create_Multistage_Html
obj = Create_Multistage_Html(comment_list,'nid', 'content', 'reply_id')
obj.help()
data_list: 是一个结构化好的数据,或者是用 ORM 的 values 取到的QuerySet数据;
格式如下:
data_list = [
{id: 1, 'content': "顶级菜单", 'reply_id': None},
{id: 2, 'content': "二级菜单", 'reply_id': 1},
{id: 3, 'content': "二级菜单", 'reply_id': 1},
{id: 4, 'content': "三级菜单", 'reply_id': 3},
{id: 5, 'content': "顶级菜单", 'reply_id': None},
{id: 6, 'content': "三级菜单", 'reply_id': 2},
]
QuerySet数据格式:
data_list = <QuerySet[
{id: 1, 'content': "顶级菜单", 'reply_id': None},
{id: 2, 'content': "二级菜单", 'reply_id': 1},
{id: 3, 'content': "二级菜单", 'reply_id': 1},
{id: 4, 'content': "三级菜单", 'reply_id': 3},
{id: 5, 'content': "顶级菜单", 'reply_id': None},
{id: 6, 'content': "三级菜单", 'reply_id': 2},
]>
"""
def __init__(self,data_list,id_key,content_key,parent_id_key):
"""
:param data_list: 有级别关系的数据,数据对象
:param id_key: 数据中每一条记录 ID 的 key(字段名),字符类型
:param content_key: 数据中的需要展示的内容的 key(字段名),字符类型;比如:评论内容,菜单名称
:param parent_id_key: 记录每条记录的上级 ID 的 key(字段名),字符类型
"""
self.data_list = list(data_list)
self.id = id_key
self.content = content_key
self.parent_id = parent_id_key
self.data_dict = {}
self.structured_data = {}
def create_structured_data(self):
for row in self.data_list:
row['child'] = []
self.data_dict[row[self.id]] = row
for row in self.data_list:
if row[self.parent_id]:
key = row[self.parent_id]
self.data_dict[key]['child'].append(row)
for k, v in self.data_dict.items():
if v[self.parent_id] == None:
self.structured_data[k] = v
return self.structured_data
def create_child_node(self,childs):
self.childs = childs
previous = """
<div class="comment">
<div class="content">
"""
for child in self.childs:
template = '<div class="items">%s</div>'
content = child['content']
str_tge = template %content
previous = previous + str_tge
if child['child']:
self.child_tge = self.create_child_node(child['child'])
previous = previous + self.child_tge
end = """
</div>
</div>
"""
return previous + end
def create_multistage_html(self):
"""
最终生成多级别 HTML 标签
:return: css 样式 和 具有等级关系且包含内容的 HTML 标签
"""
self.structured_data= self.create_structured_data()
previous = """
<div class="comment">
<div class="content">
"""
for k,v in self.structured_data.items():
template = '<div class="items">%s</div>'
content = v['content']
str_tge = template % content
previous = previous + str_tge
if v['child']:
child_tge = self.create_child_node(v['child'])
previous = previous + child_tge
end = """
</div>
</div>
"""
css = """
.comment > .content{
margin-left: 30px;
}
"""
return css,previous + end
def help(self):
help_str = """
# 1. 定义函数
def test(request):
# 2. 获取数据
comment_list = models.Comment.objects.values('nid', 'content', 'reply_id', )
# 3. 实例化对象
str_obj = Create_Multistage_Html(comment_list,'nid', 'content', 'reply_id')
# 4. 使用方法,并得到两个返回值
css,str = str_obj.create_multistage_html()
# 5. 把得到的数据返回给前端
return render(request,"test.html",{'css':css,'str':str})
"""
print(help_str)
2.自定义分页
"""
使用方式:
# views.py 的视图函数内:
try:
current_page = request.GET.get('p')
except Exception as e:
print(e)
current_page = 1
all_count = models.Student.objects.all().count()
page_info = PageInfo(current_page, 10, all_count, request.path_info)
user_list = models.Student.objects.all()[page_info.start():page_info.end()]
return render(request, 'users/user_info.html',
{"user_list": user_list,
"page_str": page_info.page_str()})
# 前端页面,基于 Bootstrap
<div class="row">
<nav aria-label="Page navigation">
<ul class="pagination">
{{ page_str |safe }}
</ul>
</nav>
</div>
"""
class PageInfo(object):
def __init__(self,current_page,per_page_num,all_count,base_url,page_range=11):
"""
:param current_page: 当前页
:param per_page_num: 每页显示数据条数
:param all_count: 数据源总条数
:param base_url: 页码标签的前缀
:param page_range: 每页最多显示的页码的标签个数,就是每页显示的页码范围
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = int(1)
self.current_page = current_page
self.per_page_num = per_page_num
self.all_count = all_count
a,b = divmod(all_count,per_page_num)
if b != 0:
self.all_page = a + 1
else:
self.all_page = a
self.base_url = base_url
self.page_range = page_range
def start(self):
return (self.current_page - 1) * self.per_page_num
def end(self):
return self.current_page * self.per_page_num
def page_str(self):
"""
在HTML页面中显示页码信息
:return:
"""
page_list = []
if self.current_page <=1:
prev = '<li><a href="#">上一页</a></li>'
else:
prev = '<li><a href="%s?p=%s">上一页</a></li>' %(self.base_url,self.current_page-1,)
page_list.append(prev)
if self.all_page <= self.page_range:
start = 1
end = self.all_page + 1
else:
if self.current_page > int(self.page_range/2):
if (self.current_page + int(self.page_range/2)) > self.all_page:
start = self.all_page - self.page_range + 1
end = self.all_page + 1
else:
start = self.current_page - int(self.page_range/2)
end = self.current_page + int(self.page_range/2) + 1
else:
start = 1
end = self.page_range + 1
for i in range(start,end):
if self.current_page == i:
temp = '<li class="active"><a href="%s?p=%s">%s</a></li>' %(self.base_url,i,i,)
else:
temp = '<li><a href="%s?p=%s">%s</a></li>' % (self.base_url, i, i,)
page_list.append(temp)
if self.current_page >= self.all_page:
nex = '<li><a href="#">下一页</a></li>'
else:
nex = '<li><a href="%s?p=%s">下一页</a></li>' % (self.base_url,self.current_page + 1,)
page_list.append(nex)
return "".join(page_list)
3.自定义验证码
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
_letter_cases = "abcdefghjkmnpqrstuvwxy"
_upper_cases = _letter_cases.upper()
_numbers = ''.join(map(str, range(3, 10)))
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
def create_validate_code(size=(120, 30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type="Monaco.ttf",
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance = 2):
'''
@todo: 生成验证码图片
@param size: 图片的大小,格式(宽,高),默认为(120, 30)
@param chars: 允许的字符集合,格式字符串
@param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
@param mode: 图片模式,默认为RGB
@param bg_color: 背景颜色,默认为白色
@param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
@param font_size: 验证码字体大小
@param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
@param length: 验证码字符个数
@param draw_lines: 是否划干扰线
@param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
@param draw_points: 是否画干扰点
@param point_chance: 干扰点出现的概率,大小范围[0, 100]
@return: [0]: PIL Image实例
@return: [1]: 验证码图片中的字符串
'''
width, height = size
img = Image.new(mode, size, bg_color)
draw = ImageDraw.Draw(img)
def get_chars():
'''生成给定长度的字符串,返回列表格式'''
return random.sample(chars, length)
def create_lines():
'''绘制干扰线'''
line_num = random.randint(*n_line)
for i in range(line_num):
begin = (random.randint(0, size[0]), random.randint(0, size[1]))
end = (random.randint(0, size[0]), random.randint(0, size[1]))
draw.line([begin, end], fill=(0, 0, 0))
def create_points():
'''绘制干扰点'''
chance = min(100, max(0, int(point_chance)))
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))
def create_strs():
'''绘制验证码字符'''
c_chars = get_chars()
strs = ' %s ' % ' '.join(c_chars)
font = ImageFont.truetype(font_type, font_size)
font_width, font_height = font.getsize(strs)
draw.text(((width - font_width) / 3, (height - font_height) / 3),
strs, font=font, fill=fg_color)
return ''.join(c_chars)
if draw_lines:
create_lines()
if draw_points:
create_points()
strs = create_strs()
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img = img.transform(size, Image.PERSPECTIVE, params)
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img, strs
4.自定义后台返回给前台的 AJAX 的响应数据
class BaseReponse:
def __init__(self):
self.status = False
self.data = None
self.error = None