Flask 1 框架基础

Flask 基础

5步快速搭建一个项目

flask是一个轻量级的web框架,只是用一个脚本就能搭建起一个项目

#1,导入模块
from flask import Flask,request

#2,实例化Flask类得到一个app对象
app=Flask(__name__)

#3,配置路由
@app.route('/')  
#4,处理请求的函数
def index():
    # 当前请求地址,当前请求携带过来的数据
    return 'hello world'
#5,启动项目
if __name__ == '__main__':
    app.run()
    # 请求来了,会执行 app(request),触发__call__方法
1, 路由写法(路径,支持的请求方式,别名)
@app.route('/login',methods=['GET','POST'],endpoint='l1')

2 返回格式:
	return '字符串' #直接返回字符串
	return render_template('index.html') #返回一个页面
	return redirect('/login') #重定向

3模板语言渲染
	-使用jinja2,和Django的dtl类似,但是比dtl强大

一 项目配置

方法1:直接在程序内修改

app.config['DEBUG'] = True
PS: 由于Config对象本质上是字典,所以还可以使用		app.config.update(...)

方法2:使用配置文件(这个方法和Django相似)

#新建py文件,内容为配置信息
settings.py
DEBUG = True

#引入配置文件
app.config.from_pyfile("python文件名称")

方法3:使用配置类

#新建py文件,内容为配置类
app.config.from_object('settings.TestingConfig')

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'


class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'


class DevelopmentConfig(Config):
    DEBUG = True


class TestingConfig(Config):
    TESTING = True

二 路由系统

#flask用装饰器的方式配置路由,一般传入3个参数,依次为路径,允许的方法,别名
@app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')

路由参数-路径

有名分组:

和Django类似,<student_id>匹配的值会以student_id为key的形式接受

@app.route('/student_list/<student_id>/')
def student_list(student_id):
    return '学生{}号的信息'.format(student_id)

路由参数-请求方法

methods=['GET'],允许什么方法就在列表里添加什么方法

路由参数-别名

endpint参数是写在注册路由的装饰器中的一个参数,学名叫端点,我们可以理解为函数的别名。如果不指定endpoint,默认就以函数名作为端点名。

Copy@app.route('/fbvtest/',methods=['GET','POST'],endpoint='fbv')  
def fbvtest():
    url_demo = url_for('fbv')
    return '利用视图函数别名翻转的url为:{}'.format(url_demo)

关键词:

  • 利用@app.route()endpoint='fbv'参数可以自由指定端点名,url_for可以根据指定的端点名进行翻转。

注册路由参数详解

常用的参数

@app.route和app.add_url_rule参数:
rule, URL规则
view_func, 视图函数名称
endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]

不常用的参数

(1) 对URL最后的 / 符号是否严格要求 strict_slashes = False

strict_slashes = False
    '''
        @app.route('/index', strict_slashes=False)
        #访问http://www.xx.com/index/ 或http://www.xx.com/index均可
        @app.route('/index', strict_slashes=True)
        #仅访问http://www.xx.com/index
    '''

(2) 重定向到指定地址redirect_to=“ ”

@app.route("/",redirect_to='/home/')
def index():

    return '根路径'

@app.route("/home/")
def admin_demo():

    return 'home路径'

(3) 为函数提供默认参数值

defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}

(4)子域名设置subdomain=“ ”

from flask import Flask,url_for

app = Flask(__name__)
app.debug = True
'''
先在hosts设置域名解析(就是在本机的hosts文件上编辑上域名对应ip的关系) 
域名解析会先解析本地如果没有再解析dns服务器
C:\Windows\System32\drivers\etc\hosts

127.0.0.1 mark.com
127.0.0.1 admin.mark.com

'''
app.config['SERVER_NAME'] = 'mark.com:5000' # 这个代表访问这个域名的时候要访问5000端口

@app.route("/")
def index():

    return '设置域名成功'

@app.route("/admin_demo/",subdomain='admin')
def admin_demo():

    return '设置子域名成功'

'''
在浏览器中访问主域名
mark.com:5000/

在浏览器中访问子域名
admin.mark.com:5000/admin_demo/

注意:后面跟的path路径部分正常写
'''

if __name__ == '__main__':
    app.run(host='127.0.0.1',port=5000) # 测试服务器不稳定,尽量手动制定ip和端口

装饰器注册路由源码浅析

(1) 首先写一个小视图函数

Copy#注册装饰器的原理
#1 v = app.route('/source_code_demo/',endpoint='source_code')
#2 v(source_code_demo)
@app.route('/source_code_demo/',endpoint='source_code')
def source_code_demo():

    return 'source_code_demo'

