Flask入门二(Flask的CBV、模版语法、请求和响应、session执行流程分析、Flask闪现、请求拓展、g对象)

文章目录

  • 一、Flask的CBV
    • 1.CBV的写法
    • 2.CBV的执行流程
    • 3.endpoint 的使用
    • 4.CBV中得methods作用
    • 5.CBV加装饰器
  • 二、模版语法
    • 1.渲染变量
    • 2.变量的循环
    • 3.逻辑判断
  • 三、请求和响应
  • 四、session执行流程分析
    • 1.基本使用
    • 2.执行流程
    • 3.Django中session的执行流程
  • 五、Flask闪现
    • 1.作用
    • 2.案例
    • 3.Django中的闪现(消息框架)
  • 六、请求扩展
  • 七、g对象

一、Flask的CBV

1.CBV的写法

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

# FBV的写法
@app.route('/')
def index():
    return 'hello'


# CBV的写法
from flask.views import MethodView
class TestView(MethodView):
    def get(self):
        return '我是get'

    def post(self):
        return '我是post'

# 注册路由
# as_view必须加一个字符串---》是路由的别名
# endpoint 和 as_view(name= 路由别名),以谁为准?
# 读源码后,知道了,以 endpoint 为准
# 如果endpoint 没传--》endpoint是 view_func.__name__ 视图函数的名字 ,别名就是函数名
# 如果endpoint 没传,as_view(name= 路由别名)也没传---》去视图函数名字-->视图函数都是:view
# as_view(name= 路由别名) 有什么用? 把view的名字改为了,你传入的字符串名
app.add_url_rule('/test', 'test', TestView.as_view('test'))


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

在这里插入图片描述

2.CBV的执行流程

	'从上面CBV的写法来查看执行流程'
	1.app.add_url_rule('/test', 'test', TestView.as_view('test'))
		-这个注册路由的第三个参数,放视图函数的内存地址,也就是TestView.as_view('test') 是函数内存地址
		
	2.所以我们需要在TestView中找类的方法as_view
		-已知我们自己写的TestView中没有写这个方法,所以得去继承的MethodView中寻找,最后在MethodView继承的View中找到了
		
		@classmethod  '把源码精简一下'
	    def as_view(cls, name,*class_args, **class_kwargs):
	        def view(**kwargs):
	        	'这里是把它放到异步函数中操作,本质就是return了self.dispatch_request(**kwargs)'
	            return current_app.ensure_sync(self.dispatch_request)(**kwargs)
	        return view
	        
	3.app.add_url_rule的第三个位置,也就是as_view,放的就是View的内层函数

	4.当请求来了的时候,路由匹配成功,就会执行view(参数),本质上就是执行self.dispatch_request(**kwargs)

	5.所以我们要去找dispatch_request方法,我们视图类中没有,那么去父类MethodView中寻找,结果找到了
	'这个就跟我们Django中的CBV一样了'
		'然后看到self.dispatch_request中方法 ,在当前视图类中反射,请求方式的小写字符串(get,post),如果我们写了这些方法 就会去执行。'
	    def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
	        # request.method.lower() 请求方式变小写
	        # self是视图类的对象
	        # 去视图类的对象中反射跟请求方式同名的方法 假设是get方法
	        meth = getattr(self, request.method.lower(), None)
	        if meth is None and request.method == "HEAD":
	            meth = getattr(self, "get", None)
	        assert meth is not None, f"Unimplemented method {request.method!r}"
	        # get(传入参数)
	        return meth(**kwargs)  

