Python-flask学习笔记

Python虚拟环境安装

1
pip install virtualenv

Python激活虚拟环境

1
virtualenv [virtualenv-name]
1
activate

pip安装flask

1
pip install flask

使用pycharm创建新项目

程序基本结构

初始化Flask对象

传递一个参数

1
2
3
4
5
6
7
8

1.方便flask框架去寻找资源

2.方便flask插件比如Flask-Sqlalchemy出现错误时候好去寻找问题所在

```python
from flask import Flask
app = Flask(__name__)

创建路由与视图函数

1
2
3
@app.route('/')
def hello_world():
return 'Hello World!'

@app.route是一个装饰器,以@开头,并且在函数的上面,说明是装饰器

这个装饰器的作用,是做一个url与视图函数的映射,处理函数与url之间的映射成为路由

127.0.0.1:5000/ -> 去请求hello_world这个视图函数,然后将结果返回给服务器

启动服务器

1
2
if __name__ == '__main__':
app.run()

app.run()作用是启动一个应用服务器,来接受用户的请求

完整程序

1
2
3
4
5
6
7
8
9
10
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World!'

if __name__ == '__main__':
app.run()

设置debug模式

1.在app.run()中传入一个关键字参数debug,app.run(debug=True),就设置当前项目为debug模式

2.debug模式的两大功能:

(1)当程序出现问题的时候,可以在页面中看到错误信息和出错的位置。

(2)只要修改了项目中的python文件,程序会自动加载,不需要手动重新启动服务器

url传参数

1.参数的作用:可以在相同的URL,但是指定不同的参数,来加载不同的数据

2.在flask中使用参数

1
2
3
@app.route('/article/<id>')
def article(id):
return u'您请求的参数是: %s '%id

参数需要放在两个尖括号中

视图函数中需要放和url中的参数同名的参数

反转url

1.什么叫做反转URL:从视图函数到url的转换叫做反转url

2.反转url的用处:

(1)在页面重定向的时候,会使用url反转

(2)在模板中,也会使用url反转

3.例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#encoding: utf-8

from flask import Flask,url_for

app = Flask(__name__)

@app.route('/')
def hello_world():
print url_for('my_list')
print url_for('article',id=1000)
return 'Hello'

@app.route('/list/')
def my_list():
return 'list'

@app.route('/article/<id>')
def article(id):
return u'您请求的参数是: %s '%id

if __name__ == '__main__':
app.run(debug=True)

页面跳转和重定向

1.用处:在用户访问一些需要登录的页面的时候,如果用户没有登录,那么可以让他重定向到登录页面

2.代码实现:

1
2
from flask import redirect,url_for
redirect(url_for('login'))

3.例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#encoding: utf-8

from flask import Flask,redirect,url_for

app = Flask(__name__)

@app.route('/')
def index():
login_url = url_for('login')
return redirect(login_url)
return u'这是首页'

@app.route('/login/')
def login():
return u'这是登录页面'

if __name__ == '__main__':
app.run(debug=True)

访问127.0.0.1:5000/自动跳转到127.0.0.1:5000/login/

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
#encoding: utf-8

from flask import Flask,redirect,url_for

app = Flask(__name__)

@app.route('/')
def index():
login_url = url_for('login')
return redirect(login_url)
return u'这是首页'

@app.route('/login/')
def login():
return u'这是登录页面'

@app.route('/question/<is_login>')
def question(is_login):
if is_login == '1':
return u'这是发布问答的页面'
else:
return redirect(url_for('login'))

if __name__ == '__main__':
app.run(debug=True)

如果我们访问127.0.0.1:5000/question/0则自动重定向到登录页面

Flask渲染jinja2模板和传参

渲染模板

1.模板放在templates文件夹下

2.从flask中导入render_template函数

3.在视图函数中,使用render_template函数,渲染模板。注意:只需要填写模板的名字,不需要填写templates文件夹

模板传参

1.如果只有一个或者少量参数,直接在render_template函数中添加关键字就可以了

2.如果有多个参数的时候,那么可以先把所有的参数放在字典中,然后在render_template中,使用两个星号,把字典转换成关键参数传递进去,这样代码更方便管理和使用

3.在模板中,如果要使用一个变量,语法是:

例子:

index.html中内容

渲染模板代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
context = {
'username':u'知了课堂',
'gender':u'男',
'age':18
}
return render_template('index.html',**context)

if __name__ == '__main__':
app.run(debug=True)

模板中访问属性和字典

访问模型中的属性或者是字典,可以通过的形式,或者是使用

例子:

index.html

1
2
3
4
5
6
7
8
9
10
11
12
这是HTML文件中出现的文字
<p>用户名:{{ username }}</p>
<p>性别:{{ gender }}</p>
<p>年龄:{{ age }}</p>

<hr>
<p>名字:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>

<hr>
<p>百度:{{ websites.baidu }}</p>
<p>谷歌:{{ websites.google }}</p>

python代码:

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
#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
class Person(object):
name = 'somnus'
age = 18

p = Person()

context = {
'username':'somnus',
'gender':u'男',
'age':18,
'person':p,
'websites':{
'baidu':'www.baidu.com',
'google':'www.google.com'
}
}
return render_template('index.html',**context)

if __name__ == '__main__':
app.run(debug=True)

执行结果:

if判断

1.语法:

1
2
3
{% if 判断条件 %}
{% else %}
{% endif %}

2.if的使用,可以和python中相差无几

3.例子

if.html

1
2
3
4
5
6
7
{% if user %}
<a href="#">{{ user.username }}</a>
<a href="#">注销</a>
{% else %}
<a href="#">登录</a>
<a href="#">注册</a>
{% endif %}

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/<is_login>/')
def index(is_login):
if is_login == '1':
user = {
'username':'somnus',
'age':18
}
return render_template('if.html',user=user)
else:
return render_template('if.html')

if __name__ == '__main__':
app.run(debug=True)

for循环遍历列表和字典

1.字典的遍历,语法和python一样,可以使用items(),keys(),values(),iteritems(),iterkeys(),itervalues()

1
2
3
{% for k,v in user.items() %}
<p>{{ k }}:{{ v }}</p>
{% endfor %}

2.例子

for.html

1
2
3
{% for k,v in user.items() %}
<p>{{ k }}:{{ v }}</p>
{% endfor %}

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
user = {
'username':'somnus',
'age':18
}
return render_template('for.html',user=user)

执行结果:

3.列表的遍历:语法和python一样

1
2
3
{% for list in lists %}
<p>{{ website }}</p>
{% endfor %}

过滤器

1.介绍和语法:

(1)介绍:过滤器可以处理变量,把原始的变量经过处理后再展示出来

(2)语法:

1
{{ avatar|default('xxx') }}

2.default过滤器:如果当前变量不存在,这时候可以指定默认值

3.length过滤器:求列表或者字符串或者字典或者元组的长度

继承和block

1.继承的作用和语法:

(1)作用:可以把一些公共的代码放在父模板中,避免每个模板写同样的代码

(2)语法:

1
{% extends 'base.html' %}

2.block实现:

(1)作用:可以让子模板实现自己的一些需求,父模板需要提前定义好

(2)注意点:子模板中的代码,必须放在block块中

3.例子

模板base.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是一个模板
{% block main %}
{% endblock %}
</body>
</html>

继承block.html

1
2
3
4
{% extends 'base.html' %}
{% block main %}
这是一个子模板
{% endblock %}

url链接

使用url_for(视图函数名称)可以反转成url

加载静态文件

1.语法:

1
url_for('static',filename='路径')

2.静态文件,flask会从static文件夹开始寻找,所以不用再写static这个路径

3.可以加载css文件,可以加载js文件,还有image文件

Mysql-python中间件安装

https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysql-python

flask-sqlalchemy安装与使用

1.安装

1
pip install flask-sqlalchemy

2.使用

(1)使用flask_sqlalchemy中的SQLAlchemy进行初始化:

1
2
3
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)

(2)设置配置信息:在config.py文件中添加以下配置信息:

1
2
3
4
5
6
7
8
9
10
11
# dialect+driver://username:password@host:port/database
DIALECT = 'mysql'
DRIVER = 'mysqldb'
USERNAME = 'root'
PASSWORD = 'root'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'db_demo1'

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = False

(3)在主app文件中,添加配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config

app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)

db.create_all()

@app.route('/')
def index():
return ''

if __name__ == '__main__':
app.run(debug=True)

(4)测试有没有问题报错,如无,则成功连接

使用Flask-SQLAlchemy创建模型与表的映射

1.模型需要继承自db.Model,然后需要映射到表中的属性,必须写成’db.Column’的数据类型

2.数据类型:db.Integer代表的是整型,db.String代表的是varchar,需要指定最长的长度,db.Text代表的是text

3.其他参数:primary_key代表的是将这个字段设置为主键,autoincrement代表的是这个主键为自增长的,nullable代表的是这个字段是否可以为空,可以将这个值设置为False,在数据库中,这个值就不能为空了

4.最后需要调用db.create_all来将模型真正创建到数据库中

例子:

config.py

1
2
3
4
5
6
7
8
9
10
DIALECT = 'mysql'
DRIVER = 'mysqldb'
USERNAME = 'root'
PASSWORD = 'root'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'db_demo2'

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = False

创建table执行的sql语句:

1
2
3
4
5
create table article(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
)

db_demo2.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config

app = Flask(__name__)
app.config.from_object(config)

db = SQLAlchemy(app)

class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),nullable=False)
content = db.Column(db.Text,nullable=False)

db.create_all()

@app.route('/')
def index():
return 'index'

if __name__ == '__main__':
app.run(debug=True)

Flask-SQLAlchemy数据的增,删,改,查

1.增:

1
2
3
article1 = Article(title='aaa',content='bbb')
db.session.add(article1)
db.session.commit()

2.查:

1
2
3
article1 = Article.query.filter(Article.title == 'aaa').first()
print 'title:%s' % article1.title
print 'content:%s' % article1.content

3.改:

1
2
3
4
5
6
# 先把你要更改的数据查找出来
article1 = Article.query.filter(Article.title == 'aaa').first()
# 把这条数据进行修改
article1.title = 'new title'
# 做事务的提交
db.session.commit()

4.删:

1
2
3
4
5
6
# 把需要删除的数据查找出来
article1 = Article.query.filter(Article.content == 'bbb').first()
# 把这条数据删除掉
db.session.delete(article1)
# 做事务的提交
db.session.commit()

flask中的session工作机制

1.flask中的session机制是:把敏感数据经过加密后放入session中,然后再把session存放到cookie中,下次请求的时候,再把浏览器发送过来的cookie中读取session,然后再从session中读取敏感数据,并进行解密,获取最终的用户数据

2.flask的这种session机制,可以节省服务器的开销,因为把所有的信息都存储到了客户端(浏览器)

3.安全是相对的,把session放到cookie中,经过加密,也是比较安全的

flask操作session

1.session的操作方式:

(1)使用session需要从flask中导入session,以后和session相关的操作都是通过这个变量来的

(2)使用session需要设置SECRET_KEY,作为加密用的,并且这个SECRET_KEY,如果每次服务器启动后都变化的话,那么之前的session就不能再通过当前这个SECRET_KEY就不能再进行解密了

(3)操作session的时候,跟操作字典是一样的

(4)添加session:session[‘username’]=’admin’

(5)删除:session.pop(‘username’)

(6)清除所有session:session.clear()

(7)获取session:session.get(‘username’)

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from flask import Flask,session
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) #设置随机24位字符串作为加密的盐

@app.route('/')
def index():
session['username'] = 'admin'
return 'hello'

@app.route('/get/')
def get():
return session.get('username')

@app.route('/delete/')
def delete():
print session.get('username')
session.pop('username')
print session.get('username')
return 'success'

2.设置session过期时间

(1)如果没有指定session的过期时间,那么默认浏览器关闭后就自动结束

(2)如果设置了session的permanent属性为True,那么过期时间是31天

(3)可以通过给app.config设置PERMANENT_SESSION_LIFETIME来更改过期时间,这个值的数据类型是datetime.timedelay类型

Flask实现GET和POST请求获取参数

1.get请求是通过flask.request.args来获取

2.post请求是通过flask.request.form来获取

3.post请求在模板中要注意几点:

(1)input标签中,要写name来标识这个value的key,方便后台获取

(2)在写form表单的时候,要指定method=’post’,并且要指定action=’/login/‘

实例:

实现页面跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
return render_template('get_post_demo.html')

@app.route('/search/')
def search():
return 'search'

@app.route('/login/')
def login():
return 'login'

html代码:

1
<a href="{{ url_for('search',q='hello') }}">跳转到搜索页面</a>

获取GET请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask,render_template,request

app = Flask(__name__)

@app.route('/')
def index():
return render_template('get_post_demo.html')

@app.route('/search/')
def search():
q = request.args.get('q')
return 'get:%s'%q

@app.route('/login/')
def login():
return 'login'

获取POST请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from flask import Flask,render_template,request

app = Flask(__name__)

@app.route('/')
def index():
return render_template('get_post_demo.html')

@app.route('/search/')
def search():
q = request.args.get('q')
return 'get:%s'%q

@app.route('/login/',methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
return 'username:%s password:%s'%(username,password)

html代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form action="{{ url_for('login') }}" method="post">
<table>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" placeholder="请输入用户名" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="text" placeholder="请输入密码" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登录"></td>
</tr>
</tbody>
</table>
</form>

保存全局变量的g属性

g:global

1.g对象是专门用来保存用户的数据

2.g对象在一次请求中的所有的代码的地方,都是可以使用的

钩子函数(hook)

1.before_request:在请求之前执行的,即在视图函数执行之前执行的,这个函数只是一个装饰器,他可以把需要设置为钩子函数的代码放到视图函数执行之前来执行

示例代码:

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
#encoding: utf-8

from flask import Flask,render_template,request,session,g,redirect,url_for
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)

@app.route('/')
def index():
return render_template('get_post_demo.html')

@app.route('/login/',methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
if username == 'admin' and password == '123456':
session['username'] = username
return u'登录成功'
else:
return u'用户名或密码错误'

@app.route('/edit/')
def edit():
if hasattr(g,'username'):
return u'修改成功'
else:
return redirect(url_for('login'))

@app.before_request
def before_request():
if session.get('username'):
g.username = session.get('username')

if __name__ == '__main__':
app.run(debug=True)

2.context_processor:

(1)上下文处理器应该返回一个字典,字典中的key会被模板中当成变量来渲染

(2)上下文处理器中返回的字典,在所有页面中都是可用的

示例代码:

1
2
3
4
5
@app.context_processor
def my_context_processor():
username = session.get('username')
if username:
return {'username':username}

视频学习地址:flask视频学习