flask入门

Oct 21, 2018 09:54 · 1167 words · 6 minute read python

入门笔记。

2018-10-21 开始 > 2018-11-1结束

flask学习

安装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的目录下

flask手册

运行环境

. 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_templaterender_template_string两种。

模板的使用需要 导入render_templaterender_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 &#123;&#123;username&#125;&#125; and my password is &#123;&#123;password&#125;&#125;</h1>
<h1>my name is &#123;&#123;array.yang&#125;&#125; and my password is &#123;&#123;array['Yang1k']&#125;&#125;</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 &#123;&#123;username&#125;&#125;</h4>
<h4>my age is &#123;&#123;age&#125;&#125;</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>&#123;&#123;k&#125;&#125; is &#123;&#123;v&#125;&#125;</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 : &#123;&#123;x&#125;&#125;</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>&#123;&#123;book['name']&#125;&#125;</td>
<td>&#123;&#123;book['price']&#125;&#125;</td>
<td>&#123;&#123;book.number&#125;&#125;</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>


&#123;&#123;a|default('qweqwe')&#125;&#125;

</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>


数量:&#123;&#123;comment|length&#125;&#125;

{% for comment in comment%}
<li>&#123;&#123;comment.user&#125;&#125;</li>
<li>&#123;&#123;comment.pass&#125;&#125;</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):格式化字符串。比如:&#123;&#123; "%s" - "%s"|format('Hello?',"Foo!") &#125;&#125;将输出: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。

加载静态文件

  1. 语法 url_for('static',filename='路径')
  2. 静态文件 ,flask会自动从static文件夹开始寻找,所以不需要再写static这个路径
  3. 可以加载css文件,js文件,还有image图片
  4. 要把静态文件放在static目录下 直接在html中写就可以。

示例(加载图片) index.html

<img src="&#123;&#123; url_for('static',filename='7.jpg')&#125;&#125;" alt="">

1.py

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

Flask-SQLAlchemy的介绍与安装

  1. ORM: Object Relationship Mapping(模型关系映射)
  2. flask-sqlalchemy是一套ORM框架
  3. ORM的好处,可以让我们操作数据库跟操作对象一样简单,很方便。一个表就抽象成一个类,一条数据就抽象成该类的一个对象。
  4. 安装Flask-SQLAlchemypip 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里,但是不行。那就哪里用到了,就在哪里设置吧。

传参

  1. 获取get传参

    
    @app.route('/get/')
    def re_get():
    # 获取get参数
    a = request.args.get('id')
    return a
    
    
  2. 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对象在一次请求中的所有的代码的地方,都是可以使用的。

钩子函数

  1. before_request before_request:在请求之前执行的

这个函数只是一个装饰器,可以让代码在视图函数执行之前执行。

简单示例

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


  1. 上下文处理器

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>
&#123;&#123;username&#125;&#125;
</body>
</html>

在渲染模板的时候需要在渲染函数中设置username变量,才可以在index.html中显示出username,但是如果使用上下文处理器,他会自动注册username变量,使其在所有模板中均可使用。

这个可以用到判断是否有用户登录,如果用户登录的话,就将用户名赋值给username,这样所有的模板文件都可以使用username变量了。

tweet Share