前言
突然意识到自己做了不少flask框架的题还没有好好学一下flask基础
而且ssti的题没学flask基础的话感觉学得不是特别明白
那就开个坑进行一个学
安装
已有python环境,命令行输入
pip install flask
即可安装
测试
from flask import Flask
app = Flask(__name__) # 创建一个flask实例
@app.route('/') # 路由规则,即符合规则的url请求将会触发此函数
def flask_test():
return '<h1>Hello World!</h1>'
if __name__ == '__main__': # 如果是已主程序的方式启动(不是以导入模块的方式),则运行flask实例
app.run(port=8000) # app.run(debug=True),即可开启debug模式
# 端口要选择没被占用的
运行py脚本,就开启了一个http://127.0.0.1:8000/
服务器
浏览器访问该地址
说明flask引入成功,并且能正常工作
代码分析
创建实例
from flask import Flask
app = Flask(__name__) # 创建一个flask实例
第一个参数是应用模块或者包的名称。 __name__
是一个适用于大多数情况的快捷方式。有了这个参数, Flask 才能知道在哪里可以找到模板和静态文件等东西
route路由
解析url地址和所携带的参数,对网络请求进行筛选
route中所带的参数是一个字符串类型,它的内容就对应它要响应的标示,即route()会告诉 Flask 触发函数的 URL
函数返回需要在用户浏览器中显示的信息。默认的内容类型是 HTML ,因此字符串中的HTML标签会被浏览器渲染。
@app.route('/')
def flask_test():
return '<h1>Hello World!</h1>'
通过把 URL 的一部分标记为 <variable_name>
就可以在 URL 中添加变量,监听带参数的url
@app.route('/name/<name>')
def flask_test(name):
return '<h1>Hello</h1>' + name
访问http://127.0.0.1:8000/name/admin
,此时admin被当做参数name传入函数中
再来一个例子看看
@app.route('/user/<username>')
def user(username):
return 'username:{0}'.format(username)
可以看到第二个route路由,其中加了/,这就是传入参数的接口,其中username相当于一个变量,将username放进def user()中,然后用format带入username
HTTP方法
缺省情况下,一个路由只回应
GET
请求。可以使用route()
装饰器的methods
参数来处理不同的 HTTP 方法。
from urllib import request
from flask import Flask,request
app = Flask(__name__)
@app.route('/method',methods = ['GET','POST'])
def method():
if request.method == 'GET':
return '现在的方法是GET'
elif request.method == 'POST':
return '现在的方法是POST'
if __name__ == '__main__':
app.debug = True
app.run('127.0.0.1','8080')
可以看到请求方法要大写,路由中要用[]
括起来
也可以把不同方法所对应的视图分别放在独立的函数中。 Flask 为每个常用 的 HTTP 方法提供了捷径,如get()
,post()
等等。
@app.get('/login')
def login_get():
return 'get'
@app.post('/login')
def login_post():
return 'post'
Redirect重定向
这个关键字在flask中用于重定向,需要配合url_for使用,url_for使用于构造url
比如常见的用法就是在登陆页面,输入正确的账号密码后,重定向到另外一个页面中
基础代码:
@app.route('/')
def index():
return redirect(url_for('login'))
使用例:
from flask import Flask,request,redirect,url_for
app = Flask(__name__)
@app.route('/login',methods = ['GET','POST'])
def login():
username = 'admin' # 定义username
password = '123456' # 定义password
user = request.args.get('username') # 获取传入的用户名
passwd = request.form['passwd'] # 获取传入的密码
if user == username and passwd == password: # 判断用户名和密码是否和预定义的一样
return redirect(url_for('login_s')) # 如果一样,则通过redirect和url_for重定向到login_s中
else:
return 'username or password error' # 错误则返回用户名或者密码错误
@app.route('/login_s',methods = ['GET']) # 定义一个新的页面login_s
def login_s():
return '登录成功' # 返回登陆成功
if __name__ == '__main__':
app.debug = True
app.run('127.0.0.1','8080')
没有传入参数的情况下访问/login会直接报错
传入错误的值,不发生重定向跳转
传入正确的值,此时重定向跳转到/login_s页面
main入口
当.py文件被直接运行时,if __name__ == '__main__'
之下的代码块将被运行;当.py文件以模块形式被导入时,if name == 'main'
之下的代码块不被运行
if __name__ == '__main__':
app.debug = True
app.run()
debug调试模式
flask编写的程序和php不一样,每一次变动都需要重启服务器来执行变更,就显得很麻烦,为了应对这种问题,flask中的debug模式可以在不影响服务器运行下,执行更新每一次的变更
测试的时候,我们可以使用debug,方便调试
下面两种方法都可以启用debug
app.debug = True
app.run(debug=True)
注:debug模式启用后,访问/console路由可以打开交互调试器进行命令执行,前提是知道pin码
debug开启后,请求过程中发生错误时会产生报错页面
模板渲染
在上面的路由部分我们知道可以在字符串中添加HTML标签来被浏览器渲染
但是这种办法过于笨拙,所以我们需要一个准备好的模板来帮我们完成这件事
模板渲染需要注意一点,py文件和外部文件要放在同一个文件夹下,并且放置外部文件的文件夹名,要重命名为templates
render_template
这个函数可以将py文件中的对应数据渲染至index.html,如果有多个参数,则使用形参的形式传出,如下面py文件代码所示,有三个参数,那么就用**contents传过去
index.html文件中,需要使用格式为
{{ 参数名 }}
接受参数值
例:
test.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
contents = {'username': 'admin', 'password': '123456', 'system': 'Hacker!'}
return render_template('index.html', **contents)
if __name__ == '__main__':
app.debug = True
app.run('127.0.0.1', '8000')
templates/index.html
<html>
<head>
<body>
<h1>Hello,{{username}}</h1>
<h2>{{password}}</h2>
<h3>{{system}}</h3>
</body>
</head>
</html>
render_template_string
这个是渲染字符串的一个函数,此函数可以将html代码变成字符串, 然后使用render_template_string(xxx)将文件渲染输出
这个可以用于没有外部文件的情况,直接在同文件下,定义好html代码,然后直接就可以渲染
render_template_string和render_template都是渲染,但是前者是字符串,后者是外部文件
基本语法
{%%}
:主要用来声明变量,也可以用于条件语句和循环语句
{% set c='ciallo' %}
{% if 81==9*9 %}ciallo{% endif %}
{% for i in ['1','2','3'] %}ciallo{%endfor%}
{{}}
:用于将表达式打印到模板输出,比如我们一般在里面输入2-1,2*2,或者是字符串,调用对象的方法,都会渲染出结果
{{2-1}} #输出1
{{2*2}} #输出4
这也就是SSTI的来源
{ ## }
:表示未包含在模板输出中的注释(使用时去掉里面的空格,博客渲染的时候也会被注释掉)
##
:有和{%%}
相同的效果
后日谈
咦,怎么和博客模板渲染差不多(