python之路_flask框架_flask框架基础(1)

一、路由系统

  在入门中我们提到了flask框架中的两种路由形式,现在将以第一种形式,详细介绍其中的各个参数。具体参数如下:

#@app.route和app.add_url_rule参数:
rule                                         #URL规则
view_func                                    #视图函数名称
defaults = None                              #默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数
endpoint = None                              #名称,用于反向生成URL,即: url_for('名称')
methods = None                               #允许的请求方式,如:["GET", "POST"]
strict_slashes = None                        #对URL最后的 / 符号是否严格要求,
'''
如:
1、@app.route('/index', strict_slashes=False)访问:http: // www.xx.com / index / 
或http: // www.xx.com / index均可
2、@app.route('/index', strict_slashes=True)仅访问http: // www.xx.com / index
'''
redirect_to = None                          #重定向到指定地址
subdomain = None                            #子域名访问

1、带参数路径

  常见五种路由如下,其中带参数的路由,需要指定参数的类型,不指定类型时即为默认的字符串类型

@app.route('/user/<username>')
@app.route('/post/<int:post_id>')
@app.route('/post/<float:post_id>')
@app.route('/post/<path:path>')
@app.route('/login', methods=['GET', 'POST'])

   如下实例,视图函数中的参数可以通过如下两种方式获得:一种就是我们说的如下形式的带参数的路径,另一种就是我们通过在路由中的default参数进行传值,这两种的形式的参数都可以在视图函数中进行获得和使用。

from flask import Flask
app=Flask(__name__)

@app.route("/index/<int:nid>",defaults={"cid":123})
def index(nid,cid):
    print(nid,cid)
    return "from index"

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

 2、url反向解析

  在路由中的endpoint参数即为url的url别名,通过url别名,利用url_for()可以获得反向解析的路径,如下为但参数的反向解析实例,不带参数的路径在反向解析的时候不用给其参数即可。

from flask import Flask,url_for
app=Flask(__name__)
@app.route("/index/<int:nid>",endpoint="xxx")
def index(nid):
    v=url_for("xxx",nid=nid)                           #带参数形式的反向解析
    print(v)
    return "ok"

3、重定向参数

  在我们的路由中,我们redirect_to这样一个参数,通过给其配置一个路径,则在请求当前路由的时候,不再访问当前路由所装饰的视图函数,而是访问重定向参数设置对应的路由下视图函数,实例如下:

from flask import Flask
app=Flask(__name__)
@app.route("/old",redirect_to="/new")                 #当访问/old路径时,会重定向到访问/new对应的视图
def old():
    return "old"

@app.route("/new")
def new():
    return "new"

4、子域名访问

(1)静态域名

  在路由中,有这样的subdomain参数,通过它可以定义我们子域名访问限制,具体实例如下:

from flask import Flask
app=Flask(__name__)
app.config['SERVER_NAME'] = 'bjg.com:5000'   #必须有这样的设置
@app.route("/index",subdomain="admin")
def index():
    return "index"

  上例的的解释为:我们想要访问index视图函数,必须要通过admin.bjg.com:5000/index这个路径进行访问才可以访问到,即subdomain参数数限制了我们访问的域名。为了让我的上例测试成功,我们必须对admin.bjg.com域名进行解析,DNS解析一般会先从我们电脑上的文件中进行解析,如果解析不成功就会到公网上解析。为了测试,我们只需要在我们的电脑上进行上述域名的ip对应设置,让测试在电脑上完成。具体步骤如下:

1、找到路径C:WindowsSystem32driversetc
2、在此路径的hosts文件中设置:
        127.0.01         admin.bjg.com

(2)动态域名

  如上设置,我们会把域名限制死,不会很灵活,通过如下的参数的形式,只要能解析成功的域名我们都可以访问,如下:

from flask import Flask
app=Flask(__name__)
app.config['SERVER_NAME'] = 'bjg.com:5000'  #必须有这样的设置
@app.route("/index",subdomain='<xxx>')
def index(xxx):
    return "%s.bjg.com" %xxx

'''
假如有如下形式的域名解析关系,均可以成功访问index视图:
sss.bjg.com     127.0.0.1
yyy.bjg.com     127.0.0.1
zzz.bjg.com     127.0.0.1

访问形式:
sss.bjg.com :5000/index
yyy.bjg.com :5000/index
zzz.bjg.com :5000/index
'''

 5、自定义正则路由匹配

  具体实现请参考如下实例:

from flask import Flask,url_for

app = Flask(__name__)

# 定义转换的类
from werkzeug.routing import BaseConverter
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

# 添加到converts中
app.url_map.converters['xxx'] = RegexConverter

# 进行使用
@app.route('/index/<xxx("d+"):nid>',endpoint='xx')
def index(nid):
    url_for('xx',nid=123)
    return "Index"

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

二、视图函数

1、FBV形式

from flask import Flask,url_for

app=Flask(__name__)
# 方式二:
@app.route("/index/")
def index():
    return "from index"


#方式二:
def demon():
    return "from demon"
app.add_url_rule("/demon",demon)

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

2、CBV形式

  如下实例,此种视图形式只能使用add_url_rule的形式匹配视图。

from flask import Flask,views,url_for

app=Flask(__name__)
def auth(func):
    def inner(*args,**kwargs):
        print("before")
        result=func(*args,**kwargs)
        print("after")
        return result
    return inner

