笔记1:ModelForm Ajax全套 文件上传 验证码 KindEditor
内容回顾: Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = fields.EmailField() user = pwd = - is_valid -> 每一个字段进行正则(字段内置正则)+clean_字段 -> clean(__all__) -> _post_clean - cleand_data - error --------> 推荐 <--------- 一、ModelForm 参考博客: http://www.cnblogs.com/wupeiqi/articles/6229414.html Model + Form => 验证 + 数据库操作 - class LoginModelForm(xxxxx): 利用model.A中的字段 1. 生成HTML标签:class Meta: ... 2. 生成默认值(编辑):mf = xxxModelForm(instance=ModelObj) 3. 额外的标签(免登录单选框), is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) 4. 各种验证 is_valid() -> 各种钩子clean... 5. mf.save() # 查看源码分析: # 或 instance = mf.save(False) instance.save() mf.save_m2m() 6.model与form紧耦合,适用于小程序,大程序不要用它。 二、Ajax 参考博客: http://www.cnblogs.com/wupeiqi/articles/5703697.html 原生 jQuery 伪Ajax操作 时机: 如果发送的是【普通数据】 -> jQuery,XMLHttpRequest,iframe 三、文件上传(预览) - Form提交 - Ajax上传文件 时机: 如果发送的是【文件】 -> iframe,jQuery(FormData),XMLHttpRequest(FormData), 四、图片验证码 + Session - session - check_code.py(依赖:Pillow模块和字体文件) - src属性后面加? 五、CKEditor,UEEditor,TinyEditor,KindEditor(***) 参考博客: http://www.cnblogs.com/wupeiqi/articles/6307554.html - 基本使用 - 文件上传,多文件上传,文件空间管理 - XSS攻击(过滤的函数或类) 下节课说... 作业: 主站: http://127.0.0.1:8000/ 博客首页 http://127.0.0.1:8000/zhaofan/1.html 某人的某篇博客 个人博客: http://127.0.0.1:8000/zhaofan.html 某人的博客 http://127.0.0.1:8000/zhaofan/tag/python.html 某人的博客筛选 http://127.0.0.1:8000/zhaofan/catetory/mvc.html 某人的博客筛选 http://127.0.0.1:8000/zhaofan/date/2011-11.html 某人的博客筛选 个人后台管理: http://127.0.0.1:8000/backend/base-info.html http://127.0.0.1:8000/backend/tag.html http://127.0.0.1:8000/backend/category.html http://127.0.0.1:8000/backend/article.html http://127.0.0.1:8000/backend/add-article.html
验证码
urls:
# 需要的文件: # (1)check_code.py (2) Monaco.ttf字体文件 (3)Html文件 url('^checkcode$', views.checkcode), # 用户访问的url页面(验证码单独新url) url('^radom_code', views.radom_code), # 前端POST提交验证码的url
views:
###################################验证码示例############################### from io import BytesIO # 从内存中读取 from utils.check_code import create_validate_code def checkcode(request): """ 验证码 :param request: :return: """ # data = open('static/imgs/avatar/20130809170025.png','rb').read() # return HttpResponse(data) # 文件的读取方法 - 重在理解思路 # 1. 创建一张图片 pip3 install Pillow # 2. 在图片中写入随机字符串 # obj = object() # 3. 将图片写入到制定文件 # 4. 打开制定目录文件,读取内容 # 5. HttpResponse(data) ''' img, code = create_validate_code() # img.save('文件句柄', '文件格式') # 写入文件 f = open('utils/uson_checkcode.png', 'wb') img.save(f, 'PNG') f.close() # return render(request, 'radom_code.html') # 读取文件 return HttpResponse(open('utils/uson_checkcode.png', 'rb').read()) ''' # 内存的存储方法 stream = BytesIO() # 从内存读取 img, code = create_validate_code() # 用户访问页面,创建并生成图片对象和字符串给用户 img.save(stream, 'PNG') # 将以png为后缀的图片对象存放到内存中 request.session['CheckCode'] = code # 并保存到session中,用于post提交验证用户输入是否一致 return HttpResponse(stream.getvalue()) # 从内存中获取图片返回给用户 def radom_code(request): if request.method == 'POST': code = request.POST.get('check_code') # 用户输入input的name:check_code if code.upper() == request.session['CheckCode'].upper(): print('验证码正确') else: print('验证码错误') return render(request, 'day24-app06/radom_code.html')
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .checkcode{ width: 130px; height: 33px; border: 1px solid red; } </style> </head> <body> <div class="checkcode"> <img src="/cohui/checkcode" onclick="changeCheckCode(this);"> </div> <script> function changeCheckCode(ths) { // ths.src = "/cohui/checkcode" + '?'; // 只能改变一次 ths.src = ths.src + '?'; // 只有url动态改变,验证码的url才能不断被提交 } </script> </body> </html>
check_code.py:
#!/usr/bin/env python # -*- coding:utf-8 -*- import random # pip3 install Pillow from PIL import Image, ImageDraw, ImageFont, ImageFilter _letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z _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="utils/Monaco.ttf", # 依赖字体 # 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))) # 大小限制在[0, 100] 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 # img: 图片对象, strs: 验证码字符串
验证码文件:点击获取
依赖字体文件:点击获取
笔记2:Xss攻击 单例模式 事务操作
XSS过滤特殊标签
处理依赖: 1 pip3 install beautifulsoup4
XSS示例:
#!/usr/bin/env python # -*- coding:utf-8 -*- from bs4 import BeautifulSoup class XSSFilter(object): __instance = None def __init__(self): # XSS白名单 self.valid_tags = { "font": ['color', 'size', 'face', 'style'], 'b': [], 'div': [], "span": [], "table": [ 'border', 'cellspacing', 'cellpadding' ], 'th': [ 'colspan', 'rowspan' ], 'td': [ 'colspan', 'rowspan' ], "a": ['href', 'target', 'name'], "img": ['src', 'alt', 'title'], 'p': [ 'align' ], "pre": ['class'], "hr": ['class'], 'strong': [] } @classmethod def instance(cls): if not cls.__instance: obj = cls() cls.__instance = obj return cls.__instance def process(self, content): soup = BeautifulSoup(content, 'lxml') # 遍历所有HTML标签 for tag in soup.find_all(recursive=True): # 判断标签名是否在白名单中 if tag.name not in self.valid_tags: tag.hidden = True if tag.name not in ['html', 'body']: tag.hidden = True tag.clear() continue # 当前标签的所有属性白名单 attr_rules = self.valid_tags[tag.name] keys = list(tag.attrs.keys()) for key in keys: if key not in attr_rules: del tag[key] return soup.renderContents() if __name__ == '__main__': html = """<p class="title"> <b>The Dormouse's story</b> </p> <p class="story"> <div name='root'> Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a> <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>; and they lived at the bottom of a well. <script>alert(123)</script> </div> </p> <p class="story">...</p>""" v = XSSFilter.instance().process(html) print(v)
基于__new__实现单例模式示例
#!/usr/bin/env python # -*- coding:utf-8 -*- from bs4 import BeautifulSoup class XSSFilter(object): __instance = None def __init__(self): # XSS白名单 self.valid_tags = { "font": ['color', 'size', 'face', 'style'], 'b': [], 'div': [], "span": [], "table": [ 'border', 'cellspacing', 'cellpadding' ], 'th': [ 'colspan', 'rowspan' ], 'td': [ 'colspan', 'rowspan' ], "a": ['href', 'target', 'name'], "img": ['src', 'alt', 'title'], 'p': [ 'align' ], "pre": ['class'], "hr": ['class'], 'strong': [] } def __new__(cls, *args, **kwargs): """ 单例模式 :param cls: :param args: :param kwargs: :return: """ if not cls.__instance: obj = object.__new__(cls, *args, **kwargs) cls.__instance = obj return cls.__instance def process(self, content): soup = BeautifulSoup(content, 'lxml') # 遍历所有HTML标签 for tag in soup.find_all(recursive=True): # 判断标签名是否在白名单中 if tag.name not in self.valid_tags: tag.hidden = True if tag.name not in ['html', 'body']: tag.hidden = True tag.clear() continue # 当前标签的所有属性白名单 attr_rules = self.valid_tags[tag.name] keys = list(tag.attrs.keys()) for key in keys: if key not in attr_rules: del tag[key] return soup.renderContents() if __name__ == '__main__': html = """<p class="title"> <b>The Dormouse's story</b> </p> <p class="story"> <div name='root'> Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a> <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>; and they lived at the bottom of a well. <script>alert(123)</script> </div> </p> <p class="story">...</p>""" obj = XSSFilter() v = obj.process(html) print(v)