自动生称有多级关系的 HTML 标签
1 class Create_Multistage_Html(object): 2 """ 3 用于创建多级 HTML 标签,比如: 多级评论,基于权限管理的多级菜单 4 利用了递归函数功能。 5 6 使用方法: 7 需要导入一下: 8 from create_multistage_html import Create_Multistage_Html 9 obj = Create_Multistage_Html(comment_list,'nid', 'content', 'reply_id') 10 obj.help() 11 12 data_list: 是一个结构化好的数据,或者是用 ORM 的 values 取到的QuerySet数据; 13 格式如下: 14 data_list = [ 15 {id: 1, 'content': "顶级菜单", 'reply_id': None}, 16 {id: 2, 'content': "二级菜单", 'reply_id': 1}, 17 {id: 3, 'content': "二级菜单", 'reply_id': 1}, 18 {id: 4, 'content': "三级菜单", 'reply_id': 3}, 19 {id: 5, 'content': "顶级菜单", 'reply_id': None}, 20 {id: 6, 'content': "三级菜单", 'reply_id': 2}, 21 ] 22 QuerySet数据格式: 23 data_list = <QuerySet[ 24 {id: 1, 'content': "顶级菜单", 'reply_id': None}, 25 {id: 2, 'content': "二级菜单", 'reply_id': 1}, 26 {id: 3, 'content': "二级菜单", 'reply_id': 1}, 27 {id: 4, 'content': "三级菜单", 'reply_id': 3}, 28 {id: 5, 'content': "顶级菜单", 'reply_id': None}, 29 {id: 6, 'content': "三级菜单", 'reply_id': 2}, 30 ]> 31 """ 32 def __init__(self,data_list,id_key,content_key,parent_id_key): 33 """ 34 :param data_list: 有级别关系的数据,数据对象 35 :param id_key: 数据中每一条记录 ID 的 key(字段名),字符类型 36 :param content_key: 数据中的需要展示的内容的 key(字段名),字符类型;比如:评论内容,菜单名称 37 :param parent_id_key: 记录每条记录的上级 ID 的 key(字段名),字符类型 38 """ 39 self.data_list = list(data_list) 40 self.id = id_key 41 self.content = content_key 42 self.parent_id = parent_id_key 43 self.data_dict = {} 44 self.structured_data = {} 45 46 47 def create_structured_data(self): 48 49 for row in self.data_list: 50 row['child'] = [] 51 self.data_dict[row[self.id]] = row 52 53 for row in self.data_list: 54 if row[self.parent_id]: 55 key = row[self.parent_id] 56 self.data_dict[key]['child'].append(row) 57 58 for k, v in self.data_dict.items(): 59 if v[self.parent_id] == None: 60 self.structured_data[k] = v 61 return self.structured_data 62 63 def create_child_node(self,childs): 64 self.childs = childs 65 previous = """ 66 <div class="comment"> 67 <div class="content"> 68 """ 69 for child in self.childs: 70 template = '<div class="items">%s</div>' 71 content = child['content'] 72 str_tge = template %content 73 previous = previous + str_tge 74 if child['child']: 75 self.child_tge = self.create_child_node(child['child']) 76 previous = previous + self.child_tge 77 78 end = """ 79 </div> 80 </div> 81 """ 82 return previous + end 83 84 def create_multistage_html(self): 85 """ 86 最终生成多级别 HTML 标签 87 :return: css 样式 和 具有等级关系且包含内容的 HTML 标签 88 """ 89 self.structured_data= self.create_structured_data() 90 91 previous = """ 92 <div class="comment"> 93 <div class="content"> 94 """ 95 for k,v in self.structured_data.items(): 96 template = '<div class="items">%s</div>' 97 content = v['content'] 98 str_tge = template % content 99 previous = previous + str_tge 100 if v['child']: 101 child_tge = self.create_child_node(v['child']) 102 previous = previous + child_tge 103 104 end = """ 105 </div> 106 </div> 107 """ 108 css = """ 109 .comment > .content{ 110 margin-left: 30px; 111 } 112 """ 113 return css,previous + end 114 def help(self): 115 help_str = """ 116 # 1. 定义函数 117 def test(request): 118 # 2. 获取数据 119 comment_list = models.Comment.objects.values('nid', 'content', 'reply_id', ) 120 # 3. 实例化对象 121 str_obj = Create_Multistage_Html(comment_list,'nid', 'content', 'reply_id') 122 # 4. 使用方法,并得到两个返回值 123 css,str = str_obj.create_multistage_html() 124 # 5. 把得到的数据返回给前端 125 return render(request,"test.html",{'css':css,'str':str}) 126 """ 127 print(help_str)
自定义分页
""" 使用方式: # 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) # 只有 8页 if self.all_page <= self.page_range: start = 1 end = self.all_page + 1 else: # 页数 18 if self.current_page > int(self.page_range/2): # 当前页: 6,7,8,,9,100 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: # 当前页: 1,2,3,4,5, 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)
自定义验证码
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 import random 5 from PIL import Image, ImageDraw, ImageFont, ImageFilter 6 # pip3 install Pillow 7 8 _letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z 9 _upper_cases = _letter_cases.upper() # 大写字母 10 _numbers = ''.join(map(str, range(3, 10))) # 数字 11 init_chars = ''.join((_letter_cases, _upper_cases, _numbers)) 12 13 def create_validate_code(size=(120, 30), 14 chars=init_chars, 15 img_type="GIF", 16 mode="RGB", 17 bg_color=(255, 255, 255), 18 fg_color=(0, 0, 255), 19 font_size=18, 20 font_type="Monaco.ttf", 21 length=4, 22 draw_lines=True, 23 n_line=(1, 2), 24 draw_points=True, 25 point_chance = 2): 26 ''' 27 @todo: 生成验证码图片 28 @param size: 图片的大小,格式(宽,高),默认为(120, 30) 29 @param chars: 允许的字符集合,格式字符串 30 @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG 31 @param mode: 图片模式,默认为RGB 32 @param bg_color: 背景颜色,默认为白色 33 @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF 34 @param font_size: 验证码字体大小 35 @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf 36 @param length: 验证码字符个数 37 @param draw_lines: 是否划干扰线 38 @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效 39 @param draw_points: 是否画干扰点 40 @param point_chance: 干扰点出现的概率,大小范围[0, 100] 41 @return: [0]: PIL Image实例 42 @return: [1]: 验证码图片中的字符串 43 ''' 44 45 width, height = size # 宽, 高 46 img = Image.new(mode, size, bg_color) # 创建图形 47 draw = ImageDraw.Draw(img) # 创建画笔 48 49 def get_chars(): 50 '''生成给定长度的字符串,返回列表格式''' 51 return random.sample(chars, length) 52 53 def create_lines(): 54 '''绘制干扰线''' 55 line_num = random.randint(*n_line) # 干扰线条数 56 57 for i in range(line_num): 58 # 起始点 59 begin = (random.randint(0, size[0]), random.randint(0, size[1])) 60 #结束点 61 end = (random.randint(0, size[0]), random.randint(0, size[1])) 62 draw.line([begin, end], fill=(0, 0, 0)) 63 64 def create_points(): 65 '''绘制干扰点''' 66 chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100] 67 68 for w in range(width): 69 for h in range(height): 70 tmp = random.randint(0, 100) 71 if tmp > 100 - chance: 72 draw.point((w, h), fill=(0, 0, 0)) 73 74 def create_strs(): 75 '''绘制验证码字符''' 76 c_chars = get_chars() 77 strs = ' %s ' % ' '.join(c_chars) # 每个字符前后以空格隔开 78 79 font = ImageFont.truetype(font_type, font_size) 80 font_width, font_height = font.getsize(strs) 81 82 draw.text(((width - font_width) / 3, (height - font_height) / 3), 83 strs, font=font, fill=fg_color) 84 85 return ''.join(c_chars) 86 87 if draw_lines: 88 create_lines() 89 if draw_points: 90 create_points() 91 strs = create_strs() 92 93 # 图形扭曲参数 94 params = [1 - float(random.randint(1, 2)) / 100, 95 0, 96 0, 97 0, 98 1 - float(random.randint(1, 10)) / 100, 99 float(random.randint(1, 2)) / 500, 100 0.001, 101 float(random.randint(1, 2)) / 500 102 ] 103 img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲 104 105 img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强(阈值更大) 106 107 return img, strs
自定义后台返回给前台的 AJAX 的响应数据
class BaseReponse: def __init__(self): self.status = False self.data = None self.error = None