Python入门自学进阶-Web框架——42、Web框架了解-bottle、flask

WEB框架的三大组件:路由系统、控制器(含模板渲染)、数据库操作

微型框架:依赖第三方写的socket,WSGI,  本身功能少

安装:
pip install bottle


pip install flask

安装flask,同时安装了MarkupSafe、Werkzeug、Jinja2、itsdangerous。
Werkzeug是Python的WSGI规范的实用函数库。使用广泛,基于BSD协议,是Flask使用的底层WSGI库;
itsdangerous是flask中引用的一个第三方包,用来解决生成token等网络安全问题;
MarkupSafe为 Python 实现 XML/HTML/XHTML 标记安全字符串;
Jinja2是一个模板语言,是一个现代的、设计友好的、依照django模板的python模板语言;

pip install tornado

已经安装过。

Bottle:

一个程序文件完成整个网站:

from bottle import template,Bottle
root = Bottle()@root.route('/hello/')  
# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理,就是路由系统
def index():return "Hello World!"root.run(host='localhost', port=8080)
# 这里就是启动webserver服务器,然后等待请求

运行整个Python程序:

浏览器端请求:

上面的路由(即装饰器)是静态路由,还可以使用动态路由:

@root.route('/wiki/<pagename>')
def
 callback(pagename):
    ...

pagename作为参数变量名,匹配字符串。

@root.route('/object/<id:int>')
def
 callback(id):
    ...
id是一个int型的参数变量名。

@root.route('/show/<name:re:[a-z]+>')
def
 callback(name):
   ...
name是一个正则表达式参数变量。

@root.route('/static/<path:path>')
def
 callback(path):
    
return static_file(path, root='static')
定义路径,类似Django中的静态文件路径,主要是定义文件在服务器存储中的位置。

root指定的是项目中的一个目录,这里指定了项目中的static,在这个目录下有testcss.css文件,可以访问:

修改一下:

如果root为'static'不变,还可以这样访问:

对于路由对应的函数,除了返回字符串,还可以使用模板:

@root.route('/hello/')
# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
def index():# return "Hello World!"return template('<b>Hello {{name}}!</b>',name="小花")

对于template(),除了像上面直接在其中写模板外,还可以直接指定一个模板文件,如

return template(‘index.html’)

创建index.html文件。这里要注意的是默认bottle找模板的路径,在bottle中有如下配置变量

TEMPLATE_PATH = ['./', './views/'],即默认模板查找顺序是先在项目根目录,然后是views目录,我们可以添加自己定义的目录

最终程序:

from bottle import template,Bottle,static_file
import bottle
bottle.TEMPLATE_PATH.append('./templates/')root = Bottle()# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
@root.route('/hello/')
def index():print(bottle.TEMPLATE_PATH)# return "Hello World!"# return template('<b>Hello {{name}}!</b>',name="小花")return template("index.html")@root.route('/sta/<path:path>')
def callback(path):return static_file(path,root='static')root.run(host='localhost', port=8080)

运行程序后,打印的TEMPLATE_PATH为:['./', './views/', './templates/'],但是却找不到模板文件:

经过反复的测试,查找资料,这个问题我个人的理解是:

这个路径是linux系统的路径,在windows系统下失去效果,windows系统下,需要添加windows的绝对路径,使用os.path.abspath(os.path.join(os.path.dirname(__file__), "views")来获取windows下的绝对路径:

from bottle import run,template,Bottle,TEMPLATE_PATH
import os
app = Bottle()
TEMPLATE_PATH.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "templates")))
TEMPLATE_PATH.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "views")))
print(TEMPLATE_PATH)@app.route('/')
@app.route('/hello/<name>')
def index(name='default'):return template('hello.html',name=name)run(app,host='localhost',port=8080)

这时的TEMPLATE_PATH为:

['D:\\website\\bottlepro\\templates', './', './views/', 'D:\\website\\bottlepro\\views']

这时再访问,就没有问题了。

请求方法路由

@root.route('/hello/', method='POST')
def index():
    ...
 
@root.get('/hello/')
def index():
    ...
 
@root.post('/hello/')
def index():
    ...
 
@root.put('/hello/')
def index():
    ...
 
@root.delete('/hello/')
def index():
    ...

一个简单的登陆:

from bottle import template,Bottle,static_file,TEMPLATE_PATH,request,redirect
import osTEMPLATE_PATH.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'templates')))
root = Bottle()# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
@root.route('/login/',method=['GET','POST'])
def login():if request.method == "GET":return template('login.html')else:# v = request.forms  # POST的数据都保存# v = request.query  # GET发来的请求数据# v = request.body   # POST发来的请求数据u = request.forms.get('user')p = request.forms.get('pwd')print(u,p)return redirect('/index/')
@root.route('/index/')
def index():return template('index.html')@root.route('/sta/<path:path>')
def callback(path):return static_file(path,root='static')root.run(host='localhost', port=8080)
# 这里就是启动webserver服务器,然后等待请求
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>Bottle登录</h1><form action="/login/" method="post"><input type="text" name="user" placeholder="用户名"><input type="password" name="pwd" placeholder="密码"><input type="submit" value="提交"></form>
</body>
</html>

Bottle中的request其实是一个LocalReqeust对象,其中封装了用户请求的相关信息:

request.headers     :    请求头信息

request.query         :    get请求信息

request.forms         :     post请求信息

request.files            :    上传文件信息

request.params       :     get和post请求信息

request.GET             :     get请求信息

request.POST           :     post和上传信息

request.cookies        :     cookie信息     

request.environ        :     环境相关相关

bottle的模板,在使用for循环遍历列表生成<ul><li>时的问题:

@root.route('/index/')
def index():user_list = [{'id': 1, 'name': 'root1', 'age': 18},{'id': 2, 'name': 'root2', 'age': 19},{'id': 3, 'name': 'root3', 'age': 20},{'id': 4, 'name': 'root4', 'age': 21},]return template('index.html', user_list=user_list)

模板index.html:

<body>{{user_list}}<hr/><ul>% for item in user_list :<li>{{item}}<li/>% end</ul>
</body>

预想的是这样:

实际是这样:

多出来的这些空行,都是<li>::marker</li>,为何会多产生这些标签??怎么去掉?希望高手指点一二。

Flask:

基本框架与Bottle差不多,如下:

from flask import Flaskapp = Flask(__name__)@app.route('/index/')
def index():return "hello world!"if __name__ == "__main__":app.run()

启动后:

默认是在5000端口。访问:

在Flask()中,可以对静态文件和模板路径进行配置:相关参数如下

默认模板路径就是templates,

这个不像Bottle,项目下创建了templates,就可以直接找到。

传递参数:

@app.route('/index/')
def index():# return "hello world!"return render_template('flaskindex.html',k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})

模板:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>Flask index</h1>{{k1}} <!-- 单值 -->{{k2}} <!-- 列表 --><hr/><ul>{% for item in k2 %}<li>{{item}}</li>{% endfor %}</ul>{{k3}} <!-- 字典 --><hr/>{% for k,v in k3.items() %}{{k}}--{{v}}<br>{% endfor %}
</body>
</html>

还可以传递函数:

模板中:要在变量后加上小括号

Flask的动态路由方式:

  • @app.route('/user/<username>')
  • @app.route('/post/<int:post_id>')
  • @app.route('/post/<float:post_id>')
  • @app.route('/post/<path:path>')
  • @app.route('/login', methods=['GET', 'POST'])

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

与bottle一样,也有方法请求路由,即在路由中增加“method=”参数

对于Http请求,Flask会讲请求信息封装在request中(werkzeug.wrappers.BaseRequest),提供的如下常用方法和字段以供使用:

request.method
request.args
request.form
request.values
request.files
request.cookies
request.headers
request.path
request.full_path
request.script_root
request.url
request.base_url
request.url_root
request.host_url
request.host

Flask中使用cookie:使用make_response函数包装render_template,生成的对象有set_cookie方法。先导入make_response

@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj

Flask中重定向:redirect

url_for(别名),这里的别名就是函数名,不需要在route中单独定义

Flask中使用session,先导入session,from flask import session

要使用session,需要先配置一个SECRET_KEY,在Flask对象上设置,设置后才能在函数中使用:session['key']=value的方式

