Flask学习#
1.1 配置环境与访问#
- 配置环境
1
2
3
| cdvirtualenv 进入虚拟环境
rmvirtualenv 删除虚拟环境
lsvittualenv 列出虚拟环境
|
- 自己安装:
进入终端中进入虚拟环境—–>
1
2
3
| pip list
pip install pymysql
pip install flask==1.0(卸载原来的版本,安装指明的版本)
|
- 项目结构介绍:
1
2
3
4
| --项目名:
|---static (静态)js css
|---templates(模板)
|--app,py(运行引启动)
|
新建Flask项目
1
2
3
4
5
6
7
8
9
10
11
12
| from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world(): # put application's code here
return '哈哈哈'
if __name__ == '__main__':
app.run()
|
路由 URL http://127.0.0.1:5000
WSGI: Python Web Server Gateway Interface 是为Python语言定义的Web应用程序
Flask内置服务器 nginx
app = Flask(__name__)
run(host=‘ip地址’,port=‘端口号’)
ip地址,一个端口号对应的是一个程序
http://192.168.1.5:5000/ 如果host改成: 0.0.0.0 外网可以访问默认情况下只能是本机。
app.run(host=‘0..0.0’,port=5001, debug=True)
debug: 布尔类型的
debug=True 开启了debug调试模式 只要代码改变服务器会重新加载最新的代码
debug=False 默认 代码发生改变不会自动加载 适用于production环境
注意!这一步在Pycharm可能有坑!
1.2 Flask请求响应#
可以另起settings来实现ENV环境
设置
设置配置文件:
settings
配置文件
1
2
| ENV 'development'
DEBUG True
|
路由的请求和响应:
浏览器地址栏输入的内容:http://192.168.1.5:8000/index
—-> 服务器 —–>app—–> 有没有这个路由
—-> 就会执行路由匹配的函数——> return’heLL0 world’
—–> response——> 客户端的浏览器
请求:request
http协议:
request请求
请求行:
请求地址:http://0.0.0.0:8000/index
请求方法是什么? method:get post
请求头: key:value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding:
gzip, deflate, br
Accept-Language:
zh-CN,zh;q=0.9
Cache-Control:
max-age=0
Connection:
keep-alive
Host:
127.0.0.1:5000
Sec-Ch-Ua:
"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"
Sec-Ch-Ua-Mobile:
?0
Sec-Ch-Ua-Platform:
"Windows"
Sec-Fetch-Dest:
document
Sec-Fetch-Mode:
navigate
Sec-Fetch-Site:
none
Sec-Fetch-User:
?1
Upgrade-Insecure-Requests:
1
User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
|
response
响应
响应行:状态码
200 ok,404 not found,500 服务器端错误(Server Internal Error),302 状态码302表示重定向。它是指请求的资源已被分配到新的URL上
1
2
3
4
5
| 响应头
Content-Length:18
Content-Type:text/html;charset=utf-8
Date:Mon,18 May 2020 08:57:02 GMT
Server:Werkzeug/1.0.1 Python/3.7.4
|
响应体:
1
| <font color="red">Hello World333333!</font>
|
Hello World333333!
1.3 Flask的路由和变量规则#
settings配置
1
2
| ENV = 'development'
DEBUG = True
|
另配置文件生效
app.config.from_object(settings)
route就是路由
1
2
3
4
| def index():
return 'welcome everyone!'
app.add_url_rule('/index', view_func=index) #这两行代码表示内容相同
|
1
2
3
4
5
6
| route:
def route(self,rule,**options):
def decorator(f):
self.add_url_rule(rule, endpoint, f,**options)
return f
return decorator
|
这个装饰器其实就是将rule字符串跟视图函数进行了绑定,通过add_url_rule()
实现的绑定
1
2
3
| @app.route('/index')
def index():
return 'welcome everyone!'
|
1
2
3
4
5
6
| data = {'a' : '北京','b' : '上海','c' : '深圳'}
@app.route('/getcity/<key>') #key就是一个变量名,默认是字符串类型的
def get_city(key):
print(type(key))
return data.get(key)
|
在浏览器中输入 http://0.0.0.0:5000/getcity/a 打印出北京
同理,输入 http://0.0.0.0:5000/getcity/b 打印出上海
1
2
3
4
| @app.route('/add/<int:num>')
def add(num):
result = num + 18
return (result)
|
进入http://0.0.0.0:5000/add/15
此时会报错,在DEBUG页显示
返回类型必须是字符串、字典、列表、带有标题或状态的元组、响应实例或可调用的 WSGI,但它是一个 int。
则我们需要把result
进行转换
1
2
3
4
| @app.route('/add/<int:num>')
def add(num):
result = num + 18
return str(result)
|
进入http://0.0.0.0:5000/add/15
正常显示
1.4 Flask的变量规则和相应对象#
1
2
3
4
| @app.route('/add1/<float:money>')
def add1(money): #注意!是add1!!!
print('--->', type(money))
return str(money)
|
1
2
3
4
5
| @app.route('/index/<path:p>')
def get_path(p):
print('--->', type(p)) #p是字符串(str)类型的
print(p)
return p
|
进入 http://0.0.0.0:5000/index/first/a1/111
得到
1
2
3
4
| @app.route('/test/<uuid:id>')
def test(id)
print('#####>>>',type(id)) #传值要符合uuid的格式才行 uuid模块 uuid.uuid4()----->UUID类型
return '获取唯一的标识码'
|
1
2
3
4
5
6
7
8
9
10
| import uuid
uid = uuid.uuid4()
print(uid)
print(type(uid))
uid1 = str(uid)
print(type(uid1))
uid1 = uid1.replace('-','')
print(uid1)
|
进入 http://0.0.0.0:5000/test/
路由的变量规则:#
string |(缺省值)接受任何不包含斜杠的文本
int 接受正整数
float 接受正浮点数
path 类似 string,但可以包含斜杠
uuid 接受 UUID 字符串
1
2
3
| @app.route('/getcity/<key>')
def get_city(key): #参数是必须添加的
return data.get(key)
|
response对象#
return 返回的字符串其实是做了一个response对象的封装,最终返回的还是response对象
1
2
3
4
5
6
7
| from flask import Flask
app = Flask(__name__)
@app.route('/index2')
def index2():
return 'hello', 200
|
1
2
3
4
5
6
7
| from flask import Flask
app = Flask(__name__)
@app.route('/index2')
def index2():
return 'sorry!page not found!', 404
|
可以自定义返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| from flask import Flask, make_response
app = Flask(__name__)
@app.route('/index2')
def index2():
return 'sorry!page not found!', 404
@app.route('/index4')
def index4():
content = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
div {
width: 100%;
height: 100px;
border: 2px solid red;
}
</style>
</head>
<body>
<h1>欢迎来到测试购物网站</h1>
<div>
<ul>
<li>hello</li>
<li>abc</li>
<li>world</li>
</ul>
</div>
</body>
</html>
'''
reponse = make_response(content) #返回值就是一个response对象
reponse.headers['mytest'] = '123abc'
return reponse
if __name__ == '__main__':
app.run()
|
返回值:
response响应对象
request对象#
参数:
1
2
3
4
5
| @app.route('/register')
def register():
r = render_template('register.html')
print(r)
return r
|
模板:
需要把模板放到templates目录下
重定向和url#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| @app.route('/register', methods=['GET','POST'])
def register():
print(request.method)
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
repassword = request.form.get('repassword')
#用户密码一致性验证
if password == repassword:
#保存用户
user = {'username': username, 'password' : password}
users.append(user)
return redirect('/')
else:
return '两次密码不一致'
return render_template('register.html')
|
视图函数的返回值:
response响应:
- str 自动转成response对象
- dict json
- response对象 response对象
- make_response() response对象
- redirect() 重定向 302状态码
- render_template()| 模板渲染 + 模板
模板介绍(jinja2)
模板:(网页)
模板的语法:
- 在模板重获取view中传递的变量值: {{ 变量名key }}
render_template(‘模板名字’,key=value,key=value)
name = 'python' #字符串
age = 18 #整型
friends = ['a','b','c'] #列表
dict1 = {'a':1,'b':2,'c':3} #字典
#创建对象
girlfrind = GirlFriend('小红','河南郑州') #自定义类构造的类型,Girl对象
模板:
{{ list.0 }} 同 {{ list[0] }}
{{ dict.key }} 同 {{ dict.get(key) }}
{{ girl.name }} 同 {{ 对象.属性 }}
- 控制块:
{% if 条件表达式 %}
{% elif 条件表达式 %}
{% else %}
{% endif %}
{% for 变量 in 可迭代对象 %}
{% endfor %}
{% while 条件表达式 %}
{% endwhile %}
{% break %}
{% continue %}
1
2
3
4
5
| <ul>
{%for girl in girls%}
<li>{{gir}}</i>
{% end for%}
</ul>
|
可以使用Loop变量
Loop.index 序号从1开始
Loop.index0 序号从0开始
Loop.revindex reverse 序号是倒着的
Loop.revindex0
loop.first 布尔类型 是否是第一行
Loop.Last 布尔类型 是否是第二行
3.过滤器
过滤器的本质就是函数
模板语法中过滤器:
{{变量名 | 过滤器(*args)}}{{变量名 | 过滤器}}
常见的过滤器:
- safe:
禁用转译
1
2
| msg =<h1>520快乐!</h1>
return render_template('show_2.html', girls=girls,users=users, msg=msg)
|
不想让其转译:
{{ msg | safe }}
2. capitalize:单词的首字母大写 {{ n1 | capitalize }}
- Lower和upper
大小写的转换
- title: 每个单词的首字母大写
msg = ‘hello world’
{{ msg | title }}
- reverse: 字符串反转
msg = ‘hello world’
{{ msg | reverse }}
- format
格式化字符串
msg = ‘hello {0} {1}’
{{ msg | format(‘python’,‘520’) }}
- truncate: 字符串截取
msg = ‘hello world’
{{ msg | truncate(5) }}
list的操作
list的操作:
{#列表过滤器的使用#}
{{ girls | first }}
{{ girls | Last}}
{{ girls | length }}
{#{{girls | sum}}# 整型的计算}
{{ [1,3,5,7,9] | sum }-}
{{ [1,8,5,7,3] | sort }}
dict:
{% for v in users.0.values() %} —->获取值
{{ v }}
{% endfo r%}
{% for k in users.0.keys() %} ---->获取键
{{ k }}
{% endfor %}
{% for k,v in users.0.items()%} --->获取键值
-{{ k }}---{{ v }}
{% endfor %}
复习和自定义过滤器#
request
request.method —-> app.url_map request.args
request.form
response
- 字符串
- 字典
- tuple
- response对象
- make_response()
- render_template()
- redirect() —> response 重定向
render_template('模板名字',**context)
render_template('模板名字',name=nameage=age,…)
模板语法:
变量
{{ name }}
{{ age }}
字符串
列表
tuple
set
对象—->[s1,s2,s3]
—–>[{},{},{}]
过滤器:本质就是函数
通过flask模块中的add_template_filter方法
a. 定义函数,带有参数和返回值
b. 添加过滤器 app.add_template_filter(function1,name=’’)
c. 在模板中使用过滤器 {{ 变量名 | 过滤器名 }}
使用装饰器完成
a. 定义函数,带有参数和返回值
b. 通过装饰器完成,@app.template_filter(‘过滤器名字’)装饰步骤一的函数
c. 在模板中使用: {{f 变量 | 自定义过滤器 }}
模板:复用(举例:购物网站多个页面上下框架一样,只有中间内容不一样)
模板继承 *
include
flask模板继承和inlcude#