首页 > 其他分享 >flask配置文件、路由、模板语法与cbv

flask配置文件、路由、模板语法与cbv

时间:2022-12-10 22:56:25浏览次数:44  
标签:__ index endpoint name 配置文件 flask app cbv view

web框架原理

1..符合wsgi协议
1.1使用wsgiref写
from wsgiref.simple_server import make_server

def mya(environ, start_response):
    print(environ)  # environ是http请求进来后变成的字典
    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__':
    # mya是可调用对象(函数、类、对象加括号)
    # 请求来时会执行mya,并将environ、start_response传入传过去
    myserver = make_server('', 8010, mya)
    print('监听8010')
    myserver.serve_forever()

1.2使用werkzeug写
'''
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, render_template, redirect, session, jsonify

app = Flask(__name__)
# 如果要使用session必需要加秘钥
app.secret_key = 'xaskfiwfnmkal;swfnmaocnklaK534'
USERS = {  # 数据
    1: {'name': '张三', 'age': 18, 'gender': '男', 'text': "道路千万条"},
    2: {'name': '李四', 'age': 28, 'gender': '男', 'text': "安全第一条"},
    3: {'name': '王五', 'age': 18, 'gender': '女', 'text': "行车不规范"},
    4: {'name': '赵六', 'age': 28, 'gender': '女', 'text': "亲人两行泪"},
}

# 登录页面
@app.route('/login', methods=['GET', 'POST'])
def login():
    # 这个request虽然是导入全局的,但如果是局部使用,就只是当次login请求的request
    if request.method == 'GET':
        return render_template('login.html')
    else:  # post请求,取出用户名和密码进行校验,正确则返回cookie,否则跳转index
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'barry' and password == '123':
            # 写入cookie,在重定向
            session['is_login'] = True
            return redirect('/index')
        else:
            return render_template('login.html', errors='用户名或密码错误')

# 首页显示用户信息
@app.route('/index', methods=['GET'])
def index():  # 登录后可以访问用户信息
    if session.get('is_login'):  # 登录了返回用户信息
        return render_template('index.html', **{'users': USERS})
    else:  # 没有登录则跳转到登录页面
        return redirect('/login')

# 显示用户详情
@app.route('/detail/<int:id>')
def detail(id):
    if session.get('is_login'):
        # 根据id获取当前用户
        user = USERS.get(id)
        return jsonify({'name': user.get('name'), 'age': user.get('age')})
    else:
        return redirect('/login')

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

'''
1.路由:@app.route('/detail/<int:id>', methods=['GET'])
2.新手4件套
-返回模板:return render_template('login.html', errors='用户名或密码错误')
-返回重定向:return redirect('/login')
-返回字符串:return '字符串'
-返回json字符串:return jsonify({'name': '字符串'})
3.使用cookie
就是sessin,全局的,导入使用即可,需要加秘钥
-存值:session['key'] = valus
-取值:session.get('key')
4.转换器:@app.route('/detail/<int:id>')
-要配合视图函数写法
'''

配置文件写法

1.flask中的配置文件是一个flask.config.Config对象(继承字典)
1.1默认配置为:
{
'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,
}
1.2比较重要的
DEBUG:是否是调试模式
SECRET_KEY:项目的秘钥

2.使用配置文件
2.1直接使用,通过app对象配置上,只能配置几个,本质都要放到app.config中
app.debug = True
app.secret_key = 'xaskfiwfnmkal;swfnmaocnklaK5'
app.session_cookie_name = 'sss'
print(app.config)

2.2直接通过app.config配置
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'xaskfiwfnmkal;swfnmaocnklaK5'
print(app.config)

2.3通过配置文件()
app.config.from_pyfile('settings.py')
print(app.config)
-settings.py
DEBUG = True
SECRET_KEY = 'xaskfiwfnmkal;swfnmaocnklaK5'

2.4通过类配置(可以有多套配置)
app.config.from_object('settings.DevelopmentConfig')
# app.config.from_object('settings.ProductionConfig')
print(app.config)
-配置类(setting.py)
class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'
class ProductionConfig(Config):
    DEBUG = False
    DATABASE_URI = 'mysql://192.168.11.11/foo'  # 上线数据库地址
class DevelopmentConfig(Config):
    DEBUG = True
    DATABASE_URI = 'mysql://127.0.0.1/foo'  # 开发本地数据库地址

2.5通过环境变量做配置
app.config.from_envvar("环境变量名称")
app.config.from_json("json文件名称")

2.6使用分布式配置中心
import requests
res=requests.get('asdfasdfasdf').json()
app.config.from_mapping(res)
# 配置文件都在本地

路由系统

[email protected]:重要的参数
-rule: 字符串的路径,使用转换器  <string:name>  <name>
'default':          UnicodeConverter,
'string':           UnicodeConverter,
'any':             AnyConverter,
'path':            PathConverter,    # /xx/sss/
'int':             IntegerConverter, # 数字
'float':            FloatConverter,   #小数
'uuid':            UUIDConverter,    #asdfas-asdfas-asdf
-methods: 列表,规定请求的方式,如果列表中没有,该请求方式不被支持
-endpoint:路由别名,如果不写,会以被装饰的函数名作为别名,django中叫name

路由本质

1.flask中路由是使用装饰器的,但是它的本质其实是app对象(Flask)的方法self.add_url_rule(rule, endpoint, f, **options)
-如果在视图函数上加了装饰器,其实本质是在调用self.add_url_rule
-如果不加装饰器,自己调用这个方法,也能完成路由的注册

2.路由本质
[email protected]('/')执行完成的结果是decorator内层函数--》@decorator
-index = decorator(index)
def decorator(f: T_route) -> T_route:
    # 如果没有传endpoint,这里就是None
    endpoint = options.pop("endpoint", None)
    # self是Flask对象,rule路由,endpoint是别名,其他打散传入options
    self.add_url_rule(rule, endpoint, f, **options)
    return f
-加了装饰器返回的还是index,只不过执行了 self.add_url_rule(rule, endpoint, f, **options)
-Flask类中得add_url_rule方法
    rule:就是装饰器传入的路径,路由
    endpoint:别名
    view_func:视图函数不加括号
-所以,如果不使用装饰器来注册路由
app.add_url_rule('/index', view_func=index, endpoint='index')

add_url_rule的参数

@app.route和app.add_url_rule参数:
# rule, URL规则
# view_func, 视图函数名称
# defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}
为函数提供参数,就是djagno中得kwargs

# endpoint = None, 名称,用于反向生成URL,即: url_for('名称'),等同于django的reverse
# methods = None, 允许的请求方式,如:["GET", "POST"]

# strict_slashes 对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 重定向到指定地址
redirect_to = None, 
    '''
        @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
    '''

flask的cbv

flask 的cbv写法

from flask import Flask
from flask.views import MethodView
app = Flask(__name__)

class Login(MethodView):
    def get(self):
        return 'get'
    def post(self):
        return 'post'
# 注册路由 name 是别名,本质就是endpoint
app.add_url_rule('/login', view_func=Login.as_view('login'))
if __name__ == '__main__':
    app.run()

cbv加装饰器

1.cbv如何加装饰器
类属性中加入,加入decorators = [auth, ],属性是一个列表,按照列表顺序,依次给每个方法加装饰器
'''
装饰器原理:
@auth
def view():
本质是  view=auth(view)  
'''
2.as_view执行
def as_view(cls, name: str, *class_args: t.Any, **class_kwargs: t.Any) -> ft.RouteCallable:
    if cls.decorators:
        for decorator in cls.decorators:
            # 给view加装饰器,就是给视图类中的方法加装饰器
            view = decorator(view)
    return view

as_view的执行流程

-as_view的执行流程
as_view(cls, name, *class_args, **class_kwargs):
    def view(**kwargs):
        return self.dispatch_request(**kwargs)
    return view
-请求来了,路由匹配成功,会执行as_view内的view()--》self.dispatch_request--》MethodView的dispatch_request
-MethodView的dispatch_request
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
    # 在当前视图类中反射,请求方式的小写字符串(get),我们写了get方法
    meth = getattr(self, request.method.lower(), None)
    # 执行get()
    return current_app.ensure_sync(meth)(**kwargs)

Login.as_view(name='index')

1.Login.as_view(name='index')中的name有什么用
-先研究 endpoint 有什么用,正常的fbv,如果不写endpoint,会以函数名作为别名,endpoint如何设置的
-如果endpoint为None,它把函数名作为了endpoint
if endpoint is None:
    endpoint = _endpoint_from_view_func(view_func)  # view_func.__name__
    options["endpoint"] = endpoint
-Login.as_view(name='index'),name到底有啥用
-app.add_url_rule('/login', view_func=Login.as_view('login'))
-没有传endpoint,Login.as_view('login')是 view函数的内存地址,
-endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字
-如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主
app.add_url_rule('/login',view_func=Login.as_view(name='login'),endpoint='xxx')

继承View写cbv

1.继承View写视图类(CBV)
-继承 View 的视图类,执行流程都是一样的
-请求来了,路由匹配成功,执行self.dispatch_request
-self.dispatch_request 没有实现,直接抛异常NotImplementedError()
-必须重写 dispatch_request,自己写匹配规则,执行不同的方法

2.cbv中得methods作用
-视图类中有个类属性 methods = ['POST']
-用来控制允许的请求方式
-如果不写,写了什么方法,就允许什么请求

模板语法

from flask import Flask, render_template

app = Flask(__name__)

USERS = {  # 数据
    1: {'name': '张三', 'age': 18, 'gender': '男', 'text': "道路千万条"},
    2: {'name': '李四', 'age': 28, 'gender': '男', 'text': "安全第一条"},
    3: {'name': '王五', 'age': 18, 'gender': '女', 'text': "行车不规范"},
    4: {'name': '赵六', 'age': 28, 'gender': '女', 'text': "亲人两行泪"},
}

@app.route('/')
def index():
    a = '<a href="http://www.baidu.com">点我看美女</a>'
    return render_template('test.html', user=USERS, a=a)

if __name__ == '__main__':
    app.run()
  • test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<table>
<h1>循环</h1>
    {% for k,v in user.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>

<table>
<h1>判断</h1>
    {% if name %}
        <h1>Hello {{ name }}!</h1>
    {% else %}
        <h1>Hello World!</h1>
    {% endif %}
</table>


<h1>a标签渲染</h1>
{{ a|safe }}
{{ a}}

</body>
</html>

登录显示用户信息写一下

-使用登录认证装饰器写,登录认证,写在index和detail上
-坑(1 顺序问题 2 需要指定endpoint)

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

app = Flask(__name__)
# 如果要使用session必需要加秘钥
app.secret_key = 'xaskfiwfnmkal;swfnmaocnklaK534'
USERS = {  # 数据
    1: {'name': '张三', 'age': 18, 'gender': '男', 'text': "道路千万条"},
    2: {'name': '李四', 'age': 28, 'gender': '男', 'text': "安全第一条"},
    3: {'name': '王五', 'age': 18, 'gender': '女', 'text': "行车不规范"},
    4: {'name': '赵六', 'age': 28, 'gender': '女', 'text': "亲人两行泪"},
}

# 登录验证
def outer(func):
    def core(*args, **kwargs):
        if session.get('is_login'):
            res = func(*args, **kwargs)
            return res
        else:
            return redirect('/login')
    return core

# 登录页面
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'barry' and password == '123':
            session['is_login'] = True
            return redirect('/index')
        else:
            return render_template('login.html', errors='用户名或密码错误')

# 首页显示用户信息
@app.route('/index', methods=['GET'], endpoint='index')
@outer
def index():
    return render_template('index.html', **{'users': USERS})

# 显示用户详情
@app.route('/detail/<int:id>', endpoint='detail')
@outer
def detail(id):
    return render_template('detail.html', **{'user': user})

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

标签:__,index,endpoint,name,配置文件,flask,app,cbv,view
From: https://www.cnblogs.com/riuqi/p/16972528.html

相关文章

  • 配置文件的读取
    1. 配置文件(nginx.conf)1#是注释行,2#每个有效配置项用等号处理,等号前不超过40个字符,等号后不超过400个字符;345#[开头的表示组信息,也等价于注释行6#[......
  • springboot启动读取配置文件过程&自定义配置文件处理器
        最近看到看到spring的配置文件放在了resources/config/application.yal文件内部,第一次见。就想的研究下,springboot启动读取配置文件的过程。1.启动过程org.sp......
  • CBV加装饰器的三种方式
    CBV如何加装饰器#先导包:fromdjango.utils.decoratorsimportmethod_decorator#方式一,加在某个具体的方法上,格式:@method_decorator(装饰器名字)#方式二,加在类上,格式......
  • containerd 配置文件 /etc/containerd/config.toml
    自动生成配置文件$containerdconfigdefault>/etc/containerd/config.toml修改配置文件后生效$systemctldaemon-reload&&systemctlrestartcontainerdvim/et......
  • flask蓝图与项目一般结构
    flask一般项目结构初始化配置flask项目时,路由和视图是放在启动文件里的,这样不太方便我们后期的整理和查阅!因此,我们需要将项目启动文件和路由视图分开处理!在项目文件下......
  • flask基础介绍和语法
    flask基础介绍和语法flask项目初始化的app.py介绍#从flask包中导入flask类fromflaskimportFlask#使用flask类实例化出一个app对象#__name__:代表当前app.py这......
  • 运维篇-配置文件优先级和自定义配置文件
           ......
  • VSCode C/C++编译/调试配置文件
    VSCode其实是一款编辑器,再加上一系列的扩展之后,就可以作为IDE使用了,而且很多轻量方便的扩展非常有用,特别是remote-SSH,已经成为远程开发linux程序必不可少的工具,我是用VSCod......
  • 学习python-flask
    Flask介绍目前python界,比较出名的web框架django:大而全,web开发用的东西,它都有Flask:小而精,只能完成请求与响应,session,cache,orm,admin则都没有。可以用很多第三方框架,使......
  • 【Flask】flask应用
    目录1.配置文件写法2.路由系统3.路由本质3.1add_url_rule的参数4.cbv写法4.1flask的cbv写法4.2cbv加装饰器,如何做?4.3as_view的执行流程4.4Login.as_view(name='......