from flask import Flask,render_template,make_response,session,request,redirect,url_forapp = Flask(__name__)
app.config.update(SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/') # 要使用session,必须设置这个参数def myfun():return "<a>测试传递函数</a>"@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj@app.route('/login/',methods=['GET','POST'])
def login():if request.method =='POST':session['user'] = request.form.get('user') # 设置session内容url = url_for('redirectaliastest')return redirect(url)else:return render_template('login.html')@app.route('/testurlfor')
def redirectaliastest():print(session)  # login中设置的session在这里能打印出return render_template('flaskindex.html')if __name__ == "__main__":app.run()

关于Flask的中间件调用机制:

所有的WSGI在执行时,即实例化时,要先执行__call__()方法,

def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:return self.wsgi_app(environ, start_response)

这个方法返回的是是执行wsgi_app方法的结果,然后在进入到Flask。

我们可以将这个wsgi_app换成我们自定义的类,在__call__方法中添加我们自己的代码,最后在调用原来的wsgi_app,这样就在请求处理前,先经过了我们自己的处理,像Django的中间件就是这种机制实现的。

from flask import Flask,render_template,make_response,session,request,redirect,url_forapp = Flask(__name__)
app.config.update(SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/')def myfun():return "<a>测试传递函数</a>"@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj@app.route('/login/',methods=['GET','POST'])
def login():if request.method =='POST':session['user'] = request.form.get('user')url = url_for('redirectaliastest')return redirect(url)else:return render_template('login.html')@app.route('/testurlfor')
def redirectaliastest():print(session)return render_template('flaskindex.html')class Foo:def __init__(self,w):self.w = wdef __call__(self, environ,start_response):print("自己的中间件")obj = self.w(environ,start_response)return obj
if __name__ == "__main__":app.wsgi_app = Foo(app.wsgi_app)  # 将原来的wsgi_app换成我们的类,Foo加上括号,即Foo()会先init,然后call# call的时候先执行我们的逻辑(相当于中间件),最后执行原来的wsgi_app# 这种方法有点装饰器的设计模式app.run()

启动后,页面请求过程:

Flask的消息:取一次就消失:

放置在session中,使用flash(value),取用,get_flashed_message(),取完就删除了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/143849.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣每日一题(+日常水题|树型dp)

740. 删除并获得点数 - 力扣&#xff08;LeetCode&#xff09; 简单分析一下: 每一个数字其实只有2个状态选 or 不 可得预处理每一个数初始状态(不选为0,选为所有x的个数 * x)累加即可 for(auto &x : nums)dp[x][1] x;每选一个树 i 删去 i 1 和 i - 1 故我们可以将 i…

【笔记】离线Ubuntu20.04+mysql 5.7.36 + xtrabackup定时增量备份脚本

一、环境 ● Ubuntu版本查看 lsb_release -a● mysql 版本查看 mysql --version我的是ubuntu 20.04&#xff0c;mysql是5.7.36&#xff0c;所以要用 install_percona-xtrabackup-24 二、原理 备份 通过ubuntu自带的定时器运行增量备份脚本备份文件可以存储在映射后的其他…

26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法

声明 本文是学习GB-T 26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了工业用X 射线CT 装置(以下简称CT 装置)性能测试的术语、定义、缩略语以及空间 分辨力、密度分辨率…

#硬件电路设计VL817-Q7(B0)芯片拓展USB3.0一转四调试心得

供电电路 基于XL4005的电源供电电路 SS34肖特基二极管 ZMM5V1稳压二极管 SMAJ15A TVS &#xff08;注意这个封装搞错5V会短接&#xff09; Vout0.8*[1(R2R3)/R1] D14 SR05静电防护器件 一路稳压两路TVS 共模电感 &#xff1a; 型号&#xff1a; SDCW2012-2-900TF 品牌&#…

Mac 苹果系统使用nvm use 切换node版本号

windows在使用 nvm 管理并切换 node 时&#xff0c;通过 nvm use 切换node版本会全局切换。也就是node版本号切换后只要不手动更改就会一直保持当前版本号不变。 但博主最近换了苹果系统后&#xff0c;发现苹果系统不能全局更改node版本。我在 vscode中使用nvm use x.x.x之后&…

Midjourney 生成油画技巧

基本 prompt oil painting, a cute corgi dog surrounded with colorful flowers技法 Pointillism 点描绘法 笔刷比较细&#xff0c;图像更精细 oil painting, a cute corgi dog surrounded with colorful flowers, pontillismImpasto 厚涂绘法 笔刷比较粗&#xff0c;图像…

Prometheus-监控Mysql进阶用法(1)(安装配置)

阿丹&#xff1a; 在开发和生产环境中有可能会出现慢mysql等问题&#xff0c;那么这里就需要我们优秀的程序员来进行监控和解决&#xff0c;那么如何借助云原生的监控系统来完成这个操作呢&#xff1f; 环境描述&#xff1a; 使用一台空白的阿里云服务器2核4G。 服务器基本安装…

Python:使用PySimpleGUI中sg.Input控件获取数据plot导致yticks错乱

sg.Input获取y轴数据代码 sg.Text(First Read:, font("Times New Roman", 9)),sg.Input(key-first_read-, size(25, 1), default_text0,0,0, justificationcenter, font("Times New Roman", 9), expand_xTrue), sg.Text(Second Read:, font("Times Ne…

PHP8中的构造方法和析构方法-PHP8知识详解

今日分享的内容是php8中的构造方法和析构方法&#xff0c;我们把构造方法和析构方法这两个方法分开来讲&#xff1a; 1、构造方法 构造方法存在于每个声明的类中&#xff0c;主要作用是执行一些初始化任务。如果类中没有直接声明构造方法&#xff0c;那么类会默认地生成一个没…

人工智能 与 搜索引擎的较量

随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到了我们生活的方方面面&#xff0c;搜索引擎也不例外。AI与传统搜索引擎之间的较量成为了科技界和互联网用户关注的热点话题。 人工智能 与 搜索引擎的较量 A - 搜索引擎B - 人工智能AI 的优势理解力…

「C++之STL」关于在模拟实现STL容器中的深浅拷贝问题

文章目录 前言杨辉三角深浅拷贝问题模拟实现的vector对题目杨辉三角引发的程序崩溃原因解决办法 前言 在学习STL容器中,不仅需要学会容器的使用,同时也需要了解容器的大体框架以及各个函数的模拟实现才能更好的去了解这个容器; 杨辉三角 在LeetCode中有一道这样的题目,给定一…

jvm垃圾收集算法

简介 由于《分代收集理论》和不同垃圾收集算法&#xff0c;Java堆应该被划分为不同区域&#xff0c;一般至少会把Java堆划分为新生代&#xff08;Young Generation&#xff09;和老年代&#xff08;Old Generation&#xff09;两个区域。 垃圾收集器可以只回收其中某一个或者…

单片机外设-串口(UART)详情

目录 学习UART要先认识一些基础知识 一&#xff1a;什么是串行、并行通信&#xff1f; &#xff08;1&#xff09;串行通信 串行通信概念&#xff1a; 串行通信的特点&#xff1a; &#xff08;2&#xff09;并行通信 并行通信概念&#xff1a; 并行通信特点&#xff1…

【Linux】Linux远程访问Windows下的MySQL数据库

1.建立Windows防火墙规则 首先需要开放windows防火墙&#xff0c;针对3306端口单独创建一条规则&#xff0c;允许访问。 打开windows安全中心防火墙与保护&#xff0c;点击高级设置 进入之后&#xff0c;点击入站规则&#xff0c;新建一条规则 新建端口入站规则 端口填写330…

问题 - 谷歌浏览器 network 看不到接口请求解决方案

谷歌浏览器 -> 设置 -> 重置设置 -> 将设置还原为其默认值 查看接口情况&#xff0c;选择 All 或 Fetch/XHR&#xff0c;勾选 Has blocked cookies 即可 如果万一还不行&#xff0c;卸载浏览器重装。 参考&#xff1a;https://www.cnblogs.com/tully/p/16479528.html

C# 字符串和正则表达式

C# 字符串和正则表达式 System.String 类StringBuilder 成员格式化字符串正则表达式 System.String 类 StringBuilder 成员 格式化字符串 正则表达式

python加入环境变量

今天没事玩了会python,之前都是在windows下玩的&#xff0c;没什么问题。 今天要在dos窗口下运行python&#xff0c;却发现运行不了。而且在python安装目录下是可以运行的&#xff0c;于是我知道了我在安装python的时候没选择加入环境变量。我对windows还有是有定了解的&#x…

算法与数据结构-Trie树

文章目录 什么是“Trie 树”&#xff1f;如何实现一棵 Trie 树&#xff1f;Trie 树真的很耗内存吗&#xff1f;Trie 树与散列表、红黑树的比较 什么是“Trie 树”&#xff1f; Trie 树&#xff0c;也叫“字典树”。顾名思义&#xff0c;它是一个树形结构。它是一种专门处理字符…

你真的会自动化吗?Web自动化测试-PO模式实战,一文通透...

前言 PO模式 Page Object(简称PO)模式&#xff0c;是Selenium实战中最为流行&#xff0c;并且是自动化测试中最为熟悉和推崇的一种设计模式。在设计自动化测试时&#xff0c;把页面元素和元素的操作方法按照页面抽象出来&#xff0c;分离成一定的对象&#xff0c;然后再进行组…

《DATASET CONDENSATION WITH GRADIENT MATCHING》

本文提出了一种用于数据效率学习的训练集合成技术&#xff0c;称为“数据集凝聚”(Dataset)&#xff0c;它学习将大数据集压缩成一个小的信息合成样本集&#xff0c;用于从头开始训练深度神经网络。我们将这个目标表述为在原始数据和合成数据上训练的深度神经网络权值的梯度之间…