3.endpoint 的使用

	1.如果写了endpoint,别名以它为准,如果不写以as_view的参数为准
	app.add_url_rule('/test', endpoint='xxx',view_func=TestView.as_view('test'))
	
	'逻辑:'
	1 app.add_url_rule('/test',endpoint='xxx', view_func=TestView.as_view('test'))
	
	2 endpoint = _endpoint_from_view_func(view_func)
		如果endpoint没传也就是None,就会走这句 view_func是TestView.as_view('test')  它就是函数名
		if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)	# view_func.__name__
        options["endpoint"] = endpoint		# 如果都是endpoint就会冲突
        
	3 _endpoint_from_view_func(view_func)---》返回了传入的函数的名字
		return view_func.__name__
		# 如果没有其他更改--->所有cbv的函数内存地址都是view
	
	4 如果上面传入了TestView.as_view('test'),它的函数名就是view---》endpoint就是view
		-view.__name__ = name
	    -view的名字 是咱么  TestView.as_view('名字') 传入的名字,不再是view了
	
	'总结:'
	endpoint如果不传,会以视图函数的函数名作为endpoint
    	-fbv:如果不写endpoint,会以函数名作为endpoint,但是如果多个视图函数加了同一个装饰器,又没有指定endpoint,就会出错了
        -cbv:调用as_view一定要传入一个字符串---》如果endpoint没写,endpoint就是传入的这个字符串,如果写了,这个字符串没用
        
    如果传了,直接以endpoint传入的作为endpoint


	TestView.as_view(name='index'),name到底有啥用
		app.add_url_rule('/test', view_func=TestView.as_view('test'))
	   	没有传endpoint,Login.as_view('login')是view函数的内存地址
	       endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字
	       如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主
	       app.add_url_rule('/test', view_func=TestView.as_view(name='test'),endpoint='xxx')

4.CBV中得methods作用

	视图类中有个属性就是methods = ['GET', 'POST']
	用来控制允许的请求方式 写了什么方法 就允许什么请求 若没有写则不能使用该方法

5.CBV加装饰器

	1 使用步骤:在类中加入类属性:
	class UserView(MethodView):
	    decorators = [装饰器1,装饰器2] # 先写的装饰器放在最内部(最左边),是最后执行的装饰器
	    def get(self):
            return 'get'
	
	    def post(self):
	        return 'post'
	
	2.我们在as_view源码中可以看到
    if cls.decorators:
        view.__name__ = name
        view.__module__ = cls.__module__
         # 这就是装饰器的本质原理
        '循环拿出,然后使用装饰器来执行被装饰函数,然后在把执行的赋值给被装饰函数'
        for decorator in cls.decorators:
            view = decorator(view)

二、模版语法

1.渲染变量

<!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>

2.变量的循环

<!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>

3.逻辑判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% if name %}
          <h1>Hello {{ name }}!</h1>
        {% else %}
          <h1>Hello World!</h1>
        {% endif %}
    </table>
</body>
</html>

比django中多可以加括号,执行函数,传参数

	from flask import Flask,render_template,jsonify,make_response
	from markupsafe import Markup
	app = Flask(__name__, template_folder='temp')
	
	def func1(arg):
	    return Markup("<input type='text' value='%s' />" %(arg,))
	@app.route('/')
	def index():
	    return render_template('index.html',ff = func1)
	
	if __name__ == '__main__':
	    app.run()

	index.html
	<!DOCTYPE html>
	<html lang="en">
	<head>
	    <meta charset="UTF-8">
	    <title>Title</title>
	</head>
	<body>
	
	    {{ff('六五')}}
		{{ff('六五')|safe}}
	
	</body>
	</html>

	注意:
	1.Markup等价django的mark_safe ,
	2.extends,include一模一样

