flask框架之初识

一.什么是flask?

1.和django一样都是基于python开发的web框架

2.和django一样是同步的框架

3.依赖jinja2模板和Werkzeug WSGI服务的一个微型框架

 

二.安装flask

pip3 install flask

 

三.werkzeug简介

Werkzeug是一个基于WSGI的工具包,可以作为一个Web框架的底层库,它封装好了很多Web框架的东西,比如Request,Response

 

四.flask快速使用

from flask import Flask
# 实例化生成一个FLask对象
app = Flask(__name__)

# 将'/'和视图函数index绑定,并添加到路由中
@app.route('/')
def index():
    return 'ok'

if __name__ == '__main__':
    # run()本质是调用了run_simple()
    app.run()

 

五.flask基本使用之四剑客

flask可以直接返回字符串,也可以返回html页面,也可以重定向到其他页面,也可以返回json数据

from flask import Flask, render_template, redirect, jsonify
app = Flask(__name__)

@app.route('/')
def index():
    # 1.直接返回字符串
    # return 'ok'

    # 2.返回html页面,可以使用模板语法
    # dic = {'age': 18}
    # return render_template("index.html", name='sxc', dic=dic)

    # 3.重定向页面
    # return redirect('/login')

    # 4.返回json数据
    # info = [{'name': 'sxc'}, {'name': 'zzj'}]
    # return jsonify(info)

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

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

 

六.flask配置文件的四种方式

# flask的配置文件
from flask import Flask
app = Flask(__name__)

# 第一种配置方式,只能配置两种
# app.debug = True
# app.secret_key = '123'

# 第二种配置,以字典的形式
# app.config['DEBUG'] = True

# 第三种,以文件的形式
# app.config.from_pyfile('settings.py')

# 第四种,以类的方式(推荐)
app.config.from_object('settings.ProductionConfig')


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

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

具体的配置文件

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
    {
        'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
        'TESTING':                              False,                          是否开启测试模式
        'PROPAGATE_EXCEPTIONS':                 None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
        'SECRET_KEY':                           None,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
        'USE_X_SENDFILE':                       False,
        'LOGGER_NAME':                          None,
        'LOGGER_HANDLER_POLICY':               'always',
        'SERVER_NAME':                          None,
        'APPLICATION_ROOT':                     None,
        '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,
        'MAX_CONTENT_LENGTH':                   None,
        'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS':              False,
        'TRAP_HTTP_EXCEPTIONS':                 False,
        'EXPLAIN_TEMPLATE_LOADING':             False,
        'PREFERRED_URL_SCHEME':                 'http',
        'JSON_AS_ASCII':                        True,
        'JSON_SORT_KEYS':                       True,
        'JSONIFY_PRETTYPRINT_REGULAR':          True,
        'JSONIFY_MIMETYPE':                     'application/json',
        'TEMPLATES_AUTO_RELOAD':                None,
    }

 

七.路由系统

装饰器的方式

@app.route('/index/<int:nid>', methods=['POST', 'GET'], endpoint='hhh')

通过源码分析得到的新方式

app.add_url_rule('/index/<string:nid>', methods=['GET', 'POST'], view_func=index, endpoint='hhh')

路由系统的本质

def decorator(f):
    endpoint = options.pop("endpoint", None)
    self.add_url_rule(rule, endpoint, f, **options)
    return f
'''
内部代码self.add_url_rule(rule, endpoint, f, **options)
这里的self指代的就是app,rule就是/index, f就是index函数
endpoint是为该路由取的别名,不传默认是函数名
view_func就是f就是index,
endpoint必须有值,当不传的情况下,默认使用函数名,如果不使用装饰器,并且view_func也不传,那么endpoint就会没有值,那么就会报错
'''

路由中的<string:nid>是它的有名分组,前面的是指定类型,后面的是传入的参数

 

CBV(源码分析)

# CBV的控制类
from flask import Flask, views
app = Flask(__name__)
app.debug = True

class IndexView(views.View):
    def dispatch_request(self):
        print('Index')
        return 'index'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'), endpoint='hhh')

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

