flask框架-上

flask简介

  Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。

  Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。

为什么要从Flask开始学习web框架?

  依赖于wsgiref、jianjia2、wsgi、Werkzeug。

"""
1.python语言的灵活性给予了Flask同样的特征;

2.无论是用户画像还是产品推荐,python相比其他语言都有极大的优势;

3.Flask轻便,容易上手,试错成本低
"""

与其他web框架对比

"""(1)Django:比较“重”的框架,同时也是最出名的Python框架。包含了web开发中常用的功能、
组件的框架(ORM、Session、Form、Admin、分页、中间件、信号、缓存、ContenType....),
Django是走大而全的方向,最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。 (2)Tornado:大特性就是异步非阻塞、原生支持WebSocket协议; (3)Flask:如上 (4)Bottle:是一个简单高效的遵循WSGI的微型python Web框架。说微型,是因为它只有一个文件,除Python标准库外,它不依赖于任何第三方模块。
"""

flask安装及使用

 目录结构

通过别人的目录大致了解一下flask框架的目录结构

 初始化项目

(1)、创建flask实例对象

flask程序必须创建一个程序实例,常用的方法:

   这里的app就是一个程序实例,客户端(一般是浏览器)将请求发送给服务端Web服务器,Web服务器再把请求发给Flask实例。

(2)构建实例对象从URL到python函数的映射关系

  程序实例需要知道所有URL对应的执行代码,所以要有从URL到python函数的映射关系。处理URL到python函数映射关系的程序一般叫做路由(Router)

(3)启动服务器 

 开始测试hello world

最简单的测试

 这是flask框架制作的一个最小的应用。使用python运行后访问localhost:5000就能看到网页显示Hello world。

  这里首先引入了Flask类,然后给这个类创建了一个实例,name代表这个模块的名字。因为这个模块是直接被运行的所以此时name的值是main。
然后用route()这个修饰器定义了一个路由,告诉flask如何访问该函数。最后用run()函数使这个应用在服务器上运行起来。

flask模板

 Flask的模板功能是基于Jinja2模板引擎实现的。让我们来实现一个例子吧。创建一个新的Flask运行文件(你应该不会忘了怎么写吧),代码如下:

 flask启动的本质

  flask依赖于两个模块的运行:werkzeug、wsgiref.

wsgiref可以当做独立的server来运行。

from wsgiref.simple_server import make_server

def mya(environ, start_response):
    print(environ)
    start_response('200 OK', [('Content-Type', 'text/html')])
    if environ.get('PATH_INFO') == '/index':
        with open('index.html','rb') as f:
            data=f.read()

    elif environ.get('PATH_INFO') == '/login':
        with open('login.html', 'rb') as f:
            data = f.read()
    else:
        data=b'<h1>Hello, web!</h1>'
    return [data]

if __name__ == '__main__':
    myserver = make_server('', 8011, mya)
    print('监听8011')
    myserver.serve_forever()

werkzeug是WSGI工具包,它可以作为web框架的底层库

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

app=Flask(__name__)

# mvc.c  CBV
@app.route('/')路由
def index():
    return "back ok"

if __name__ == '__main__':
    # 本质上run_simple(host,port,app,**options)
   # app(),对象加().执行__call__
   app.run()

默认的启动ip和端口:

flask的四剑客使用

from flask import Flask,render_template,redirect,Response,jsonify

app=Flask(__name__)

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

    # 1直接返回字符串
    # return "人生苦短,我学Python"

    # 2返回html
    # name_dict = {"name":'Eason'}
    # return render_template("text.html",name="java",name_dict=name_dict)

#跳转页面 # return redirect("/login") # 返回json数据 name_dict = {{"name":"jack"},{'hobby':"music"}} @app.route('/login') def login(): return "Hello woorld" if __name__ == '__main__': app.run()

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 %}

</body>
</html>

flask配置文件的4种方式

  只要配置之后,Ctrl+s保存,即可实现重启服务器生效的作用。

from  flask import Flask
app=Flask(__name__)
#配置文件1,这中方式只能配置两种 # app.debug=True # app.secret_key="123123" #第二种,以字典的形式 # app.config['DEBUG']=True

#第三种,以文件的形式 # app.config.from_pyfile("settings.py") #第四种以类的形式(推荐) settings.py文件下自定义的类。 app.config.from_object('settings.DevelopmentConfig')
@app.route(
'/login') def login(): print(123) return "ojbk_login" if __name__ == '__main__': app.run()

settings.py

# DEBUG = True

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