class IndexView(views.MethodView):                                   #必须继承views.MethodView
    methods = ["POST"]                                               #用于指定可以请求的方法,否则请求无法执行post视图
    decorators = [auth,]                                             #用于给视图加装饰器,通过列表加多个
    def get(self):
        url_for("xxx")
        return "GET"

    def post(self):
        return "POST"

app.add_url_rule('/index',view_func=IndexView.as_view(name="xxx"))   #name='xxx'为设置的url别名


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

三、请求与响应

1、请求request

# 请求相关信息
        # request.method
        # request.args
        # request.form
        # request.values
        # request.cookies
        # request.headers
        # request.path
        # request.full_path
        # request.script_root
        # request.url
        # request.base_url
        # 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))

  部分实例如下:

from flask import Flask,request,render_template,jsonify
from urllib.parse import urlencode
app=Flask(__name__)

@app.route('/index',endpoint='xxx',methods=["POST","GET"])
def index():
    if request.method=="POST":
        get_args=request.args
        print(get_args)                 #获得url中参数,如ImmutableMultiDict([('id', '1')])
        get_dict=get_args.to_dict()
        print(get_dict)                 #将其转为字典:{'id': '1'}
        get_dict["xxx"]=18
        url=urlencode(get_dict)
        print(url)                      #结果id=1&xxx=18


        print(request.query_string)     #结果:b'id=1'

        get_form = request.form
        print(get_form)                 #获得form表单中数据,如ImmutableMultiDict([('user', '321'), ('pswd', '321')])
        get_values = request.values
        print(get_values)               #获得即包含url数据又包含form表单中数据
        return jsonify(name="alex",age=18)  #返回json数据形式

    return render_template("index.html")

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

2、相应response

 # 响应相关信息
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')

        # 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 response

四、模板语言

  Flask使用的是Jinja2模板,所以其语法和Django无差别。具体使用见如下实例:

from flask import Flask,render_template,Markup
app=Flask(__name__)

#如下方式装饰的方法可以在全局的模板中使用

@app.template_global
def sb(a,b):
    return a+b

@app.template_filter
def db(a,b,c):
    return a+b+c


def test(a,b):
    return a+b

@app.route('/index')
def index():
    v1=1111
    v2=[11,22,33]
    v3={"a":1,"b":2}

    v4='<input type="text">'
    v5=Markup('<input type="text">')  #Markup等价django的mark_safe
    
    return render_template("index.html",v1=v1,v2=v2,v3=v3,v4=v4,v5=v5,test=test)

if __name__ == '__main__':
    app.run()
视图
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Title</title>


</head>
<body>
<!--对象-->
<h1>{{v1}}</h1>

<!--列表循环-->
{% for i in v2 %}
<h2>{{i}}</h2>
{% endfor %}
<!--列表索引-->
<h2>{{v2.0}} {{v2.1}} {{v2.2}}</h2>
<!--字典循环-->
 <ul>
    {% for k,v in v3.items() %}
    <li>{{k}}  {{v}}</li>
    {% endfor %}
 </ul>
<!--字典索引-->
<h2>{{v3.a}}</h2>
<h2>{{v3.get("a")}}</h2>
<!--标签-->
<p>{{v4| safe}}</p>
<p>{{v5}}</p>
<!--函数-->
<h1>{{test(23,10)}}</h1>

<!--全局方法@app.template_global-->
<p>{{sb(1,2)}}</p>
<!--全局方法@app.template_filter-->
<p> {{ 1|db(2,3)}}</p>

</body>
</html>
模板文件

五、session

  具体session的设置见如下实例:

from flask import Flask,session

app = Flask(__name__)
app.secret_key ='sdfsdfsdf'  #设置session需要设置密钥
app.config['SESSION_COOKIE_NAME'] = 'session_lvning'  #设置session相关参数
"""
session相关参数:

'SESSION_COOKIE_NAME':                  'session',
'SESSION_COOKIE_DOMAIN':                None,
'SESSION_COOKIE_PATH':                  None,
'SESSION_COOKIE_HTTPONLY':              True,
'SESSION_COOKIE_SECURE':                False,
'SESSION_REFRESH_EACH_REQUEST':         True,
'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)
"""

@app.route('/index',endpoint='xx')
def index():
    # session本质上操作的是字典,假设session保存在数据库

    session['xx2'] = 123
    session['xx3'] = 123
    del session['xx2']
    return "xxx"

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

六、闪现(flash)

  是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。具体设置和使用实例说明如下:

from flask import Flask,flash,get_flashed_messages,redirect,url_for

app=Flask(__name__)
app.secret_key="adfsldgja"                     #flash基于session所以需要设置secret_key

app.route('/user',endpoint="xxx")
def user():
    msg=get_flashed_messages()                 #取出数据后删除
    print(msg)
    return "ok"

@app.route('/add')
def add():
    flash("添加成功")                           #存入数据
    return redirect('/user')

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

七、扩展

  有如下实例扩展,与django的中间件相似,可以用来处理例如登录验证:

from flask import Flask

app=Flask(__name__)


@app.before_request #无返回值
def request1():
    print("from request1")

@app.after_request  #有返回值
def response1(response):
    print("from response1")
    return response


@app.before_request
def request2():
    print("from request2")


@app.after_request
def response2(response):
    print("from response2")
    return response


@app.route("/")
def user():
    print("main")
    return "ok"


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


'''
请求/路径打印结果为:
from request1
from request2
main
from response2
from response1
'''
原文地址:https://www.cnblogs.com/seven-007/p/8370850.html