三、请求和响应

	from flask import Flask
    from flask import request
    from flask import render_template
    from flask import redirect
    from flask import make_response

    app = Flask(__name__)


    @app.route('/login.html', methods=['GET', "POST"])
    def login():
    	'请求(request,http请求中的东西,都能从request中取出来)'
        1.请求相关信息
        # request.method  提交的方法
        # request.args  get请求提及的数据
        # request.form   post请求提交的数据
        # request.values  post和get提交的数据总和
        # request.cookies  客户端所带的cookie
        # request.headers  请求头
        # request.path     不带域名,请求路径
        # request.full_path  不带域名,带参数的请求路径
        # request.script_root  
        # request.url           带域名带参数的请求路径
        # request.base_url		带域名请求路径
        # request.url_root      域名
        # request.host_url		域名
        # request.host			127.0.0.1:500
        # request.files
        # obj = request.files['the_file_name']
        # obj.save('/var/www/uploads/' + secure_filename(f.filename))
        
		'响应'
        2.响应相关信息
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')
        #return jsonify({'k1':'v1'})

        # response = make_response(render_template('index.html'))
        # response是flask.wrappers.Response类型
        # response.delete_cookie('key')
        # response.set_cookie('key', 'value')
        # response.headers['X-Something'] = 'A value'
        # 向响应头中添加
        res = make_response('hello')
        res.headers['xx'] = 'll'
        # return response
        retrun res

        return "内容"

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

四、session执行流程分析

1.基本使用

	'cookie 是客户端浏览器的键值对,session是存在于服务端的键值对'
	flask的session存在哪了?它加密后存放到了cookie中
	
	from flask import Flask, request,session
	from flask.views import MethodView
	
	app = Flask(__name__)
	app.debug = True
	app.secret_key='xuoikjfdlsakjfs'
	
	
	@app.route('/login', methods=['GET'])
	def login():
	    name = request.args.get('name')  # 获取路径后面的?name=xxx
	    '存入全局的Session,session需要匹配secret_key才能使用'
	    session['name'] = name
	    return 'Hello World!,%s' % name
	
	
	class UserView(MethodView):
	    def get(self):
	    	取值全局Session
	        name = session.get('name')
	        if name:
	            return '欢迎你:%s' % name
	        else:
	            return '没有登录无法查看'
	
	    def post(self):
	        return 'post'
	
	app.add_url_rule('/user', 'user', UserView.as_view('user'))
	
	if __name__ == '__main__':
	    app.run(debug=True)

2.执行流程

	'flask中通过SecureCookieSessionInterface对象来控制整个session的使用流程'
		app.session_interface=SecureCookieSessionInterface()
		
	1.登录成功后,会放到session中数据,最终它把session中的数据取出来,并且加密(dumps),放到cookie中,
	然后返回给前端-->save_session
	
	2.请求来了,请求中携带了cookie,然后falsk框架会取出cookie,然后会进行解密(loads)得到数据,
	把数据放到session中,然后进入到视图函数,这样在后续的视图函数中直接使用session.get()
	就能取出当时放入的值-->open_session

	'注意:不同浏览器,放的不一样,取出来也不一样'

	'SecureCookieSessionInterface 俩方法来支撑上面的流程'
	1.open_session: 请求来的时候--》解析出cookie,放到session中
	def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
		# 拿到解密或加密的对象
	    s = self.get_signing_serializer(app) # 获取签名的序列化
	    if s is None:
	        return None
	    
	    # request.cookie 取出客户端携带的cookie
	    # self.get_cookie_name(app) ---》 app.config["SESSION_COOKIE_NAME"]--》session
	    # eyJuYW1lIjoieHh4In0.ZeVMAw.2iCEYHAW7rDaH6Z5ntmKonErTbw
	    # val 就是取出的三段 头 荷载 签名
	    val = request.cookies.get(self.get_cookie_name(app))
	    if not val:
	        # 如果是空,就会走这里,这里做成空session后,返回了
	        return self.session_class()
	    # 如果不为空,继续执行下面代码,cookie在过期时间内
	    max_age = int(app.permanent_session_lifetime.total_seconds())
	    try:
	        # 解密--》把eyJuYW1lIjoieHh4In0.ZeVMAw.2iCEYHAW7rDaH6Z5ntmKonErTbw解成字典
	        data = s.loads(val, max_age=max_age)
	        # 组装成有 数据的session
	        return self.session_class(data)
	    except BadSignature:
	        return self.session_class()

	2.save_session:请求走的时候---》放到cookie中
	def save_session(self, app: Flask, session: SessionMixin, response: Response) -> None:
		 # 拿到  session 字符串  拿到配置文件中对应的配置
        name = self.get_cookie_name(app)
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        httponly = self.get_cookie_httponly(app)
        if session.accessed:
            response.vary.add("Cookie")
            
        # 如果session不为空,就继续往下走---》视图函数中放入了值  session[name]=jack
        if not session:
            # 判断session是否被修改过
            if session.modified:
                # 如果session被修改过,删除cookie
                response.delete_cookie(
                    name,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                    httponly=httponly,
                )
                response.vary.add("Cookie")

            return

        if not self.should_set_cookie(app, session):
            return

       	# 获取过期时间
        expires = self.get_expiration_time(app, session)
        # 获得加密对象,使用dumps对session进行加密---》asdfas.asdfas.asdfasd
        val = self.get_signing_serializer(app).dumps(dict(session))  # type: ignore
        # 放到cookie中
        response.set_cookie(
            name,
            val,  # type: ignore
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite,
        )
        response.vary.add("Cookie")