# 内部源码
@classmethod
    def as_view(cls, name, *class_args, **class_kwargs):
        def view(*args, **kwargs):
            self = view.view_class(*class_args, **class_kwargs)
            return self.dispatch_request(*args, **kwargs)
        view.view_class = cls  # 将控制类赋值给view_class
        view.__name__ = name  # 将name赋值给__name__
        view.__doc__ = cls.__doc__
        view.__module__ = cls.__module__
        view.methods = cls.methods
        view.provide_automatic_options = cls.provide_automatic_options
        return view
'''
上面源码的view.__name__ = name十分重要,
因为endpoint必须有值,当不传的时候默认是函数的__name__,
如果这步不设置,那么所有控制类的endpoint就都是view了,这样会出错
所以必须提前设置view.__name__ = name,故而这个name我们必须传入,
当然我们传入name之后还是可以指定endpoint
'''

CBV的不同请求方式的不同执行函数

# 自定义的CBV代码
class IndexView(views.MethodView):
    # decorators = [,,,]  # 装饰器,可以有多个
    def get(self):
        return 'index get'
    def post(self):
        return 'index post'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'), endpoint='hhh')

# 源码,继承MethodView
class MethodView(with_metaclass(MethodViewType, View)):
    def dispatch_request(self, *args, **kwargs):
        meth = getattr(self, request.method.lower(), None)
        # 如果没传默认是get方法
        if meth is None and request.method == "HEAD":
            meth = getattr(self, "get", None)
        assert meth is not None, "Unimplemented method %r" % request.method
        # 传了就是对应的方法,即meth=get/post
        # 下面加括号调用之后就执行自定义函数对应的方法
        return meth(*args, **kwargs)

 

app.add_url_rule参数

from flask import Flask
app = Flask(__name__)
app.debug = True

# strict_slashes该参数是用来设置严格模式,当设置为False时/index和/index/都可以被识别
# redirect_to是路由跳转
@app.route('/index', strict_slashes=False, redirect_to='/login')
def index():
    return 'index'

@app.route('/login/<int:nid>')
def login(nid):
    print(nid)
    return 'login'


if __name__ == '__main__':
    app.run()
@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"]
#对URL最后的 / 符号是否严格要求
strict_slashes = None
    '''
        @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
    '''
#重定向到指定地址
redirect_to = None, 
    '''
        @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
    '''

#子域名访问
subdomain = None, 
    '''
    #C:\Windows\System32\drivers\etc\hosts
    127.0.0.1       www.liuqingzheng.com
    127.0.0.1       admin.liuqingzheng.com
    127.0.0.1       buy.liuqingzheng.com
    
    from flask import Flask, views, url_for
    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'liuqingzheng.com:5000'
    @app.route("/", subdomain="admin")
    def static_index():
        """Flask supports static subdomains
        This is available at static.your-domain.tld"""
        return "static.your-domain.tld"
    #可以传入任意的字符串,如传入的字符串为aa,显示为 aa.liuqingzheng.com
    @app.route("/dynamic", subdomain="<username>")
    def username_index(username):
        """Dynamic subdomains are also supported
        Try going to user1.your-domain.tld/dynamic"""
        return username + ".your-domain.tld"
    if __name__ == '__main__':
        app.run()
        
    访问:
    http://www.liuqingzheng.com:5000/dynamic
    http://admin.liuqingzheng.com:5000/dynamic
    http://buy.liuqingzheng.com:5000/dynamic
    '''

 

路由系统支持正则

'''
当我们需要使用路由匹配正则时
1.导入from werkzeug.routing import BaseConverter
2.写一个类继承BaseConverter,初始化实现__init__方法,实现to_python和to_url两个函数
3.app.url_map.converters['regex'] = RegexConverter添加到flask中
4.绑定的装饰器@app.route('/index/<regex("\d+"):nid>'),书写注册的正则
5.regex正则匹配出的结果交给to_python,进行一系列自定义操作后return出来
6.当我们做反向解析的时候,参数传给to_url,return才是我们需要拼接到路由上的

'''

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

app = Flask(__name__)

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

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

    def to_url(self, value):
        '''
        使用url_for反向生成url时,传递的参数经过该方法处理,返回的值用于生成url中的参数
        '''
        val = super().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=nid))
    return 'index ok'

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

 89

posted @ 2019-11-12 00:06  瓜落桥下塘  阅读(162)  评论(0编辑  收藏  举报