Home >  > 一天学会Python Web框架(十)公司介绍

一天学会Python Web框架(十)公司介绍

0

现在,网站的整体架构(包括前端、后台)都搭建起来了,但是我们还有许多东西需要完善。

1.后台需要有修改公司介绍的功能。
2.需要有上传图片的功能。

下面我们就来完善这些功能。

一、添加公司介绍
运行pgAdmin连上数据库,然后按第4章的做法,打开sql查询分析器,运行下面代码添加一条数据库记录:

1INSERT INTO infomation(id, title)  VALUES (1, '公司介绍');

二、公司介绍记录读取

将main.py用户登录判断那两行代码注释掉
Snap1365

在api文件夹下面新增一个about.py,在下面添加如下代码:

1#!/usr/bin/evn python
2# coding=utf-8
3 
4from bottle import get, put
5from common import web_helper, string_helper, db_helper
6 
7 
8@get('/api/about/')
9def callback():
10    """
11    获取指定记录
12    """
13    sql = """select * from infomation where id = 1"""
14    # 读取记录
15    result = db_helper.read(sql)
16    if result:
17        # 直接输出json
18        return web_helper.return_msg(0, '成功', result[0])
19    else:
20        return web_helper.return_msg(-1, "查询失败")

因为公司介绍id添加后不会再改变,所以sql语句直接绑死id为1,另外,执行数据库查询以后,返回的是列表,所以返回记录时要加上序号:result[0]

三、测试结果

在浏览器输入:http://127.0.0.1:9090/api/about/,看到如下界面,里面有“ "state": 0”的信息,就表示成功了。
Snap1363

备注:乱码问题
如果你看到的界面是这样的,是因为中文字符是unicode编码。
Snap1360

这样的代码可以通过站长工具进行转码。

四、防sql注入和防xss处理
首先使用pip install bleach安装bleach这个库,它是一个基于白名单、通过转义或去除标签和属性的方式,来对HTML文本净化的python库。
打开string_helper文件,在开头加入import bleach,在末尾添加如下代码:

1def clear_xss(html):
2    """
3    清除xss攻击标签
4    :param html: 要处理的html
5    :return:
6    """
7    tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li', 'ol', 'strong', 'ul']
8    tags.extend(
9        ['div', 'p', 'hr', 'br', 'pre', 'code', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'del', 'dl', 'img', 'sub', 'sup', 'u',
10         'table', 'thead', 'tr', 'th', 'td', 'tbody', 'dd', 'caption', 'blockquote', 'section'])
11    attributes = {'*': ['class', 'id'], 'a': ['href', 'title', 'target'], 'img': ['src', 'style', 'width', 'height']}
12    return bleach.linkify(bleach.clean(html, tags=tags, attributes=attributes))

五、添加修改公司介绍接口
修改记录使用put方式接收:@put('/api/about/'),在about.py中,添加如下代码:

1@put('/api/about/')
2def callback():
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, '成功')

六、添加上传接口
由于我们使用的文本编辑器是百度的ueditor,因为它没有python的上传处理代码,所以我们需要动手编辑上传接口,以及html上也要进行对应的修改。
在api文件夹下面新建一个files.py,代码如下:

1#!/usr/bin/evn python
2# coding=utf-8
3 
4import os
5from bottle import post, request
6from common import datetime_helper, random_helper, log_helper
7 
8@post('/api/files/')
9def callback():
10    """
11    修改记录
12    """
13    # 初始化输出值
14    result = {
15        "state": "FAIL",
16        "url": "",
17        "title": "上传失败",
18        "original": ""
19    }
20    # 获取上传文件
21    try:
22        # upfile为前端HTML上传控件名称
23        upload = request.files.get('upfile')
24        # 如果没有读取到上传文件或上传文件的方式不正确,则返回上传失败状态
25        if not upload:
26            return result
27 
28        # 取出文件的名字和后缀
29        name, ext = os.path.splitext(upload.filename)
30        # 给上传的文件重命名,默认上传的是图片
31        if ext and ext != '':
32            file_name = datetime_helper.to_number() + random_helper.get_string(5) + ext
33        else:
34            file_name = datetime_helper.to_number() + random_helper.get_string(5) + '.jpg'
35        upload.filename = file_name
36 
37        # 设置文件存储的相对路径
38        filepath = '/upload/' + datetime_helper.to_number('%Y%m%d') + '/'
39        # 组合成服务器端存储绝对路径
40        upload_path = os.getcwd() + filepath
41        # 如果目录不存在,则创建目录
42        if not os.path.exists(upload_path):
43            os.mkdir(upload_path)
44        # 保存文件
45        upload.save(upload_path + upload.filename, overwrite=True)
46 
47        # 设置输出参数(返回相对路径给客户端)
48        result['title'] = result['original'] = upload.filename
49        result['url'] = filepath + upload.filename
50        result['state'] = 'SUCCESS'
51    except Exception as e:
52        log_helper.error('上传失败:' + str(e.args))
53 
54    # 直接输出json
55    return result

七、建立上传文件的存放文件夹
在项目的根目录下创建upload文件夹。

八、创建文件下载路由
添加bottle库的response, static_file这两个包,打开main.py文件,将原来的:

1from bottle import default_app, get, run, request, hook

改成:

1from bottle import default_app, get, run, request, hook, route, response, static_file

在26行的位置插入以下代码:

1# 定义upload为上传文件存储路径
2upload_path = os.path.join(program_path, 'upload')