3.Django中session的执行流程

	# django 在中间件中做的
	session不是直接加密放在cookie 中得, 加密放在 django-session表中--》有个随机字符串对应
	
	1 app中要注册 session ---》生成django-session表
		'django.contrib.sessions',
	    
	2 中间件要注册--》真正支撑session流程的
	'django.contrib.sessions.middleware.SessionMiddleware',
	
	3 支撑session流程的
	请求走了---》把session--》写入到cookie中
		-def process_response(self, request, response):---》等价于---》save_session
	请求来了---》从cookie中取出来--》查数据库--》放到session中
		-def process_request(self, request)---》等价于---》open_session

	def process_request(self, request):
		# 取出 前端在cookie中携带的  随机字符串
	    session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
	    # SessionStore 实例化得到对象---》session_key是随机字符串
	    # 内部 根据随机字符串去django-session表中--》查出 session_data--》解密--》包装成对象
	    # 赋值给request.session -->后续所有视图函数中,都能使用request.session 放值或取值
	    request.session = self.SessionStore(session_key)
	
	def process_response(self, request, response):
	    try:
	        accessed = request.session.accessed
	        modified = request.session.modified
	        empty = request.session.is_empty()
	    except AttributeError:
	        return response
	    if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
	        response.delete_cookie(
	            settings.SESSION_COOKIE_NAME,
	            path=settings.SESSION_COOKIE_PATH,
	            domain=settings.SESSION_COOKIE_DOMAIN,
	            samesite=settings.SESSION_COOKIE_SAMESITE,
	        )
	        patch_vary_headers(response, ('Cookie',))
	    else:
	        if accessed:
	            patch_vary_headers(response, ('Cookie',))
	        if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
	            if request.session.get_expire_at_browser_close():
	                max_age = None
	                expires = None
	            else:
	                max_age = request.session.get_expiry_age()
	                expires_time = time.time() + max_age
	                expires = http_date(expires_time)
	            # Save the session data and refresh the client cookie.
	            # Skip session save for 500 responses, refs #3881.
	            if response.status_code != 500:
	                try:
	                    request.session.save()
	                except UpdateError:
	                    raise SessionInterrupted(
	                        "The request's session was deleted before the "
	                        "request completed. The user may have logged "
	                        "out in a concurrent request, for example."
	                    )
	                # 往cookie中放入 key是:session  value值是随机字符串: request.session.session_key
	                response.set_cookie(
	                    settings.SESSION_COOKIE_NAME,
	                    request.session.session_key, max_age=max_age,
	                    expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
	                    path=settings.SESSION_COOKIE_PATH,
	                    secure=settings.SESSION_COOKIE_SECURE or None,
	                    httponly=settings.SESSION_COOKIE_HTTPONLY or None,
	                    samesite=settings.SESSION_COOKIE_SAMESITE,
	                )
	    return response

