Python_WEB框架之Flask

Posted 一只待宰的程序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python_WEB框架之Flask相关的知识,希望对你有一定的参考价值。

前言:

Django:1个重武器,包含了web开发中常用的功能、组件的框架;(ORM、Session、Form、Admin、分页、中间件、信号、缓存、ContenType....);

Tornado:2大特性就是异步非阻塞、原生支持WebSocket协议;

Flask:封装功能不及Django完善,性能不及Tornado,但是Flask的第三方开源组件比丰富;http://flask.pocoo.org/extensions/

Bottle:比较简单;

 

总结:

都不是我写的!!!不论优劣,不同的工具而已;

小型web应用设计的功能点不多使用Flask;

大型web应用设计的功能点比较多使用的组件也会比较多,使用Django(自带功能多不用去找插件);

如果追求性能可以考虑Tornado;

 

Flask的socket是基于Werkzeug 实现的,模板语言依赖jinja2模板,在使用Flask之前需要安装一下;

pip3 install flask           #安装flask
from werkzeug.wrappers import Request, Response  # Flask的socket使用werkzeug实现,所以要导入 werkzeug

@Request.application

def hellow(request):
    return Response(\'Hello World\')

if __name__ == \'__main__\':
    from werkzeug.serving import run_simple
    run_simple(\'localhost\',400,hellow)

 

Flask简单使用

from flask import Flask

app=Flask(__name__) #创建1个Flask实例

@app.route(\'/\')      #路由系统生成 视图对应url,1. decorator=app.route() 2. decorator(first_flask)
def first_flask():    #视图函数
    return \'Hello World\'  #response


if __name__ == \'__main__\':
    app.run()              #启动socket

一、配置文件

app=Flask(__name__,template_folder=\'templates\',static_url_path=\'/static/\',static_path=\'/zhanggen\')

模板路径: template_folder=\'templates\'

静态文件路径:static_url_path=\'/static/\'

静态文件引入别名:static_path=\'/zhanggen\'

设置为调试环境:app.debug=True (代码修改自动更新)

设置json编码格式 如果为False 就不使用ascii编码:app.config[\'JSON_AS_ASCII\']=False 

设置响应头信息Content-Type   app.config[\'JSONIFY_MIMETYPE\'] ="application/json;charset=utf-8"  (注意 ;charset=utf-8)

 

二、路由系统

 

1.动态路由(url传参)

@app.route(\'/user/<name>\')

from flask import Flask

app=Flask(__name__)

@app.route(\'/<name>\')  #设置url传参数 http://127.0.0.1:5000/zhanggen
def first_flask(name):  #视图必须有对应接收参数
    print(name)
    return \'Hello World\'  #response


if __name__ == \'__main__\':
    app.run()
接收字符串类型参数

@app.route(\'/post/<int:age>\')

#接收整型数字参数
app=Flask(__name__)
@app.route(\'/<int:age>/\')  #设置url传参数 http://127.0.0.1:5000/18/
def first_flask(age):  #视图必须有对应接收参数
    print(age)
    return \'Hello World\'  #response

if __name__ == \'__main__\':
    app.run()
接收整型数字参数

@app.route(\'/post/<float:salary>\')

#接收浮点型型数字参数
app=Flask(__name__)
@app.route(\'/<float:salary>/\')  #设置url传参数http://127.0.0.1:5000/2345555.8889/
def first_flask(salary):  #视图必须有对应接收参数
    print(salary)
    return \'Hello World\'  #response

if __name__ == \'__main__\':
    app.run()
接收浮点型数字参数

@app.route(\'/post/<path:path>\')

# 接收URL链接类型参数
app=Flask(__name__)
@app.route(\'/<path:url>/\')  #设置url传参数:http://127.0.0.1:5000/http://www.baiu.com/
def first_flask(url):  #视图必须有对应接收参数
    print(url)
    return \'Hello World\'  #response

if __name__ == \'__main__\':
    app.run()
接收URL链接类型参数

 

2、指定允许的请求方法

@app.route(\'/login\', methods=[\'GET\', \'POST\']) 

# 指定允许的请求方法
app=Flask(__name__)
@app.route(\'/<path:url>/\',methods=[\'get\']) #只允许get请求
def first_flask(url):
    print(url)
    return \'Hello World\'  #response

if __name__ == \'__main__\':
    app.run()
指定允许的请求方法

 

3、通过别名反向生成url

#反向生成url
from flask import Flask,url_for
app=Flask(__name__)
@app.route(\'/<path:url>\',endpoint=\'name1\')
def first_flask(url):
    print(url_for(\'name1\',url=url)) #如果设置了url参数,url_for(别名,加参数)
    return \'Hello World\'

if __name__ == \'__main__\':
    app.run()
url_for()反向生成url

 

4、通过app.add_url_rule()调用路由

#方式2通过app.add_url_rule()方法的方式调用路由
app=Flask(__name__)

def first_flask():
    return \'Hello World\' 

app.add_url_rule(rule=\'/index/\',endpoint=\'name1\',view_func=first_flask,methods=[\'GET\'])
#app.add_url_rule(rule=访问的url,endpoint=路由别名,view_func=视图名称,methods=[允许访问的方法])
if __name__ == \'__main__\':
    app.run()
app.add_url_rule()方法调用路由

 

5、扩展路由功能:正则匹配url

如果需要一些复杂的匹配规则可以自定义正则匹配url

    from flask import Flask, views, url_for
            from werkzeug.routing import BaseConverter

            app = Flask(import_name=__name__)


            class RegexConverter(BaseConverter):
                """
                自定义URL匹配正则表达式
                """
                def __init__(self, map, regex):
                    super(RegexConverter, self).__init__(map)
                    self.regex = regex

                def to_python(self, value):
                    """
                    路由匹配时,匹配成功后传递给视图函数中参数的值
                    :param value: 
                    :return: 
                    """
                    return int(value)

                def to_url(self, value):
                    """
                    使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
                    :param value: 
                    :return: 
                    """
                    val = super(RegexConverter, self).to_url(value)
                    return val

            # 添加到flask中
            app.url_map.converters[\'regex\'] = RegexConverter


            @app.route(\'/index/<regex("\\d+"):nid>\')
            def index(nid):
                print(url_for(\'index\', nid=\'888\'))
                return \'Index\'


            if __name__ == \'__main__\':
                app.run()
自定义正则表达式匹配路由

 

四、视图

 

1、给Flask视图函数加装饰器

注意如果要给视图函数加装饰器增加新功能,一点要加在路由装饰器下面,才会被路由装饰器装饰,才能生生成url关系;

#给Flask视图加装饰器
#1、定义1个装饰器

def auth(func):
    print(\'我在上面\')
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner


app=Flask(__name__)

@app.route(\'/\',methods=[\'GET\'])
@auth #注意如果要给视图函数加装饰器,一点要加在路由装饰器下面,才会被路由装饰器装饰
def first_flask():
    print(\'ffff\')
    return \'Hello World\'

if __name__ == \'__main__\':
    app.run()
View Code

 

2、request和response

 a.请求相关信息

request.method: 获取请求方法

request.json

request.json.get("json_key"):获取json数据 **较常用      

request.argsget(\'name\') :获取get请求参数   

request.form.get(\'name\') :获取POST请求参数

request.form.getlist(\'name_list\'):获取POST请求参数列表(多个)

request.values.get(\'age\') :获取GET和POST请求携带的所有参数(GET/POST通用)

request.cookies.get(\'name\'):获取cookies信息

request.headers.get(\'Host\'):获取请求头相关信息

request.path:获取用户访问的url地址,例如(/,/login/,/ index/);

request.full_path:获取用户访问的完整url地址+参数 例如(/login/?age=18)

request.script_root: 抱歉,暂未理解其含义;

request.url:获取访问url地址,例如http://127.0.0.1:5000/?age=18;

request.base_url:获取访问url地址,例如 http://127.0.0.1:5000/;

request.url_root

request.host_url

request.host:获取主机地址

 

request.files:获取用户上传的文件

obj = request.files[\'the_file_name\']

obj.save(\'/var/www/uploads/\' + secure_filename(f.filename))  直接保存

 

 b、响应相关信息

return "字符串" :响应字符串

return render_template(\'html模板路径\',**{}):响应模板

return redirect(\'/index.html\'):跳转页面

 

响应json数据

方式1: return jsonify(user_list) 

app.config[\'JSON_AS_ASCII\']=False  #指定json编码格式 如果为False 就不使用ascii编码,
app.config[\'JSONIFY_MIMETYPE\'] ="application/json;charset=utf-8" #指定浏览器渲染的文件类型,和解码格式;
配置

方式2:

return Response(data,mimetype="application/json;charset=utf-8",)

 

 

如果需要设置响应头就需要借助make_response()方法

 

from flask import Flask,request,make_response  

 

response = make_response(render_template(\'index.html\'))

response是flask.wrappers.Response类型

response.delete_cookie(\'key\')

response.set_cookie(\'key\', \'value\')

response.headers[\'X-Something\'] = \'A value\'

return respons

 

3 、Flask之CBV视图

#CBV视图
from flask import Flask,url_for,views
#-----------------------------------------------------
app=Flask(__name__)               #装饰器

def auth(func):
    print(\'我在上面\')
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner
#--------------------------------------------------------
class IndexView(views.MethodView):  #CBV视图
    methods=[\'GET\']                #允许的http请求方法(改CBV只允许GET方法)
    decorators = [auth,]            #每次请求过来都加auth装饰器

    def get(self):
        return \'Index.GET\'
    def post(self):
        return \'Index.POST\'

app.add_url_rule(\'/index/\',view_func=IndexView.as_view(name=\'name1\')) #(name=\'name1\'反向生成url别名


if __name__ == \'__main__\':
    app.run()
CBV视图

 

五、模板语言

Flask使用的是Jinja2模板,所以其语法和Django无差别(Django的模板语言参考Jinja2)

 

1.引用静态文件

方式1:别名引入

<link rel="stylesheet" href="/zhanggen/commons.css">

方式2:url_for()方法引入

<link rel="stylesheet" href="{{  url_for(\'static\',filename=\'commons.css\')  }}">

 

2.模板语言引用上下文对象

变量

<h1>{{user_list}}</h1> <!--变量 -->
View Code

 

Flask的Jinjia2可以通过Context 把视图中的函数传递把模板语言中执行,这就是Django中的simple_tag和simple_fifter;

simple_tag(只能传2个参数,支持for、if)

@app.template_global()   #simple_tag
def foo(arg):
    return \'<input type="text">\'
视图
<h1>{{foo(1)|safe}}</h1>                   <!--Flask的模板语言支持simple_tag-->
模板语言

 

simple_fifter(对参数个数无限制,不支持for、if)

@app.template_filter()  #simple_fifter
def foo1(arg1,arg2,arg3):
    return arg1+arg2+arg3
视图
<h1> {{ \'alex\'|foo1(\'s \',\'b\',) }}  </h1>     <!-- simple_fifter -->
模板语言

 

3.wtform(flask表单验证插件)

3.0.简介

 wtformWTForms是一个支持多个web框架的form组件,主要对用户请求数据 进行表单验证。

 

3.1. 安装

pip install wtforms  #安装wtfroms插件

 

3.2.简单使用

wtforms和Django自带的form验证插件功能相同,使用起来大同小异;

 

用户登录页面验证

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms.fields import core
from wtforms.fields import html5
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets


app=Flask(__name__,template_folder=\'templates\') #知道模板文件
app.debug=True

#登录验证实例
class LoginForm(Form):

    #不同的字段 内部包含正则表达式 html5.EmailField | html5.DateTimeField...
    name=simple.StringField(
        label=\'用户名\',
        validators=[                                #验证规则和错误提示信息
            validators.DataRequired(message=\'用户名不能为空.\'),
            validators.Length(min=6, max=18, message=\'用户名长度必须大于%(min)d且小于%(max)d\')
        ],
        widget=widgets.TextInput(),                 #前端页面显示的插件.TextArea
        render_kw={\'class\': \'form-control\'}      #设置form标签的class信息

        )

    # 不同的字段 内部包含正则表达式  html5.EmailField | html5.DateTimeField...
    pwd = simple.PasswordField(
        label=\'密码\',
        validators=[
            validators.DataRequired(message=\'密码不能为空.\'),
            validators.Length(min=8, message=\'用户名长度必须大于%(min)d\'),
            #自定义验证规则
            validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}",
                              message=\'密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符\')

        ],
        widget=widgets.PasswordInput(),
        render_kw={\'class\': \'form-control\'}
    )



@app.route(\'/login/\', methods=[\'GET\', \'POST\'])
def login():
    if request.method == \'GET\':
        form = LoginForm()     #实例化 form验证类
        return render_template(\'login.html\', form=form)
    else:
        form = LoginForm(formdata=request.form)
        if form.validate(): #判断是否验证成功?
            print(\'用户提交数据通过格式验证,提交的值为:\', form.data)
        else:
            print(form.errors)
        return render_template(\'login.html\', form=form)

if __name__ == \'__main__\':
    app.run()
app01.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登录</h1>
<form method="post" novalidate>
    <!--<input type="text" name="name">-->
    <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>

    <!--<input type="password" name="pwd">-->
    <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
    <input type="submit" value="提交">
</form>
</body>
</html>

login.html
login.html

 

用户注册页面验证 

#用户注册
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms.fields import core
from wtforms.fields import html5
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets

app = Flask(__name__, template_folder=\'templates\')
app.debug = True



class RegisterForm(Form):
    name = simple.StringField(
        label=\'用户名\',
        validators=[
            validators.DataRequired()
        ],
        widget=widgets.TextInput(),
        render_kw={\'class\': \'form-control\'},
        default=\'张根\'                                             #设置input标签中默认值
    )

    pwd = simple.PasswordField(
        label=\'密码\',
        validators=[
            validators.DataRequired(message=\'密码不能为空.\')
        ],
        widget=widgets.PasswordInput(),
        render_kw={\'class\': \'form-control\'}
    )

    pwd_confirm = simple.PasswordField(                                #第二次输入密码
        label=\'重复密码\',
        validators=[
            validators.DataRequired(message=\'重复密码不能为空.\'),
            validators.EqualTo(\'pwd\', message="两次密码输入不一致")  #验证2次输入的密码是否一致?
        ],
        widget=widgets.PasswordInput(),
        render_kw={\'class\': \'form-control\'}
    )

    email = html5.EmailField(
        label=\'邮箱\',
        validators=[
            validators.DataRequired(message=\'邮箱不能为空.\'),
            validators.Email(message=\'邮箱格式错误\')
        ],
        widget=widgets.TextInput(input_type=\'emailFlask之模板之宏继承包含

Python之flask框架

Python之Flask框架一

Python之Flask框架一

Flask框架从入门到精通之模板宏(十九)

Flask框架从入门到精通之模板宏(十九)