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

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

0

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

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

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

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

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

二、公司介绍记录读取

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

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

#!/usr/bin/evn python
# coding=utf-8

from bottle import get, put
from common import web_helper, string_helper, db_helper


@get('/api/about/')
def callback():
    """
    获取指定记录
    """
    sql = """select * from infomation where id = 1"""
    # 读取记录
    result = db_helper.read(sql)
    if result:
        # 直接输出json
        return web_helper.return_msg(0, '成功', result[0])
    else:
        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,在末尾添加如下代码:

def clear_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))

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

@put('/api/about/')
def callback():
    """
    修改记录
    """
    front_cover_img = web_helper.get_form('front_cover_img', '图片')
    content = web_helper.get_form('content', '内容', is_check_special_char=False)
    # 防sql注入攻击处理
    content = string_helper.filter_str(content, "'")
    # 防xss攻击处理
    content = string_helper.clear_xss(content)

    # 更新记录
    sql = """update infomation set front_cover_img=%s, content=%s where id=1"""
    vars = (front_cover_img, content,)
    # 写入数据库
    db_helper.write(sql, vars)

    # 直接输出json
    return web_helper.return_msg(0, '成功')

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

#!/usr/bin/evn python
# coding=utf-8

import os
from bottle import post, request
from common import datetime_helper, random_helper, log_helper

@post('/api/files/')
def callback():
    """
    修改记录
    """
    # 初始化输出值
    result = {
        "state": "FAIL",
        "url": "",
        "title": "上传失败",
        "original": ""
    }
    # 获取上传文件
    try:
        # upfile为前端HTML上传控件名称
        upload = request.files.get('upfile')
        # 如果没有读取到上传文件或上传文件的方式不正确,则返回上传失败状态
        if not upload:
            return result

        # 取出文件的名字和后缀
        name, ext = os.path.splitext(upload.filename)
        # 给上传的文件重命名,默认上传的是图片
        if ext and ext != '':
            file_name = datetime_helper.to_number() + random_helper.get_string(5) + ext
        else:
            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 not os.path.exists(upload_path):
            os.mkdir(upload_path)
        # 保存文件
        upload.save(upload_path + upload.filename, overwrite=True)

        # 设置输出参数(返回相对路径给客户端)
        result['title'] = result['original'] = upload.filename
        result['url'] = filepath + upload.filename
        result['state'] = 'SUCCESS'
    except Exception as e:
        log_helper.error('上传失败:' + str(e.args))

    # 直接输出json
    return result

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

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

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

改成:

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

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

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

插入后的效果:
Snap1364

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

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

效果图:

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

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

改成:

, serverUrl: "/api/files/"

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

/* 前后端通信相关的配置,注释只允许使用多行方式 */
{
    /* 上传图片配置项 */
    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
    "imageFieldName": "upfile", /* 提交的图片表单名称 */
    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageUrlPrefix": "", /* 图片访问路径前缀 */
    "imagePathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                                /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
                                /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
                                /* {time} 会替换成时间戳 */
                                /* {yyyy} 会替换成四位年份 */
                                /* {yy} 会替换成两位年份 */
                                /* {mm} 会替换成两位月份 */
                                /* {dd} 会替换成两位日期 */
                                /* {hh} 会替换成两位小时 */
                                /* {ii} 会替换成两位分钟 */
                                /* {ss} 会替换成两位秒 */
                                /* 非法字符 \ : * ? " < > | */
                                /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */

    /* 涂鸦图片上传配置项 */
    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
    "scrawlPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
    "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
    "scrawlInsertAlign": "none",

    /* 截图工具上传 */
    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
    "snapscreenPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */

    /* 抓取远程图片配置 */
    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
    "catcherPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "catcherUrlPrefix": "", /* 图片访问路径前缀 */
    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */

    /* 上传视频配置 */
    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
    "videoFieldName": "upfile", /* 提交的视频表单名称 */
    "videoPathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "videoUrlPrefix": "", /* 视频访问路径前缀 */
    "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
    "videoAllowFiles": [
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */

    /* 上传文件配置 */
    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
    "fileFieldName": "upfile", /* 提交的文件表单名称 */
    "filePathFormat": "/upload/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "fileUrlPrefix": "", /* 文件访问路径前缀 */
    "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
    "fileAllowFiles": [
        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
    ], /* 上传文件格式显示 */

    /* 列出指定目录下的图片 */
    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
    "imageManagerListPath": "/upload/", /* 指定要列出图片的目录 */
    "imageManagerListSize": 20, /* 每次列出文件数量 */
    "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */

    /* 列出指定目录下的文件 */
    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
    "fileManagerListPath": "/upload/", /* 指定要列出文件的目录 */
    "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
    "fileManagerListSize": 20, /* 每次列出文件数量 */
    "fileManagerAllowFiles": [
        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
    ] /* 列出的文件类型 */

}

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

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

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

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

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里面的这段代码是有问题的:

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

to_number是不需要带参数的。

暧昧帖

本文暂无标签

发表评论

*

*