五、Flask闪现

1.作用

	'访问A页面出现错误 重定向到B页面,要在B页面上展示A页面报错的信息'
	-在某个请求中放入值,另一个请求中取出,取出来后就没了(只能使用一次)
	-谁(浏览器)放入的,谁(浏览器)才能取出来
	-所以它实际上是放在session中了,但是flask中session是通过加密放在cookie中
	-所以闪现必须配合session(secret_key)使用
	

	使用方式1:
		设置值:
		    flash('用户名或密码错误')	# 可以用多次  
		取值:
		    get_flashed_messages()		# 取出列表

	使用方式2(高级使用,设置flash时,设置category分类):
		设置值:
			flash('用户名或密码错误',category='login')
	        flash('register的错误',category='register')	# 可以使用多次
		取值:
			res = get_flashed_messages(category_filter=['login'])  # 可迭代对象
			res = res[0][1]  # 取出来的格式为,列表套元组
			

2.案例

	from flask import Flask,request,session,render_template,redirect,flash,get_flashed_messages
	
	app=Flask(__name__)
	app.secret_key='kjfldaoiuozflka'
	app.debug=True
	
	@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 == 'jack' and password == '123':
	            # 存入session
	            session['name'] = username
	
	            return redirect('/')
	        else:
	            # 往flash中放入值
	            # flash('用户名或密码错误')
	            # 高级使用,设置分类
	            flash('用户名或密码错误',category='login')
	            flash('register的错误',category='register')
	            return redirect('/errors')
	            # return '用户名或密码错误!'
	
	
	@app.route('/',methods=['GET'])
	def index():
	    name = session.get('name')
	    if name:
	        return '欢迎您:%s'%name
	    else:
	        return '您还没有登录,请登录后尝试'
	
	
	@app.route('/errors')
	def errors():
	    # 从flash中取出值
	    # res = get_flashed_messages()[0]  # 是一个列表
	    # 高级使用,通过分类取出
	    res = get_flashed_messages(True,category_filter=['login'])  # 只拿登录相关的
	    res = res[0][1]  # 取出来的格式是列表套元组
	    # flash闪现,主要取出来就没有了
	    return '请求出错!,错误是:%s' % res
	
	
	if __name__ == '__main__':
	    app.run()

3.Django中的闪现(消息框架)

	1 注册app
	  'django.contrib.messages',

	2 注册中间件
	'django.contrib.sessions.middleware.SessionMiddleware',
	'django.contrib.messages.middleware.MessageMiddleware',

	3 配置 templates
	TEMPLATES = [
	    {
	        'BACKEND': 'django.template.backends.django.DjangoTemplates',
	        'DIRS': [os.path.join(BASE_DIR,'templates')],
	        'APP_DIRS': True,
	        'OPTIONS': {
	            'context_processors': [
									...
	                'django.contrib.messages.context_processors.messages',
	            ],
	        },
	    },
	]
	
	4 以后再视图函数中 放入
		from django.contrib import messages
		messages.debug
		messages.info
		messages.success
		messages.warning
		messages.error
		messages.warning(request,'登陆失败,用户名或密码无效')
	
	5 在 视图函数中取
		get_messages(request)
		# 4 在模板中
		{% if messages %}
		    {% for message in messages %}
		        <div class="alert alert-{{ message.tags }} fade in">
		            {{ message }}
		        </div>
		    {% endfor %}
		{% endif %}

六、请求扩展