(2) 查看app.route()源码

    def route(self, rule, **options):
         def decorator(f):
                endpoint = options.pop('endpoint', None)
                self.add_url_rule(rule, endpoint, f, **options)
                return f
         return decorator

解析:

  • ,发现route()返回的是decorator函数地址,然后基于语法糖和装饰器的原理,decorator会加括号运行,像这样decorator(source_code_demo)
  • decorator函数中首先取出endpoint,然后运行self.add_url_rule(rule, endpoint, f, **options)
  • 所以 self.add_url_rule(rule, endpoint, f, **options)就是注册路由的核心

(3) 点进self.add_url_rule(rule, endpoint, f, **options)查看源码,

再点进_endpoint_from_view_func(view_func)查看源码

    
  @setupmethod
  def add_url_rule(self, rule, endpoint=None, view_func=None,
                     provide_automatic_options=None, **options):


  	   if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options['endpoint'] = endpoint
        methods = options.pop('methods', None)

        if methods is None:
            methods = getattr(view_func, 'methods', None) or ('GET',)
            

def _endpoint_from_view_func(view_func):

    assert view_func is not None, 'expected view func if endpoint ' \
                                  'is not provided.'
    return view_func.__name__

解析:

  • 由上述代码我们可以直到如果没有指定endpoint,我们调用了 _endpoint_from_view_func()
  • 观察_endpoint_from_view_func函数我们可以知道,返回了视图函数的名字给了endpoint赋值
  • methos没有指定会给methos赋默认值('GET',)

小结:

  1. self.add_url_rule(rule, endpoint, f, options)就是注册路由的核心
  2. 观察_endpoint_from_view_func函数我们可以知道,返回了视图函数的名字给了endpoint赋值
  3. methos没有指定会给methods赋默认值('GET',)

另一种注册路由的方式---app.add_url_rule()

通过看上一个小节写的源码,现在我们知道了app.route() 的核心就是self.add_url_rule(rule, endpoint, f, options)就是注册路由的核心。所以我们可以直接使用app.add_url_rule()的方式来注册路由。

实例:

def add_url_test():

    return '实现了add_url方式注册路由'
                 # url                       端点                 函数地址
app.add_url_rule('/add_url_test/',endpoint='add_demo',view_func=add_url_test)

转换器

可以对<student_id>要匹配的值进行限定,如:限定student_id必须为整数类型

@app.route('/student_list/<int:student_id>/')
def article_detail(student_id):
    return '学生{}号的信息'.format(student_id)

主要有这几种类型过滤:

  string: 默认的数据类型,接收没有任何斜杠"\ /"的字符串

  int: 整型

  float: 浮点型

  path: 和string类型相似,但是接受斜杠,如:可以接受参数/aa/bb/cc/多条放在一起

  uuid: 只接受uuid格式的字符串字符串

any: 可以指定多种路径,如下面的例子

@app.route('/<any(student,class):url_path>/<id>/')
def item(url_path, id):
    if url_path == 'student':
        return '学生{}详情'.format(id)
    else:
        return '班级{}详情'.format(id)

处理动态路由

自定义一个类,该通过继承werkzeug.routing 的BaseConverter类不光可以实现正则匹配,我们介绍一下以下两个方法:

  • 在该类中实现 to_python 方法:

    这个方法的返回值,将会传递给视图函数的形参。我们可以利用这个方法实现处理url中动态路由部分。

  • 在该类中实现 to_url 方法:

    翻转url的时候也就是使用url_for函数的时候,我们传入指定的动态路由部分,触发to_url方法,这个方法的返回值,会拼接在非动态路由上,从而实现生成符合要求的url格式。

Copyfrom flask import Flask,request,url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)
app.debug =True


class ListConverter(BaseConverter):
    regex = '.*'     # 这个regex代表都匹配的意思,可以根据自己的需求制定url规则
    def to_python(self, value):
        '''这个函数用于拿到了路由里的动态参数赋值给value,
          可以在to_python进行操作动态参数,
          返回操作完的的结果给视图函数的形参'''
        return value.split('+')

    def to_url(self, value):
        '''这个函数用于和url_for连用,
           url_for通过指定给动态参数(以关键字实参的形式)赋值给value
           我们可以根据我们的需求操作url_for传进来的参数,
           然后返回一个理想的动态路由内容拼接在url上'''
        return '+'.join(value)


app.url_map.converters['list'] = ListConverter

@app.route('/student_list/<list:students>/')
def student_list(students):
    print(url_for('student_list',students=['a','b'])) # 输出 /student_list/a+b/

    return '{}'.format(students)


if __name__ == '__main__':
    app.run()
posted @ 2020-03-27 05:12  Franciszw  阅读(155)  评论(0编辑  收藏  举报