01. flask简介

一、flask

1、flask简介

1 Flask是一个基于Python开发并且依赖jinja2模板(django模板语言)和Werkzeug WSGI(django:wsgiref)服务的一个微型框架

2 对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器

3(micro) 可以用单文件,也可以搞成django很多目录(自由定制)
缓存,认证,forms,orm。。。都没有---》很多第三方集成进去,想用就用,不想用就不集成---》可以任意组合
4 安装 :pip3 install flask

2、flask简单使用

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

# flask的路由是基于装饰器
@app.route('/')
def index():
    # 没有请求对象,没有响应对象
    return 'hello world flask'

if __name__ == '__main__':
    app.run()   # 默认port是5000

# 终端运行flask run -p 8000 才能改变默认端口号

3、新手四件套

from flask import Flask, render_template, redirect, jsonify

# 实例化得到一个flask对象
app = Flask(__name__, template_folder='templates')

@app.route('/')
def hello_world():
    # 1、返回字符串
    return 'Hello World!'
    # 2、返回模板
    # return render_template('index.html')
    # 返回重定向
    # return redirect('https://baidu.com')
    # 返回json格式
    # return jsonify({'name': 'cc', 'age': 18})

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

4、请求对象

from flask import Flask, request

app = Flask(__name__, template_folder='templates')

@app.route('/')
def index():
    print(request)
    print(request.method)  # method
    print(request.cookies)  # cookie
    print(request.environ)  # meta
    print(request.form)  # POST
    print(request.query_string)  # BODY
    print(request.args)  # GET
    return 'hello world'


@app.route('/home/')
def home():
    print(request.method)  # method
    print(request.args)  # GET
    return 'home'


if __name__ == '__main__':
    app.run()
# 上面的案例中request是一个全局对象,request.args--->不同请求取出来是不同请求携带的数据
# flask是通过不同线程/协程来区分是哪个request

二、登录小案例

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

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 == 'cc' and pwd == '123':
            return redirect('https://www.baidu.com')
        return render_template('login.html', error='用户名或者密码错误')
 
if __name__ == '__main__':
    app.run()

detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>detail</title>
</head>
<body>
<h1>详细信息</h1>
<div>
    {{ info.name }}
    {{ info.text }}
</div>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</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>	

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</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>

三、配置文件

flask的配置方式一:

from  flask import Flask,request,render_template,session,redirect,url_for

app=Flask(__name__)
## 方式一,直接给app设置(仅仅支持以下两个)
app.secret_key = 'asdfasdfasdf4545322wefaaeaesfsad'
app.debug = True  # 调试模式

方式二:

# 给app的config设置,可以作用于所有的配置
print(app.config)
app.config['DEBUG'] = True

方式三:通过settings.py文件(类似于django,不常用,不推荐)

app.config.from_pyfile('settings.py')

方式四:通过环境变量配置(不常用)

import os
os.environ['DEBUG'] = 'True'
app.config.from_envvar(os.environ['DEBUG'])
# app.config.from_pyfile(os.environ['YOURAPPLOCATION_SETTINGS'])
# 环境变量的值为python文件的名称,内部调用from_pyfile方法

方式五:通过json文件(不常用)

app.config.from_json('settings.json')
# json文件名称,必须是json格式,因为内部会执行json.loads

# app.config.from_mapping({'DEBUG': True})  # 此方式也不常用

方式六:通过类配置(常用)

app.config.from_object('settings.ProductionConfig')

print(app.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,
        
    }
'''

settings.py

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URL = 'xxxx'
    USER='root'
    PASSWORD='123'


class ProductionConfig(Config):
    DATABASE_URL = 'mysql://user@localhost/foo'
    USER = 'luffy'
    PASSWORD = 'luffy?'


class DevelopmentConfig(Config):
    DEBUG = True
    DATABASE_URL = '127.0.0.1'
    USER = 'root'
    PASSWORD = '123'


class TestingConfig(Config):
    TESTING = True
   
# app文件使用:
# app.config.from_object('settings.ProductionConfig')

四、路由系统

典型写法:

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

默认转换器

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

路由系统本质(重点)

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return 'hello world'

# @app.route('/')----本质原理----》index=app.route('/')(index)
# 执行app.route()--->得到decorator内存地址----》index=decorator(index)
# 执行 self.add_url_rule(rule, endpoint, f, **options)

不使用装饰器来注册路由:

def index():
    return jsonify({'name':'lqz','age':18})

def home():
    return 'home'


# 不用装饰器,自己注册路由
app.add_url_rule('/',endpoint='index',view_func=index)
# 与django路由类似: url('/index',view.test,name='xxx')
app.add_url_rule('/home',endpoint='home',view_func=home)


# django与flask路由:flask路由基于装饰器,本质是基于:add_url_rule
# add_url_rule 源码中,endpoint如果为空,endpoint = _endpoint_from_view_func(view_func),最终取view_func.__name__(即函数名)
# endpoint如果不传,默认用函数名作为反向解析的名字,但是一定要注意多装饰器的问题

CBV(源码分析)

from flask.views import View,MethodView
# 继承View,必须重写dispatch_request,自己去做分发
class Index(View):# 一般不继承view,因为重写dispatch_request比较麻烦
    # 重写dispatch_request
    def dispatch_request(self):
        return '所有请求都走我,我自己分发'

# 继承MethodView----》它等同于django中的View
class Index(MethodView):
    def get(self):
        print(request.method)
        return 'index的get请求'
    def post(self):
        return 'index的post请求'
   
### 可以通过自定义,让路由支持正则(了解)

# 注册路由
# 如果是cbv,as_view(name='xx') name就是别名
# 优先用endpoint指定的
# 如果endpoint不传,使用函数名字作为endpoint---->即view
app.add_url_rule('/index',endpoint='sss',view_func=Index.as_view(name='xx'))

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

路由中直接做重定向

@app.route('/', defaults={'name':'cc'}, redirect_to='https://www.baidu.com')
def index(name):
    return 'xxx'

add_rul_url的参数

'''
@app.route和app.add_url_rule参数:
rule, URL规则,不支持正则 (django2.0以后也不用正则了)
view_func, 视图函数名称 (cbv  类名.as_view(name))
defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'} 为函数提供默认参数
endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]
strict_slashes = None, 对URL最后的 / 符号是否严格要求
	示例:
        @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
'''

可以通过自定义,让路由支持正则(了解)

# 注册路由
# 如果是cbv,as_view(name='xx') name就是别名
#如果endpoint不传,使用函数名字作为endpoint----view
# 优先有endpoint指定的
app.add_url_rule('/index',endpoint='sss',view_func=Index.as_view(name='xx'))

if __name__ == '__main__':
    app.run()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值