在请求进入视图函数之前执行一些代码,请求出了视图函数以后执行一些代码,类似于django的中间件完成的功能6个装饰器(原来有7个,新版本去掉一个)

	1. before_request:在请求进视图函数之前执行
		多个的话会从上往下依次执行 django:process_request,如果返回四件套之一就直接返回了,在这里面正常使用request对象
		
	2. after_request:在请求从视图函数走之后执行
		多个的话会从下往上依次执行 django:process_response一样,要有参数和返回值参数就是response对象 返回值也必须是resposne对象
		session、request照常使用
		
	3. before_first_request:(这个新版本去掉了)项目启动后第一次访问会执行以后再也不执行了
		可以做一些初始化的操作
		
	4. teardown_request:每一个请求之后绑定一个函数即使遇到了异常,每个请求走都会执行记录错误日志
		@app.teardown_request
		def tear_down(e):
			print(e)  # 如果有异常,这是异常对象
			print('我执行了')
			
	5. errorhandler路径不存在时404,服务器内部错误500
		@app.errorhandler(404)
		def error_404(arg):
			print('404会执行我')
			return "404错误了"
			return render_template('404.html')
		
		@app.errorhandler(500)  # debug为False请情况下才能看到
		def error_500(arg):
		    print('500会执行我')
		    return "服务器内部错误"
		    
	6. template_global 标签 在模板中用  {{sb(1,2)}}
		@app.template_global()
			def sb(a1, a2):
			    return a1 + a2
			    
	7. template_filter过滤器  在模板中用  {{10|db(1,2)}}
		@app.template_filter()
			def db(a1, a2, a3):
			    return a1 + a2 + a3

展示案例

	from flask import Flask,request,session,render_template,redirect,flash,get_flashed_messages
	app=Flask(__name__)
	app.secret_key='kjfldaoiuozflka'
	app.debug=True
	
	@app.before_request  # 任意一次请求来的都会执行,被装饰函数
	def before_request():
	    # 判断如果没有登录,重定向到登录
	    if session.get('name') or 'login' in request.path:
	        print('请求来了')
	    else:
	        return redirect('/login')
	
	
	@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 == 'jack' and password == '123':
	            session['name'] = username
	
	            return redirect('/')
	        else:
	            flash('用户名或密码错误',category='login')
	            return redirect('/errors')
	
	
	@app.route('/',methods=['GET'])
	def index():
	    name = session.get('name')
	    if name:
	        return '欢迎您:%s'%name
	    else:
	        return '您还没有登录,请登录后尝试'
	
	
	@app.route('/errors')
	def errors():
	    res = get_flashed_messages(True,category_filter=['login'])
	    res = res[0][1]  # 取出来的格式是列表套元组
	    return '请求出错!,错误是:%s' % res
	
	
	@app.teardown_request  # 每一个请求之后绑定一个函数,即使遇到了异常
	def teardown_request(error):
	    # 可以在这里记录错误日志
	    print(error)
	
	
	@app.errorhandler(404)  # 监听http响应码:只要响应码对应,就会执行对应的函数
	def errorhandler(args):  # 会和debug模式冲突,因为debug模式是要在页面展示错误,会冲突
	    # 也可以写一个页面来展示404页面
	    return '路径不存在,404'
	
	
	@app.after_request  # 任意一次请求走了的都会执行,被装饰函数
	def after_reqeust(response):
	    print('请求走了')
	    # 在响应头中加入一些数据
	    response.headers['hello'] = 'world'
	    return response
	
	
	# 标签
	@app.template_global()  # {{sb(1,2)}}
	def sb(a1, a2):
	    return a1 + a2
	
	
	# 过滤器
	@app.template_filter()  # {{10|db(1,2)}}
	def db(a1, a2, a3):
	    return a1 + a2 + a3
	
	
	if __name__ == '__main__':
	    app.run()

七、g对象

专门用来存储用户信息的g对象,g的全称的为global
g对象在一次请求中的所有的代码的地方,都是可以使用的

from flask import Flask,request,session,g
# g global 全局的意思,每次请求,这个g一直存在,可以设置值和取值
app = Flask(__name__)
app.secret_key = 'kjfldaoiuozflka'
app.debug = True