其他配置方式,有哪些配置,了解即可。

 {
 2         'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
 3         'TESTING':                              False,                          是否开启测试模式
 4         'PROPAGATE_EXCEPTIONS':                 None,                          
 5         'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
 6         'SECRET_KEY':                           None,
 7         'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
 8         'USE_X_SENDFILE':                       False,
 9         'LOGGER_NAME':                          None,
10         'LOGGER_HANDLER_POLICY':               'always',
11         'SERVER_NAME':                          None,
12         'APPLICATION_ROOT':                     None,
13         'SESSION_COOKIE_NAME':                  'session',
14         'SESSION_COOKIE_DOMAIN':                None,
15         'SESSION_COOKIE_PATH':                  None,
16         'SESSION_COOKIE_HTTPONLY':              True,
17         'SESSION_COOKIE_SECURE':                False,
18         'SESSION_REFRESH_EACH_REQUEST':         True,
19         'MAX_CONTENT_LENGTH':                   None,
20         'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
21         'TRAP_BAD_REQUEST_ERRORS':              False,
22         'TRAP_HTTP_EXCEPTIONS':                 False,
23         'EXPLAIN_TEMPLATE_LOADING':             False,
24         'PREFERRED_URL_SCHEME':                 'http',
25         'JSON_AS_ASCII':                        True,
26         'JSON_SORT_KEYS':                       True,
27         'JSONIFY_PRETTYPRINT_REGULAR':          True,
28         'JSONIFY_MIMETYPE':                     'application/json',
29         'TEMPLATES_AUTO_RELOAD':                None,

路由系统

@app.route('/xxx/<username>')
@app.route('/xxx/<int:id>')
@app.route('/xxx/<float:id>')
@app.route('/xxx/<path:path>')
@app.route('/xxx', methods=['GET', 'POST'])

@app.route本质,源码分析

 

 内部源码add_url_rule,所需要传的参数:view_func、endpoint....

 代码演示

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

@app.route('/login',methods=['POST','GET'],endpoint="test")
#decorator
def login(nid):
    print(type(nid),nid)
    return "obi_login"

# rule 就是路由
# enpoint,取别名,如果没有就用当前的函数名
# enpoint,不能重复
# methods=["POST","GET"]

# view_func 就是我们enpoint,指向的函数,也就是请求该路由的时候,要响应函数
# app.add_url_rule(rule,'取别名,反向解析,login')
app.add_url_rule('/login/<strnig:nid>',view_func=login,endpoint="func",methods=["POST","GET"])

"""
取别名:
"""
#app01.route('/',endpoint="func")

def index():
    real_url = url_for("test")
    return real_url

app.add_url_rule('/index',view_func=index,methods=["POST","GET"])

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

 method=[],如果不传参数,默认是视图类,可以只传POST/GET.

路由默认的转换器,有名分组支持的数据类型

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

初识flask中的CBV视图

cbv视图类的基本写法

#第一种方法
class IndexView(views.View):
    methods = ['GET']
    decorators = [auth, ]

    def dispatch_request(self):
        print('Index')
        return 'Index!'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  
#第二种方法(通常使用这种) class IndexView(views.MethodView): methods = ['GET','POST'] #指定可以接收的方法有什么,默认可以不写 decorators = [auth, ] #指定自定义的装饰器 def get(self): return 'Index.GET' def post(self): return 'Index.POST' app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))

 

总结流程:

1.先从flask中导入views

2.写一个类一定要继承views.MethodView

3.在类中写methods = ['GET','POST'],可以指定可接受的请求类型,默认是两种都行

4.在类中写decorators = [auth,]可以指定装饰器,第一个装饰器是最里层函数依次往外包裹

5.在类中写def get(self):用于获取get请求

6.在类中写def post(self):用于获取post请求

7.添加路由的方法使用

app.add_url_rule('路由', view_func=IndexView.as_view(name='自定义一个端点名字'))  

  其原理是IndexView.ad_view(name='自定义名字')会返回一个函数,name是为这个函数命名,可以通过这个函数进行分发请求等操作。

#IndexView.as_view(name='index')都views.View里面的as_view的view
#为什么要as_view(name='index'),
#如果不指定,就都是view
#所以必须指定

 

CBV常用的模式

继承的是:MethodView

登录实现

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):
    info = USERS.get(nid)
    return render_template('detail.html',info=info)

@app.route('/index',methods=['GET'])
def index():
    return render_template('index.html',user_dict=USERS)

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':
            url=url_for('index')
            return redirect(url)
            # session['user_info'] = user
        return render_template('login.html', error='用户名或密码错误')
app.add_url_rule("/login",view_func=login,methods=["GET","POST"])



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

 

posted @ 2019-11-11 18:26  游走De提莫  阅读(263)  评论(0编辑  收藏  举报