插入后的效果:
Snap1364

再在函数主入口前面位置添加以下代码,设置后只要放在upload目录下的文件都可以直接通过浏览器下载:

1@get('/upload/<filepath:path>')
2def upload_static(filepath):
3    """设置静态内容路由"""
4    response.add_header('Content-Type', 'application/octet-stream')
5    return static_file(filepath, root=upload_path)

效果图:

九、修改前端页面
打开html文件夹中的/lib/ueditor/1.4.3/ueditor.config.js,修改“服务器统一请求接口路径”为下面的形式。
将原来的

1, serverUrl: URL + "php/controller.php"

改成:

1, serverUrl: "/api/files/"

在/lib/ueditor/1.4.3/目录下面添加一个python文件夹,在里面新增一个config.json文件,代码如下:

1/* 前后端通信相关的配置,注释只允许使用多行方式 */
2{
3    /* 上传图片配置项 */
4    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
5    "imageFieldName": "upfile", /* 提交的图片表单名称 */
6    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
7    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
8    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
9    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
10    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
11    "imageUrlPrefix": "", /* 图片访问路径前缀 */
12    "imagePathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
13                                /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
14                                /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
15                                /* {time} 会替换成时间戳 */
16                                /* {yyyy} 会替换成四位年份 */
17                                /* {yy} 会替换成两位年份 */
18                                /* {mm} 会替换成两位月份 */
19                                /* {dd} 会替换成两位日期 */
20                                /* {hh} 会替换成两位小时 */
21                                /* {ii} 会替换成两位分钟 */
22                                /* {ss} 会替换成两位秒 */
23                                /* 非法字符 \ : * ? " < > | */
24                                /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
25 
26    /* 涂鸦图片上传配置项 */
27    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
28    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
29    "scrawlPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
30    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
31    "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
32    "scrawlInsertAlign": "none",
33 
34    /* 截图工具上传 */
35    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
36    "snapscreenPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
37    "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
38    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
39 
40    /* 抓取远程图片配置 */
41    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
42    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
43    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
44    "catcherPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
45    "catcherUrlPrefix": "", /* 图片访问路径前缀 */
46    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
47    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
48 
49    /* 上传视频配置 */
50    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
51    "videoFieldName": "upfile", /* 提交的视频表单名称 */
52    "videoPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
53    "videoUrlPrefix": "", /* 视频访问路径前缀 */
54    "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
55    "videoAllowFiles": [
56        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
57        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
58 
59    /* 上传文件配置 */
60    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
61    "fileFieldName": "upfile", /* 提交的文件表单名称 */
62    "filePathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
63    "fileUrlPrefix": "", /* 文件访问路径前缀 */
64    "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
65    "fileAllowFiles": [
66        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
67        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
68        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
69        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
70        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
71    ], /* 上传文件格式显示 */
72 
73    /* 列出指定目录下的图片 */
74    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
75    "imageManagerListPath": "/upload/", /* 指定要列出图片的目录 */
76    "imageManagerListSize": 20, /* 每次列出文件数量 */
77    "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
78    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
79    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
80 
81    /* 列出指定目录下的文件 */
82    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
83    "fileManagerListPath": "/upload/", /* 指定要列出文件的目录 */
84    "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
85    "fileManagerListSize": 20, /* 每次列出文件数量 */
86    "fileManagerAllowFiles": [
87        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
88        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
89        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
90        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
91        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
92    ] /* 列出的文件类型 */
93 
94}

完成以上两项配置之后,就可以使用上传图片的功能了。

十、修改公司介绍
点击“首页图片”后面的“浏览”按钮,插入一张图片。

点击编辑器上的插入图片图标,选择一张图片插入。

然后再输入公司简介的内容,点击保存。

Snap1323

进入数据库,可以看到我们刚刚修改后的结果。

Snap1324

十一、设定图片路径
从步骤十的截图可以看到,我们上传的图片显示为一个白色的小图标,而百度的UEditor上传图片之后,是可以显示图片的。
通过测试发现:我们可以通过:http://127.0.0.1:9090/upload/20180312200449/2018031220044969Fw2.jpg 来访问这张上传的图片,但是我们如果用http://127.0.0.1:81/upload/20180312200449/2018031220044969Fw2.jpg 是无法显示这张图片的,而我们现在正在我们的后台,后台的地址就是http://127.0.0.1:81,所以图片当然也无法显示了。

打开nginx配置文件 :E:\Service\nginx-1.11.5\conf\nginx.conf

将location ~* ^/(index|api)/ 修改为 location ~* ^/(index|api|upload)/

Snap1325

然后同时按Ctrl+Alt+Del键,点击启动任务管理器,找到nginx_service.exe,右键=》结束进程树。

重新打开服务(控制面板=》所有控制面板项=》管理工具=》服务),启动nginx_service服务。

刷新一下后台,就可以看到图片正常显示了。

备注:
这一章是最难的一章,两次在这儿栽跟斗,就是源码有问题,我第一次做这个教程的时候做到第十一章,当时是解决了这个问题的。、
不过第二次做时,完全忘记了,所以又犯了同样的错误,就是可以通过info.log查看出错信息,这样就可以发现files.py里面的这段代码是有问题的:

1filepath = '/upload/' + datetime_helper.to_number('%Y%m%d') + '/'

to_number是不需要带参数的。

暧昧帖

本文暂无标签

发表评论

*

*