@app.before_request
def before():
    # 在g中设置值
    g.name = 'jack'  # 放入g中


def ShowName():
    print('ShowName',g.name)

@app.route('/', methods=['GET'])
def index():
    # 取出g中得值
    print('index',g.name)
    ShowName()
    return 'hello world'


@app.after_request
def after(response):
    print(g.name)
    return response


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/428325.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity】Node.js安装与配置环境

引言 我们在使用unity开发的时候&#xff0c;有时候会使用一些辅助工具。 Node.js就是开发中&#xff0c;经常会遇到的一款软件。 1.下载Node.js 下载地址&#xff1a;https://nodejs.org/en 2.安装Node.js ①点击直接点击Next下一步 ②把协议勾上&#xff0c;继续点击…

【论文精读】I-JEPA

摘要 计算机视觉中&#xff0c;常采用基于不变性和基于生成的方法进行自监督学习。对比学习&#xff08;CL&#xff09;是典型的基于不变性的方法&#xff0c;通过预训练方法优化编码器&#xff0c;使其能生成同一图像的两个或多个视图的相似嵌入&#xff0c;其中图像视图通常由…

格两例12345

osu/Lucky Roll gaming 周末osu有道题&#xff1a;lcg已知低位 def lcg(s, a, b, p):return (a * s b) % pp getPrime(floor(72.7)) a randrange(0, p) b randrange(0, p) seed randrange(0, p) print(f"{p }") print(f"{a }") print(f"{b …

关于python函数参数传递

参数传递 在 python 中&#xff0c;类型属于对象&#xff0c;对象有不同类型的区分&#xff0c;变量是没有类型的&#xff1a; 在下面的代码示例重&#xff0c;[1,2,3] 是 List 类型&#xff0c;“qayrup” 是 String 类型&#xff0c;而变量 a 是没有类型&#xff0c;它仅仅…

java找工作之Mybatis(入门及xml配置相关)

Mybatis 学习Mybatis就要学会查看官网&#xff0c;官网地址如下&#xff1a;<MyBatis中文网 > 1、简介 1.1什么是Mybatis MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取…

图形系统开发实战课程:进阶篇(上)——9.空间算法(一)

图形开发学院&#xff5c;GraphAnyWhere 课程名称&#xff1a;图形系统开发实战课程&#xff1a;进阶篇(上)课程章节&#xff1a;“图形样式”原文地址&#xff1a;https://www.graphanywhere.com/graph/advanced/2-9.html 第九章 空间算法&#xff08;一&#xff09; \quad 在…

计算机专业必看的十部电影

计算机专业必看的十部电影 1. 人工智能2. 黑客帝国3. 盗梦空间4. 社交网络5. Her6. 模仿游戏7. 斯诺登8. 头号玩家9. 暗网10. 网络迷踪 计算机专业必看的十部电影&#xff0c;就像一场精彩盛宴&#xff01; 《黑客帝国》让你穿越虚拟世界&#xff0c;感受高科技的魅力《模仿游戏…

小红关鸡(双指针)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K Special Judge, 64bit IO Format: %lld 题目描述 有nnn个鸡窝排成一排&a…

#WEB前端(CCS常用属性,补充span、div)

1.实验&#xff1a; 复合元素、行内元素、块内元素、行内块元素 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; span为行内元素&#xff1a;不可设置宽高&#xff0c;实际占用控件决定分布空间。 div为块内元素&#xff1a;占满整行&#xff0c;可以设置宽高 img为行内块元…

Windows 2012 设置 nginx 开机自启动(适用于windows2012/10)

Windows 2012 设置 nginx 开机自启动&#xff08;适用于windows2012/10&#xff09;https://www.cnblogs.com/xuegqcto/articles/7521483.html 在windows server 2012上安装nginx&#xff0c;同时配置开机自启动服务&#xff08;推荐使用“Windows Service Wrapper”工具&…

