初识Flask

92 阅读4分钟

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

flask简介

flask是一个基于python开发并依赖jinja2米板和Werkzug WSGI服务的一个微型框架。

Werkzug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架。

开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

wsgiref

wsgiref模块就是python基于wsgi协议开发的服务模块

flask安装

pip install flask

werkzeug简介

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等

from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
    return Response('Hello World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, hello)

flask快速使用

from flask import Flask,request


app=Flask(__name__)

@app.route('/')   # 装饰器加括号和不加括号的区别
def index():
    # 当前请求地址,当前请求携带过来的数据
    print(request.path)
    return 'hello world'

@app.route('/hello')
def hello():

    print(request.path)
    return 'hello hellohello'
if __name__ == '__main__':
    app.run()
    # 请求来了,会执行 app(request),会触发谁?触发__call__方法

小案例---登陆、显示用户信息

main.py

from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True
app.secret_key = 'sdfsdfsdfsdf'

USERS = {
    1:{'name':'张三','age':18,'gender':'男','text':"道路千万条"},
    2:{'name':'李四','age':28,'gender':'男','text':"安全第一条"},
    3:{'name':'王五','age':18,'gender':'女','text':"行车不规范"},
}

@app.route('/detail/<int:nid>',methods=['GET'])
def detail(nid):
    user = session.get('user_info')
    if not user:
        return redirect('/login')

    info = USERS.get(nid)
    return render_template('detail.html',info=info)


@app.route('/index',methods=['GET'])
def index():
    user = session.get('user_info')
    if not user:
        # return redirect('/login')
        url = url_for('l1')
        return redirect(url)
    return render_template('index.html',user_dict=USERS)


@app.route('/login',methods=['GET','POST'],endpoint='l1')
def login():
    if request.method == "GET":
        return render_template('login.html')
    else:
        # request.query_string
        user = request.form.get('user')
        pwd = request.form.get('pwd')
        if user == 'cxw' and pwd == '123':
            session['user_info'] = user
            return redirect('http://www.baidu.com')
        return render_template('login.html',error='用户名或密码错误')

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

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户登录</h1>
    <form method="post">
        <input type="text" name="user">
        <input type="text" name="pwd">
        <input type="submit" value="登录">{{error}}
    </form>
</body>
</html>

总结

1 三板斧:
	-return 字符串
	-return render_template('index.html')
	-return redirect('/login')
2 路由写法(路径,支持的请求方式,别名)
@app.route('/login',methods=['GET','POST'],endpoint='l1')
3 模板语言渲染
	-同dtl,但是比dtl强大,支持加括号执行,字典支持中括号取值和get取值
4 分组(django中的有名分组)
    @app.route('/detail/<int:nid>',methods=['GET'])
    def detail(nid):
5 反向解析
	-url_for('别名')
    
6 获取前端传递过来的数据
	# get 请求
		request.query_string
  	# post请求
      user = request.form.get('user')
      pwd = request.form.get('pwd')

flask修改配置文件的方式

方式一

直接在项目运行文件中配置

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

方式二

通过py文件配置

app.config.from_pyfile("python文件名称")
如:
settings.py
DEBUG = True

方式三

通过配置不同的类实现通过不同的配置启动项目

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

路由系统

基本使用

@app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')
----------url, 支持的请求方式, 别名(默认就是函数名)

转换器

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

路由的本质

flask路由是基于装饰器,但本质是基于add_url_rule:
add_url_rule(
        self,
        rule,
        endpoint=None,
        view_func=None,
        provide_automatic_options=None,
        **options
    )
endpoint:如果不写默认就是函数名,endpoint不能重名

app.add_url_rule参数

@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最后的 / 符号是否严格要求,默认严格,False,就是不严格
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>')
    '''

CBV源码分析

from flask import Flask,request,render_template,redirect
from flask import views

app=Flask(__name__)


# class IndexView(views.View):
# 	  继承views.View需要重写dispatch_request方法
#     methods = ['GET']
#     # decorators = [auth, ]
#     def dispatch_request(self):
#         print('Index')
#         return 'Index!'

def auth(func):
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result

    return inner
class IndexView(views.MethodView):
    methods = ['GET']  # 指定运行的请求方法
    # 登录认证装饰器加在哪?
    decorators = [auth, ]  #加多个就是从上往下的效果
    def get(self):
        print('xxxxx')
        return "我是get请求"
    def post(self):
       return '我是post请求'

# 路由如何注册?
# IndexView.as_view('index'),必须传name
app.add_url_rule('/index',view_func=IndexView.as_view('index'))

if __name__ == '__main__':
    app.run()
    
    
# 用的比较少
# 继承views.MethodView,只需要写get,post,delete方法
# 如果加装饰器decorators = [auth, ]
# 允许的请求方法methods = ['GET'] 

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)