类Flask实现前后端交互之代码聊天室
前言
这两天老是做梦,全根Python有关,这不昨晚梦见我把Python做成了类似于JavaScript一样的功能,在前端混的风生水起。结果是个梦。。。。。。
在第一次接触了Flask之后,就被它优雅的路由映射给俘获了。后来我自己又搜索了相关的知识点,算是勉强做出一个最最简化的版本。详细的内容可以查看我的这篇文章。
http://blog.csdn.net/marksinoberg/article/details/72811360
关于昨晚的梦,早上醒来倒是给了我一个灵感,为什么不能做出一个代码聊天室呢? 说着可能有点让人摸不着头脑,其实说白了,就是一个本地的代码执行环境。大致的模样应该是这个样子的。
“框架”?
项目目录及各自功能
说到底,这根本不能算是一个框架,充其量也只能是一个工具集吧。项目目录也比较简单。如下:
C:\Users\biao\Desktop\笔记\code-chatter>tree /f .
文件夹 PATH 列表
卷序列号为 E0C6-0F15
C:\USERS\BIAO\DESKTOP\笔记\CODE-CHATTER
│ .gitignore
│ backend.py # 服务后台
│ executor.py # 客户端代码执行工具
│ server.py # 后台web应用处理器
│ temp.py # 客户端临时代码存放
│ test.py # 测试相关文件
│
├─templates
│ index.css
│ index.html
│ index.js
│ jquery-2.2.4.min.js
└─
流程图
大致来说,软件工作的流程如下:
由于作图工具的问题,原本应该双向交互的对象只画出了单个箭头。不过看到这个图后,这个软件的工作流程应该就不难理解了。
后端
基本上来说后端是重中之重啦。接下来一一的介绍一下吧。
server
按照WSGI标准, 一个WEB应用程序或者框架应该满足如下条件:
- 本身为一个对象(函数,类init,对象call)
- 有env, start_response两个参数(当然名字可以不固定)
- 返回对象可迭代
我这里借助了对象的形式来实现,在__call__方法中添加了处理逻辑。
def __call__(self, env, start_response):
"""
根据WSGI标准,web应用程序需要包含两个参数:
@param env : 一个包含了请求内容的字典
@param start_response : 开始处理来自客户端的请求
"""
path = env["PATH_INFO"]
if path in self.routes:
# 路由映射函数已知
status = '200 OK'
headers = [('Content-Type', 'text/html;charset=UTF-8')]
# print(env)
# 对来自客户端的请求做封装处理
request_method = env.get("REQUEST_METHOD", "")
print("***"*28, request_method)
if request_method == "POST":
content_length = int(env.get('CONTENT_LENGTH', 0))
form_data = parse_qs(env.get('wsgi.input', '').read(content_length))
self.request.add(key='method', value="POST")
# TODO 或许在这里处理一下来自用户请求的数据,比如escape防止脚本攻击
self.request.add(key='post_data', value=form_data)
elif request_method == "GET":
self.request.add(key='method', value=request_method)
query_string = env.get('QUERY_STRING', '')
self.request.add(key='query_string', value=query_string)
start_response(status, headers)
return self.routes[path](self.request)
else:
# 处理函数不包含在路由控制器内
status = '404 Not Found'
headers = [('Content-Type', 'text/html;charset=UTF-8')]
start_response(status, headers)
return ["No handler match for `{}`".format(path).encode('utf8')]
backend
后台存在的意义就是路由映射以及监听客户端请求,并将与请求对应的处理函数进行转发处理。
总的来说类似于一个控制器,或者中间件。用过Flask的童鞋可能会非常容易的理解下面代码的作用了。没用过的话也应该能见名之意。
# coding: utf8
"""
监听客户端请求,返回相应的执行结果。
"""
import os
from server import Application
from executor import runcode
# from jinja2 import Template
app = Application(__name__)
# 下面开始对于前台的请求做路由控制
@app.route('/')
def index(request):
"""
可以适当的对首页做下简介。
"""
print("handler方面:", request)
# 也可以尝试使用模板
with open('./templates/index.html', 'r', encoding="utf8") as f:
html = f.read()
f.close()
yield html.encode('utf8')
@app.route('/api/user')
def user(request):
print(request.params)
if request.params.get('method', '') == "POST" or request.params.get('method', '')== "GET":
data = request.params.get('post_data')
print(data[b'code'][0].decode('utf8'))
# yield "接口处理相关".encode('utf8')
code = data[b'code'][0].decode('utf8')
result = runcode(code)
yield result
else:
yield "Nothing".encode('utf8')
if __name__ == "__main__":
app.run(host='127.0.0.1', port=8888)
通过装饰器就可以实现非常方便的路由映射,结合server的分发处理,就可以实现针对不同的路径实现不同的功能了。
exector
临时代码执行这块稍微有点问题,经过测试,我发现使用subprocess.Popen()并不是一个很好的解决办法。具体表现在:
临时文件清理工作不够及时,不够彻底。
有待进一步改进。
目前版本也只是够用。。。。。。
# coding: utf8
"""
接受Python脚本,执行相关代码,返回相应结果。
"""
import subprocess
import os
def runcode(data):
"""
运行前台传过来的Python代码
"""
# 删除临时文件, 防止上次产生的结果产生影响。
if os.path.exists('temp.py'):
os.remove('temp.py')
with open('temp.py', 'w', encoding='utf8', buffering=1) as f:
f.write(data)
f.close()
# 开启管道,获取执行结果
process = subprocess.Popen('python temp.py', stdout=subprocess.PIPE)
data = process.stdout.read()
del process
return data
前端
前端我的思路就是利用ajax实现前后端的分离逻辑。让页面和数据处理分离开来,更高效的处理各自的事物。
ajax
为了验证方便性,我用原生的JavaScript和JQuery分别作了实现,发现还是JQuery好用啊,让我们可以更专注于事物的处理而不是纠结于控制结构上。(⊙﹏⊙)b
function send() {
// 先获取文本域内的代码值
var sourcecode = $("#sourcecode").val();
// var sourcecode = document.getElementById("sourcecode").value;
// 借助ajax实现功能获取
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
console.log(xhr.responseText)
}
}
xhr.open('post', '/api/user')
xhr.send({ 'code': sourcecode })
}
function send2(){
// 更新聊天页面
update_chat();
// 请求代码执行结果
$.ajax({
url: '/api/user',
type: "POST",
dataType: "json",
async: true,
data: {'code': $("#sourcecode").val()},
success: function(response){
console.log("Success.")
console.log(response)
// console.log(response.responseText);
// eval('var data = '+ response.responseText)
// result = response.responseText
update_robot(response.content);
},
error: function(msg){
console.log("Error.")
console.log(msg.responseText);
result = msg.responseText;
update_robot(result);
}
})
// document.getElementById("sourcecode").value = "";
// 更新滚动条,以便于自动上划。
scroll_top();
}
页面更新
这里页面更新的触发时机应该是每次点击完发送按钮之后,所以只需要在按钮的响应函数里面添加相应的逻辑即可。
function update_chat(){
console.log("Ready to append mywords.")
// 先创建本人说话的内容节点
var source = $("#sourcecode").val();
// http://avatar.csdn.net/0/8/F/3_marksinoberg.jpg
child_node = "<div class='mywords'><img src='http://avatar.csdn.net/0/8/F/3_marksinoberg.jpg'><span>"+source+"</span><br /><br /></div>"
var mywords = $(child_node);
$("#lefttop").append(mywords);
}
function update_robot(result){
console.log('更新聊天机器人代码执行结果。')
// 创建代码返回结果的节点
child_node = "<br /><br /><div class='robot'><span>"+result+"</span><img src='http://avatar.csdn.net/0/B/4/1_yangwei19680827.jpg'></div>"
var robot_words = $(child_node);
$("#lefttop").append(robot_words);
}
// 页面自动上划
function scroll_top(){
var messagebox = document.getElementById("lefttop");
messagebox.scrollTop = messagebox.scrollHeight-messagebox.style.height;
}
演示
下面来看几个图片,聊表心意。
简易“应答”模式
“代理模式”处理外部请求
后台日志
总结
已知问题:
- make_server 本身的处理问题。
- temp.py临时文件更新问题
- 静态文件路径处理的不是很好(⊙﹏⊙)b
完整代码可以到我的GitHub上进行download。
类Flask实现前后端交互之代码聊天室的更多相关文章
- 编写一个简单的flask的前后端交互的网页(flask简单知识的讲解)
实验原理: 1.什么是flask Flask是一个使用Python编写的轻量级Web应用框架,其WSGI工具采用Werkzeng,模板引擎使用Jinja2.Flask与 Django之间的区别就是Dj ...
- Flask form前后端交互消息闪现
模拟场景如果当用户注册时输入错误而由于form表单是同步提的交跳转到另一个网页时提示注册失败这时用户还需返回注册页面重新填写大大降低了客户体验,消息闪现能伪装成异步(实际还是同步)就是自己提交给自己然 ...
- 2、前端--初见前后端交互、CSS简介、基本选择器、组合选择器、属性选择器、分组与嵌套、伪类选择器
今日内容概要 初窥后端框架 css简介 css选择器 今日内容详细 初次体验前后端交互 # 代码无需掌握 只看效果即可 """后端框架:可以简单的理解为别人写好的一个非常 ...
- Flask + vue 前后端分离的 二手书App
一个Flask + vue 前后端分离的 二手书App 效果展示: https://blog.csdn.net/qq_42239520/article/details/88534955 所用技术清单 ...
- springboot+mybatis+thymeleaf项目搭建及前后端交互
前言 spring boot简化了spring的开发, 开发人员在开发过程中省去了大量的配置, 方便开发人员后期维护. 使用spring boot可以快速的开发出restful风格微服务架构. 本文将 ...
- Servlet实现前后端交互的原理及过程解析
在日常调试项目时,总是利用tomcat去启动项目,并进行前后端联调,但对于前后端的请求响应的交互原理及过程并不是特别清晰. 为什么在前端发出相应请求,就能跳转到后端通过程序得到结果再响应到前端页面呢? ...
- Python 利用三个简易模块熟悉前后端交互流程
准备工作 在学习Django之前,先动手撸一个简单的WEB框架来熟悉一下前后端交互的整体流程 本次用到的模块: 1.wsgiref,这是一个Python自带的模块,用于构建路由与视图 2.pymysq ...
- Node之简单的前后端交互
node是前端必学的一门技能,我们都知道node是用的js做后端,在学习node之前我们有必要明白node是如何实现前后端交互的. 这里写了一个简单的通过原生ajax与node实现的一个交互,刚刚学n ...
- itest 开源测试管理项目中封装的下拉列表小组件:实现下拉列表使用者前后端0行代码
导读: 主要从4个方面来阐述,1:背景:2:思路:3:代码实现:4:使用 一:封装背景 像easy ui 之类的纯前端组件,也有下拉列表组件,但是使用的时候,每个下拉列表,要配一个URL ...
随机推荐
- 浅谈 JS 内存泄露方式与避免方法(二)
Concept WHAT : 内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.正常情况下,垃圾回收器在DOM元素和event处理器不被引用或访问的时候回收它们.但是,IE的早些 ...
- Tornado的基本知识
Tornado是FriendReed使用的可扩展的非阻塞式的web服务器及其相关工具的开源版本. 这个框架看起来有些像web.py或者Google的webapp,不过为了能有效利用非阻塞服务器环境,这 ...
- curl简介、安装及使用
目录 curl简介 curl安装 curl使用 curl简介 curl是Linux下一个强大的文件传输工具,它利用URL语法在命令行方式下工作,支持文件上传和下载. curl安装 Ubuntu系统键入 ...
- redhat 9.0安装完不能上网解决办法(补) - 并附上redhat9.0 下载链接
昨天一位网友Q我,说我的开发环境搭建教程按步骤最后上不了网怎么解决我才突然想起9.0版本在VM7,8中存在问题,于是今天我就简单说下解决的方法. 由于本人习惯使用redhat 9.0版本所以到现在还是 ...
- Java程序设计专题
- pc端html页面到移动端等比缩放
head标签里面加这个<meta name="viewport" content="user-scalable=yes">
- usb gadget虚拟串口【转】
本文转载自:https://blog.csdn.net/luckywang1103/article/details/61917916 配置 配置好之后编译重新烧写到开发板,发现出现了/dev/ttyG ...
- js异步获取数据的问题
最近做js开发的时候发现了很多哥们不能区分同步和异步的区别,典型的在ajax部分,在该ajax为异步操作的时候,获取不到success之后的data的值,于是产生了各种奇葩的写法.比如创建一个局部变量 ...
- Jquery.LazyLoad.js实现图片延迟加载功能
从网上下载来的版本多多少少都有些BUG,尤其是加载后在IE6和IE7下图片闪动是个大问题,在网上查了很久,也没有找到相关的解决方案.没解决方案,就得发挥咱DIY的精神,自己想法解决,分析了BUG,理了 ...
- 八步学会数据迁移:ETL工具kettle使用方法
一.目的 将不同服务器上的表合并到另外一个服务器上.例如:将服务器1上的表A和服务器2上的表B,合并到服务器3上的表C 要求:表A需要被裁剪(去掉不必要的字段).表B需要增加一些字段 二.使用方法 ( ...