我的第一个python web开发框架(15)——公司介绍编辑功能
完成登录以后,就会进入后台管理系统的主界面,因为这个是小项目,所以导航菜单全部固化在HTML中,不能修改。一般后台还会有一个欢迎页或关键数据展示的主页面,小项目也没有多大的必要,所以登录后直接进入公司介绍编辑页面。
首先我们来看一下公司介绍页面内容
看上去功能好像很简单,其实我们要处理的东西还是挺多的。
从页面上看,我们需要有一个记录读取的接口,来获取公司介绍的内容,并展示在页面上。当然现在数据库里面没有记录存在,所以我们还需要向数据库的信息表(infomation)中插入一条公司介绍的记录,这样好直接进行编辑(因为公司介绍不会有很多条记录,一般定了后就不会再改变,所以只需要在数据库的信息表里插入一条就可以了)
另外,从界面上看,我们还需要有一个上传文件的接口,可以上传图片和文件;还需要一个更新公司介绍内容的接口。
还有需要修改几个地方,有上传文件,肯定需要有下载的接口,所以需要增加一个下载的路由(python与其他语言不一样的地方是,所有访问都必须通过路由,所以上传的或放在目录中的文件需要统一定义一个接口来处理,不然用户访问不了,虽然有点麻烦,但这样处理也安全很多,用户上传任何含有木马或程序的文件,它也无法在服务器端执行);nginx配置文件也需要修改一下,增加下载路径规则,这样就可以直接通过nginx访问下载路径了。
向数据库中添加公司介绍记录
运行pgAdmin连上数据库,然后按第4章的做法,打开sql查询分析器,运行下面代码添加一条数据库记录
INSERT INTO infomation(id, title) VALUES (1, '公司介绍');
添加公司介绍记录读取接口
1 @get('/api/about/')2 defcallback():3 """ 4 获取指定记录5 """ 6 sql = """select * from infomation where id = 1""" 7 #读取记录 8 result =db_helper.read(sql)9 ifresult:10 #直接输出json 11 return web_helper.return_msg(0, '成功', result[0])12 else:13 return web_helper.return_msg(-1, "查询失败")
因为公司介绍id添加后不会再改变,所以sql语句直接绑死id为1,另外,执行数据库查询以后,返回的是列表,所以返回记录时要加上序号:result[0]
启动debug(对main.py点击右键=》debug),将用户登录判断那两行注释掉(不然直接访问会返回-404,“您的登录已失效,请重新登录”提示),在浏览器输入:http://127.0.0.1:9090/api/about/就可以看到返回结果(结果的中文字符是unicode编码,需要用站长工具转换一下才可以转为下载效果)
{"msg": "成功", "data": {"content": "", "front_cover_img": "", "id": 1, "title": "公司介绍", "add_time": "2017-10-31 14:17:45"}, "state": 0}
添加公司介绍内容修改接口
1 @put('/api/about/')2 defcallback():3 """ 4 修改记录5 """ 6 front_cover_img = web_helper.get_form('front_cover_img', '图片')7 content = web_helper.get_form('content', '内容', is_check_special_char=False)8 #防sql注入攻击处理 9 content = string_helper.filter_str(content, "'")10 #防xss攻击处理 11 content =string_helper.clear_xss(content)12 13 #更新记录 14 sql = """update infomation set front_cover_img=%s, content=%s where id=1""" 15 vars =(front_cover_img, content,)16 #写入数据库 17 db_helper.write(sql, vars)18 19 #直接输出json 20 return web_helper.return_msg(0, '成功')
因为公司介绍只需要一条记录就够了,前面使用手动方式向数据库添加记录,所以代码中我们就不需要写添加的方法
修改记录使用put方式接收:@put('/api/about/')
从界面图片中可以看到,有文章标题、首页图片和文章内容,因为标题不需要进行修改,所以我们修改接口只需要处理剩下两项就可以了。
因为提交的内容含有HTML代码,所以使用web_helper.get_form提取值时,需要使用is_check_special_char参数,设置为不检查特殊符号,不然会接收不了。另外接收到参数值以后,我们需要对它进行防sql注入和防xss处理。
clear_xss()函数是string_helper包新增的清除xss攻击标签用的,它会过滤掉xss的攻击代码。详细代码如下:
defclear_xss(html):"""清除xss攻击标签:param html: 要处理的html:return:"""tags= ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li', 'ol', 'strong', 'ul']tags.extend(['div', 'p', 'hr', 'br', 'pre', 'code', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'del', 'dl', 'img', 'sub', 'sup', 'u','table', 'thead', 'tr', 'th', 'td', 'tbody', 'dd', 'caption', 'blockquote', 'section'])attributes= {'*': ['class', 'id'], 'a': ['href', 'title', 'target'], 'img': ['src', 'style', 'width', 'height']}return bleach.linkify(bleach.clean(html, tags=tags, attributes=attributes))
clear_xss()函数中我们使用了bleach这个库(需要安装:pip install bleach),它是一个基于白名单、通过转义或去除标签和属性的方式,来对HTML文本净化的python库。
我们在string_helper_test.py这个测试单元中添加一个测试用例,来测试一下这个函数的使用效果
deftest_clear_xss(self):print('-----test_clear_xss------')print(string_helper.clear_xss('<script src="javascript:alert(1);">abc</script>'))print(string_helper.clear_xss('<iframe src="javascript:alert(1);">abc</iframe>'))print(string_helper.clear_xss('<div style="width:0;height:0;background:url(javascript:document.body.onload = function(){alert(/XSS/);};">div</div>'))print(string_helper.clear_xss('<img src = "#"/**/onerror = alert(/XSS/)>'))print(string_helper.clear_xss('<img src = j ava script:al er t(/XSS/)>'))print(string_helper.clear_xss("""<img src = j ava script :a ler t(/xss/)>"""))print(string_helper.clear_xss('<img src="javacript:alert(\'abc\')"></img>'))print(string_helper.clear_xss('<img src="https://www.baidu.com/img/baidu_jgylogo3.gif"></img>'))print(string_helper.clear_xss('<p src="javascript:alert(1);">abc</p>'))print(string_helper.clear_xss("""<input type="text" value="琅琊榜" οnclick="javascript:alert('handsome boy')">"""))print(string_helper.clear_xss('<p οnclick="javascript:alert("handsome boy")>abc</p>'))print(string_helper.clear_xss('<a href="javascript:alert(1);">abc</a>'))print(string_helper.clear_xss('<a href="/api/">abc</a>'))print(string_helper.clear_xss('<a href="http://www.baidu.com">abc</a>'))print(string_helper.clear_xss('<marquee onstart="alert(/XSS/)">文字</marquee>'))print(string_helper.clear_xss('<div style="" οnmοuseenter="alert(/XSS/)">文字</div>'))print(string_helper.clear_xss('<li style = "TEST:e-xpression(alert(/XSS/))"></li>'))print(string_helper.clear_xss('<input id = 1 type = "text" value="" <script>alert(/XSS/)</script>"/>'))print(string_helper.clear_xss('<base href="http://www.labsecurity.org"/>'))print(string_helper.clear_xss('<div id="x">alert%28document.cookie%29%3B</div>'))print(string_helper.clear_xss('<limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point>'))
执行后输出结果:
------ini------ -----test_clear_xss------ <script src="javascript:alert(1);">abc</script><iframe src="javascript:alert(1);">abc</iframe><div>div</div> <img src="#"> <img src="j"> <img src="j"> <img> <img src="https://www.baidu.com/img/baidu_jgylogo3.gif"> <p>abc</p> <input οnclick="javascript:alert('handsome boy')" type="text" value="琅琊榜"><p>abc</p> <a>abc</a> <a href="/api/" rel="nofollow">abc</a> <a href="http://www.baidu.com" rel="nofollow">abc</a> <marquee onstart="alert(/XSS/)">文字</marquee><div>文字</div> <li></li> <input <script="" id="1" type="text" value="">alert(/XSS/)"/> <base href="<a href="http://www.labsecurity.org"rel="nofollow">http://www.labsecurity.org</a>"><div id="x">alert%28document.cookie%29%3B</div> <limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point>------clear------
可以看到,对于富文本编辑器提交的代码,bleach基本满足了我们的防范xss攻击的处理需求
添加上传接口(PS:我们使用的文本编辑器是百度的ueditor,因为它没有python的上传处理代码,所以我们需要动手编辑上传接口,以及html上也要进行对应的修改)
#!/usr/bin/evn python#coding=utf-8importosfrom bottle importpost, requestfrom common importdatetime_helper, random_helper, log_helper@post('/api/files/')defcallback():"""修改记录"""#初始化输出值result ={"state": "FAIL","url": "","title": "上传失败","original": ""}#获取上传文件try:#upfile为前端HTML上传控件名称upload = request.files.get('upfile')#如果没有读取到上传文件或上传文件的方式不正确,则返回上传失败状态if notupload:returnresult#取出文件的名字和后缀name, ext =os.path.splitext(upload.filename)#给上传的文件重命名,默认上传的是图片if ext and ext != '':file_name= datetime_helper.to_number() + random_helper.get_string(5) +extelse:file_name= datetime_helper.to_number() + random_helper.get_string(5) + '.jpg'upload.filename=file_name#设置文件存储的相对路径filepath = '/upload/' + datetime_helper.to_number('%Y%m%d') + '/'#组合成服务器端存储绝对路径upload_path = os.getcwd() +filepath#如果目录不存在,则创建目录if notos.path.exists(upload_path):os.mkdir(upload_path)#保存文件upload.save(upload_path + upload.filename, overwrite=True)#设置输出参数(返回相对路径给客户端)result['title'] = result['original'] =upload.filenameresult['url'] = filepath +upload.filenameresult['state'] = 'SUCCESS'exceptException as e:log_helper.error('上传失败:' +str(e.args))#直接输出jsonreturn result
PS:这里只做了上传文件处理,没有上传成功以后存储到数据库中统一管理,如果前端反复上传,会造成服务器存储很多多余文件的问题,大家可以自己发挥想象与动手能力,看看怎么解决这个问题。对于这个问题会在第二部分统一处理。
添加上传文件存储文件夹:直接在项目的要目录下创建upload文件夹
修改main.py文件配置,并创建文件下载路由
导入的bottle库添加response, static_file这两个包,response用于设置输出文件类型为二进制数据传输格式,这样设置后,上传的各种类型文件都可以下载;static_file是使用安全的方式读取文件并输出到客户端
from bottle import default_app, get, run, request, hook, route, response, static_file
在第26行插入下面代码,初始化上传文件存储路径
#定义upload为上传文件存储路径 upload_path = os.path.join(program_path, 'upload')
添加下载文件访问路由,设置后只要放在upload目录下的文件都可以直接通过浏览器下载
@get('/upload/<filepath:path>')defupload_static(filepath):"""设置静态内容路由"""response.add_header('Content-Type', 'application/octet-stream')return static_file(filepath, root=upload_path)
做完以上设置,上传与更新就没有问题了,上传的图片直接使用http://127.0.0.1:9090/upload/xxx.jpg方式就可以访问了,如果想要使用81端口,也就是通过nginx访问,那就需要再配置一下
打开nginx配置文件 :E:\Service\nginx-1.11.5\conf\nginx.conf
将location ~* ^/(index|api)/ 修改为location ~* ^/(index|api|upload)/
然后在windows任务管理器(键盘同时按Ctrl+Alt+Del键,点击启动任务管理器),找到nginx_service.exe,右键=》结束进程树
重新打开服务(控制面板=》所有控制面板项=》管理工具=》服务),启动nginx_service服务
前端页面相关修改
向/lib/ueditor/1.4.3/目录中添加python文件夹,将添加config.json这个配置项
修改/lib/ueditor/1.4.3/ueditor.config.js 配置项中 服务器统一请求接口路径 为 /api/files/
本文对应的源码包里有ueditor编辑器最新代码(刚刚去百度下载的),去掉了多余的文件,大家可直接删除lib目录里的ueditor这个文件夹,使用源码包里的替换上去就可以了
前端页面的javascript脚本添加了ueditor编辑器初始化、文件上传和表单提交等功能,可直接替换about_edit.html文件,具体大家自己研究一下。
最终效果:
另外,联系我们的功能与公司介绍差不多,在这里留一下作业给大家自己尝试做一个联系我们编辑页面出来,下一篇会给联系我们编辑页面源码给大家
本文对应的源码下载
版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
python开发QQ群:669058475(本群已满)、733466321(可以加2群) 作者博客:http://www.cnblogs.com/EmptyFS/
转载于:https://www.cnblogs.com/EmptyFS/p/7771065.html
我的第一个python web开发框架(15)——公司介绍编辑功能相关推荐
- 程序员新手第一个python web开发框架
接下来正式进入网站的功能开发.要完成后台管理系统登录功能,通过查看登录页面,我们可以了解到,我们需要编写验证码图片获取接口和登录处理接口,然后在登录页面的HTML上编写AJAX. 在进行接口开发之前, ...
- 我的第一个python web开发框架(40)——后台日志与异常处理
我的第一个python web开发框架(40)--后台日志与异常处理 参考文章: (1)我的第一个python web开发框架(40)--后台日志与异常处理 (2)https://www.cnblog ...
- 我的第一个python web开发框架(3)——怎么开始?
小白与小美公司经过几次接触商谈,好不容易将外包签订了下来,准备开始大干一场.不过小白由于没有太多的项目经验,学过python懂得python的基本语法,在公司跟着大家做过简单功能,另外还会一些HTML ...
- 我的第一个python web开发框架(1)——前言
由于之前经验不是很丰富,写的C#系统太过复杂,所以一直想重写,但学的越多越觉的自己懂的越少,越觉得底气不足.所以一直不敢动手,在内心深处对自己讲,要静下心来认真学习,继续沉淀沉淀.这两年多以来找各种机 ...
- 我的第一个python web开发框架(2)——一个简单的小外包
第一部分说明 第一部分大概有20来章,主要讲的是一些开发常识.开发前中后期准备内容.开发环境与服务器部署环境安装设置.python基础框架结构与功能等内容,代码会比较简单. 本系列会以故事的方式,向大 ...
- python实现第一个web_我的第一个python web开发框架(6)——第一个Hello World
小白中午听完老菜讲的那些话后一直在思考,可想来想去还是一头雾水,晕晕呼呼的一知半解,到最后还是想不明白,心想:老大讲的太高深了,只能听懂一半半,看来只能先记下来,将明白的先做,不明白的等以后遇到再学. ...
- 我的第一个python web开发框架(6)——第一个Hello World
转载 : https://www.cnblogs.com/EmptyFS/p/7491949.html 小白中午听完老菜讲的那些话后一直在思考,可想来想去还是一头雾水,晕晕呼呼的一知半解,到最后还是想 ...
- python开发框架 代码生成_我的第一个python web开发框架(28)——定制ORM(四)...
在数据库操作时,新增记录也是必不可少的,接下来我们应用字典的特性来组合sql语句 先上产品新增接口代码 1 @post('/api/product/')2 defcallback():3 " ...
- python定制框架知识点_我的第一个python web开发框架(25)——定制ORM(一)
在开始编写ORM模块之前,我们需要先对db_helper进行重构,因为ORM最终生成的sql是需要转给db_helper来执行的,所以拥有一个功能完善.健壮的数据库操作类是非常必要的. 这是项目原db ...
最新文章
- jpa中使用Query判断条件查询
- python绘制简单直方图-python plotly绘制直方图实例详解
- Indian Scientists Design Device to Collect Solar Energy 印度科学家设计太阳能收集设备
- 电子科大专科c语言作业1,电子科大15春《C语言(专科)》在线作业试卷.docx
- PSPNet网络要点
- DEKR 解构式关键点回归(一):算法思想与原理
- 异步 HttpContext.Current实现取值的方法(解决异步Application,Session,Cache...等失效的问题)...
- ros melodic控制真实机械臂之openmanipulator参考
- php过滤多空格_php如何去除多余空格
- WPS检测到字体缺失Windows字体包方正字体库
- Unity3D游戏开发之MMD For Unity插件研究
- windows注册表恢复方法
- 最佳eclipse字体推荐(个人认为)
- 复频域求零输入响应_连续信号与系统的复频域分析()LCH.ppt
- 【游戏客户端开发】Unity3D 学习笔记2——了解U3D引擎的操作面板和各种工具
- 差分GPS接收机定位原理
- InnoDB内存架构之日志缓冲区
- 2020年9月电子学会Python等级考试试卷(四级)考题解析
- java项目如何分工合作,JavaWeb基础 jsp+servlet分工合作的简单示例
- 大数据面试指南【精华】
热门文章
- php 小程序页面传参,介绍小程序中传递参数的实现方法
- python祝福祖国代码_C语言-笔记一
- 华为隐藏功能扩大内存代码大全_发现将华为手机这3个功能打开,竟然可以将手机性能极限发挥...
- sqlplus可以连接plsql连接不上_Gee引擎配置微端不更新,连接不上,尝试重新连接的解决方法...
- Android开发笔记(三十七)按钮类控件
- c语言程序100例第5题
- CF 468B Two Sets
- java:输出流程printStream
- 电信网络拓扑图自动布局
- 蔡先生论道大数据之八: 让他在看小说的时候, 看到喜欢的汽车