前后端分离项目服务器部署

文章目录 前言准备工作安装jdk1.8安装nginx安装库解压、编译nginx并安装nginx 命令测试nginx 安装mysql卸载mariadb用root用户登录系统&#xff0c;增加mysql用户和组准备数据目录初始化MySQL将mysql加入到服务中编辑配置文件&#xff0c;保存退出启动mysql配置环境变量设置开机…

20 个不同的 Python 函数实例

Python 是一种广泛使用的高级编程语言&#xff0c;其函数是 Python 编程中至关重要的概念之一。函数是一段可以重复使用的代码块&#xff0c;可以接收输入参数并返回输出结果。使用函数能够提高代码的可读性、可维护性和重用性。 基础知识 在 Python 中&#xff0c;函数使用关…

C语言初阶—数组

数组是一组相同类型元素的集合。 在C99标准之前&#xff0c;数组的大小必须是常量或常量表达式。 在C99标准之后&#xff0c;数组的大小可以是变量&#xff0c;可以支持变长数组&#xff0c;但变长数组不能初始化。 不完全初始化&#xff0c;剩余的元素默认初始化为0 。 数组访…

c++_leetcode_寻找峰值

目录 一、寻找峰值的示例 二、官方实现代码及解释 1、官方测试结果&#xff1a; 2、代码解释&#xff1a; 3、解题思路&#xff1a; 三、我的暴力解决 1、测试一&#xff1a; 2、测试二&#xff1a; 3、最终“暴力求解”代码&#xff1a; 4、官网提交测试通过&#xf…

终极排序(快排,归并,库函数)

一、快速排序 1、确定分界点&#xff1a;q [ l ] , q [ ( l r ) / 2 ] , q [ r ] ,或者其它区间之中的随机数。&#xff08;左 l 右 r &#xff09; 2、调整区间&#xff1a;&#xff08;较难理解的部分&#xff09; &#xff08;1&#xff09;、暴力做法 …

基于Siamese网络的zero-shot意图分类

原文地址&#xff1a;Zero-Shot Intent Classification with Siamese Networks 通过零样本意图分类有效定位域外意图 2021 年 9 月 24 日 意图识别是面向目标对话系统的一项重要任务。意图识别(有时也称为意图检测)是使用标签对每个用户话语进行分类的任务&#xff0c;该标签…

云手机的境外舆情监控应用——助力品牌公关

在当今数字化时代&#xff0c;社交媒体已成为品牌传播和互动的主要平台。随之而来的是海量的信息涌入&#xff0c;品牌需要及时了解并应对海外社交媒体上的舆情变化。本文将介绍如何通过云手机进行境外舆情监控&#xff0c;更好地帮助企业公关及时作出决策。 1. 境外舆情监控与…

图像实现曲面屏效果

图像实现曲面屏效果 双线性插值 双线性插值是一种常用的图像插值方法&#xff0c;用于在图像中两个相邻像素之间进行插值&#xff0c;以获取介于它们之间某个位置的像素值。在透视变换等情况下&#xff0c;由于原始图像的像素点与目标图像的像素点位置不完全重合&#xff0c;…

HTML入门:推荐1款免费好用的web开发工具

前言 你好&#xff0c;我是云桃桃。 在过去的 10 年里&#xff0c;我一直专注于 web 前端开发领域&#xff0c;积累了丰富的经验和知识。 所以&#xff0c;接下来&#xff0c;我会把自己所学所做给体系化输出&#xff0c;我将持续与你分享关于 HTML、CSS、JavaScript&#x…

yolov7添加spd-conv注意力机制

一、spd-conv是什么&#xff1f; SPD-Conv&#xff08;Symmetric Positive Definite Convolution&#xff09;是一种新颖的卷积操作&#xff0c;它主要应用于处理对称正定矩阵&#xff08;SPD&#xff09;数据。在传统的卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;…
最新文章