flask入门
Oct 21, 2018 09:54 · 1167 words · 6 minute read
入门笔记。
2018-10-21 开始 > 2018-11-1结束
flask学习
- flask学习
- 安装flask的运行环境
- 运行环境
- 路由
- debug,模式
- 唯一 URL / 重定向行为
- 使用配置文件
- 传参
- 根据函数名生成对应的url
- 页面跳转
- Flask渲染Jinja2模板和传参(html模板使用)
- 简单的if语句的实现
- for循环
- 字典的遍历
- 列表的遍历
- 简单的小示例
- 过滤器
- 常用的过滤器
- flask的继承
- flask的继承之block
- url链接
- 加载静态文件
- Flask-SQLAlchemy的介绍与安装
- session的使用
- 传参
- g对象
- 钩子函数
安装flask的运行环境
0x01 安装virtualenv
sudo apt-get install python-virtualenv
virtualenv 安装完毕后,你可以立即打开 shell 然后创建你自己的环境。我通常创建一个项目文件夹,并在其下创建一个 venv 文件夹
➜ Yang mkdir demo
➜ Yang cd demo
➜ demo ls
➜ demo virtualenv venv
0x02 安装flask
pip install flask
0x03 配置mysql
需要安装 mysql-python
.
在执行 (venv) ➜ flask pip install mysql-python
时报错
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-RFPXoe/mysql-python/
原因是没有安装相关依赖。 ubuntu下解决办法
(venv) ➜ sudo apt-get install libmysqlclient-dev
(venv) ➜ sudo apt-get install python-dev
安装时要注意,要在venv环境下安装
即在执行. venv/bin/active
的目录下
运行环境
. venv/bin/activate
路由
@app.route('/')
def hello_word():
return 'hello word'
@app.route('/index')
def index():
return "this is index page!"
if __name__ == '__main__': # 如果当前这个文件是作为入口程序运行的话,就会执行`app.run`。
app.run()
利用route装饰器将函数与路径绑定,这个route装饰器的作用就是做一个url与视图函数的映射。 即访问127.0.0.1:5000、/
便执行hello_word
函数
debug,模式
开启debug模式
app.run(debug=True)
作用1
将报错信息输出到页面
作用2
开启debug的文件内容如果被改动,就会自行重启服务器,也就是重新加载,不用在去重新运行`python 1.py`
唯一 URL / 重定向行为
使用route设置路径的时候最好带上斜线,原因如下
例1:
@app.route('/index')
def index():
return "this is index page!"
# http://127.0.0.1:5000/index/ 会报错 404 not found
# http://127.0.0.1:5000/index
例2:
@app.route('/index/')
def index():
return "this is index page!"
# http://127.0.0.1:5000/index/
# http://127.0.0.1:5000/index 会重定向到 /index/
使用配置文件
在项目根目录新建config.py
在主函数文件导入config.py,并且配置到app
中,
import config
app.config.from_object(config)
config.py
#encoding: utf-8
import os
DEBUG = True
SECRET_KEY = os.urandom(24)
config中的变量要大写,不然不起作用。
传参
示例
@app.route('/id/<int:id>')
def show(id):
return 'this is you id %s' % id
# http://127.0.0.1:5000/id/1
# 输出 this is you id 1
根据函数名生成对应的url
from flask import Flask,url_for
app = Flask(__name__)
@app.route('/')
def index(): pass
@app.route('/login')
def login(): pass
@app.route('/test_name/<username>')
def profile(username): pass
with app.test_request_context():
print url_for('index')
print url_for('login')
print url_for('login',next='123',ne='sa')
print url_for('profile',username='yang',nexe='1')
作用 重定向和跳转页面的时候使用该函数
页面跳转
#encoding: utf-8
from flask import Flask,url_for,redirect
app = Flask(__name__)
@app.route('/')
def index():
# return redirect('/login/')
return redirect(url_for('login'))
return 'this is index page'
@app.route('/login/')
def login():
return 'this is login pa1ge'
if __name__ == '__main__':
app.run(debug=True)
Flask渲染Jinja2模板和传参(html模板使用)
flask的渲染方法有render_template
和render_template_string
两种。
模板的使用需要 导入render_template
和render_template_string
模块。
调用示例
# return render_template('demo.html')
# return render_template_string('<script>alert(1);</script>')
主要看一下 render_template
的使用
1. render_template
同目录下新建templates
文件夹。(刚开始少写了一个s
,运行的时候一直报500.)
templates
文件夹下存放html文件。目录结构如下
templates/
demo.html
sec_html/
demo1.html
1.py
1.py
#encoding: utf-8
from flask import Flask,request
from flask import render_template
app = Flask(__name__)
@app.route('/html/')
def html_page():
# 两种传入HTML文件参数的方式
# return render_template('demo.html',username='yang',password='1234')
content = {
'username' : 'yang',
'password' : '1234',
'array':{
'yang': 'yam',
'Yang1k' : 'Yang1k'
}
}
return render_template('demo.html',**content)
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>my name is {{username}} and my password is {{password}}</h1>
<h1>my name is {{array.yang}} and my password is {{array['Yang1k']}}</h1>
</body>
</html>
简单的if语句的实现
1.py
@app.route('/login_res/<int:is_login>')
def is_login(is_login):
print url_for('is_login',is_login='1')
content={
'username' : 'yang',
'age': 18
}
if is_login == 1:
return render_template('demo.html',**content)
else:
return render_template('demo.html')
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{% if username and age>17%}</h1>
<h4>my name is {{username}}</h4>
<h4>my age is {{age}}</h4>
{%else%}
<h4>么有信息</h4>
{% endif %}
</body>
</html>
url http://127.0.0.1:5000/login_res/0
for循环
字典的遍历
1.py
@app.route('/for')
def for_1():
user = {
"username":"yang",
"age":"11"
}
# for k,v in user.items():
# print k
# print v
return render_template("demo.html",user=user)
遍历的时候还可以使用keys()
和values()
函数。不是只有items()
函数
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for k,v in user.items()%}
<h5>{{k}} is {{v}}</h5>
{% endfor%}
</body>
</html>
列表的遍历
1.py
@app.route('/list')
def for_list():
user = ['yang','Yang1k']
for x in user:
print x
return render_template('demo.html',user=user)
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for x in user %}
<h4>name : {{x}}</h4>
{% endfor %}
</body>
</html>
简单的小示例
1.py
@app.route('/books')
def books():
information = [
{
'name' : u'西游记',
'price' : '45',
'number' : '777'
},
{
'name' : u'三国演义',
'price' : '46',
'number' : '888'
},
{
'name' : u'水浒传',
'price' : '47',
'number' : '999'
},
{
'name' : u'红楼梦',
'price' : '48',
'number' : '1000'
}
]
# for book in information:
# print book['name']
return render_template("demo.html",xinxi=information)
# return '1'
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1px">
<tr>
<td>书名</td>
<td>钱</td>
<td>页</td>
</tr>
{% for book in xinxi%}
<tr>
<td>{{book['name']}}</td>
<td>{{book['price']}}</td>
<td>{{book.number}}</td>
</tr>
{% endfor%}
</table>
</body>
</html>
过滤器
- default
- length
default - 如果变量的值为空,则取default设置的值。
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{a|default('qweqwe')}}
</body>
</html>
- length
1.py
@app.route('/guolv')
def index_1():
comment = [
{
'user' : 'yang',
'pass' : '123'
},
{
'user' : 'Yang1k',
'pass' : '456'
}
]
return render_template('demo.html',comment=comment)
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
数量:{{comment|length}}
{% for comment in comment%}
<li>{{comment.user}}</li>
<li>{{comment.pass}}</li>
{% endfor %}
</body>
</html>
输出结果
数量:2
yang
123
Yang1k
456
常用的过滤器
abs(value):返回一个数值的绝对值。示例:-1|abs
escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。显例:content|escape或content|e。
first(value):返回一个序列的第一个元素。示例:names|first
format(value,arags,*kwargs):格式化字符串。比如:{{ "%s" - "%s"|format('Hello?',"Foo!") }}将输出:Helloo? - Foo!
last(value):返回一个序列的最后一个元素。示例:names|last。
length(value):返回一个序列或者字典的长度。示例:names|length。
join(value,d=u”):将一个序列用d这个参数的值拼接成字符串。
safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。
int(value):将值转换为int类型。
float(value):将值转换为float类型。
lower(value):将字符串转换为小写。
upper(value):将字符串转换为小写。
replace(value,old,new): 替换将old替换为new的字符串。
truncate(value,length=255,killwords=False):截取length长度的字符串。
striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
trim:截取字符串前面和后面的空白字符
string(value):将变量转换成字符串。
wordcount(s):计算一个长字符串中单词的个数。
flask的继承
这里的继承和php的include是一个意思的。
具体写法
1.py
@app.route('/user_login/')
def user_login():
return render_template('login.html')
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="main.js"></script>
</head>
<body>
{% extends 'base.html' %} <!-- 继承的写法 -->
</body>
</html>
同目录下新建base.html,这个文件就存放着公用的代码
base.html
<style>
.nav{
background-color: #3a3a3a;
height: 65px;
}
ul{
overflow: hidden;
}
ul li{
float: left;
list-style: none;
padding: 0 10px;
line-height: 65px;
}
ul li a{
color: #ffffff;
}
</style>
<div class="nav">
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">发布问答</a></li>
</ul>
</div>
flask的继承之block
先写一下block的作用,extends是继承了整个base.html文件里的所有的公用代码,但是如果还想在生成的子页面中添加一些自定义的代码呢,看代码
base.html(公用代码)
<!DOCTYPE html>
<html>
<head>
<style>
.nav{
background-color: #3a3a3a;
height: 65px;
}
ul{
overflow: hidden;
}
ul li{
float: left;
list-style: none;
padding: 0 10px;
line-height: 65px;
}
ul li a{
color: #ffffff;
}
</style>
</head>
<body>
<div class="nav">
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">发布问答</a></li>
</ul>
</div>
{% block main%}
{% endblock %}
</body>
</html>
index.html
{% extends 'base.html'%}
{% block main%}
<h1>this is hello page</h1>
{% endblock %}
login.html
{% extends 'base.html' %}
{% block main%}
<h1>this is login page!</h1>
{% endblock%}
这里如果不使用block
,直接在index.html , login.html中写html代码的话,页面是无法正常显示html代码的。所以要在base.html
中添加一个模板,然后在子文件中使用block
来继承模板,然后再在block
中写html代码。
blockl
就相当于占位符的作用。
url链接
使用 url_for()
函数可以反转生成url。
加载静态文件
- 语法
url_for('static',filename='路径')
- 静态文件 ,flask会自动从
static
文件夹开始寻找,所以不需要再写static
这个路径 - 可以加载css文件,js文件,还有image图片
- 要把静态文件放在
static
目录下 直接在html中写就可以。
示例(加载图片) index.html
<img src="{{ url_for('static',filename='7.jpg')}}" alt="">
1.py
@app.route('/css/')
def css():
return render_template('index.html')
Flask-SQLAlchemy的介绍与安装
- ORM: Object Relationship Mapping(模型关系映射)
- flask-sqlalchemy是一套ORM框架
- ORM的好处,可以让我们操作数据库跟操作对象一样简单,很方便。一个表就抽象成一个类,一条数据就抽象成该类的一个对象。
- 安装
Flask-SQLAlchemy
:pip install flask-sqlalchemy
session的使用
需要导入session模块的
from flask import session
app.config['SECRET_KEY'] = os.urandom(24)
#设置session
@app.route('/sess/')
def hi():
session['name'] = 'Yang'
return 'hello word'
# 读取session
@app.route('/get/')
def get():
return session.get('name')
# 删除session其中的一个
@app.route('/delete/')
def delete():
print session.get('name')
session.pop('name')
print session.get('name')
return 'sussec'
# 清除session中的所用变量
@app.route('/clear/')
def clear():
print session.get('name')
session.clear()
print session.get('name')
return 'sussec'
# 设置session过期时间
@app.route('/sess/')
def hi():
session['name'] = 'Yang'
# 默认是flase,会话结束后session就过期。设置是True后,过期时间为30天
session.permanent = True
return 'hello word'
尝试将session.permanent = True
设置到config里,但是不行。那就哪里用到了,就在哪里设置吧。
传参
获取get传参
@app.route('/get/') def re_get(): # 获取get参数 a = request.args.get('id') return a
post传参
# 如果不写明`methods`的话,post请求将不被允许 @app.route('/login/',methods=['get','POST']) def login(): # 区分大小写 if request.method == 'GET': return render_template('login.html') else: # 获取post传参的值 username = request.form.get('username') password = request.form.get('password') return '%s %s'%(username,password)
g对象
使用示例
''' g对象 '''
from flask import g
from utils import login_log
@app.route('/login/',methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
password = request.form.get('password')
g.username = username
login_log()
if username == 'yang' and password == 'qwe':
return u'登录成功'
else:
return u'账号密码错误!'
在根目录新建untils.py
,内容如下
#encoding: utf-8
from flask import g
def login_log():
print u'%s 登录成功'%(g.username)
g对象就是一个全局数组一样。 g:global 1. g对象是专门用来保存用户的数据的。 2. g对象在一次请求中的所有的代码的地方,都是可以使用的。
钩子函数
- before_request before_request:在请求之前执行的
这个函数只是一个装饰器,可以让代码在视图函数执行之前执行。
简单示例
@app.before_request
def before():
if session.get('username'):
g.username = session.get('username')
- 上下文处理器
1.py
上下文处理器
@app.context_processor
def my_context():
return {'username':'yang'}
@app.route('/content/')
def content():
return render_template('index.html',username='yang')
# 在使用了上下文处理器后,下面这种渲染方法也是ok的。
return render_template('index.html')
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>
{{username}}
</body>
</html>
在渲染模板的时候需要在渲染函数中设置username
变量,才可以在index.html中显示出username,但是如果使用上下文处理器,他会自动注册username变量,使其在所有模板中均可使用。
这个可以用到判断是否有用户登录,如果用户登录的话,就将用户名赋值给username,这样所有的模板文件都可以使用username变量了。