python 全栈开发,Day120(路由系统, 实例化Flask的参数, 蓝图(BluePrint), before_request after_request)

昨日内容回顾

1.Flask:from flask import Flaskapp = Flask(__name__)# 从源码中可以看出,Flask集成的run方法是由werkzeug中的run_simple方法提供的。app.run() # run_simple(host,port,obj_or_func())obj() 对象加括号相当于调用 __call__() 方法2.简单路由@app.route("/index",methods=["GET","POST"])def index(){return}默认GET请求,如果改写了methods,GET一定要加上3.flask 中的返回值:左边是django,右边是flaskHttpResponse  == return "OK!"render == render_templateredirect == redirectreturn send_file() # 将一个文件打开,然后返回文件内容4.request:requestform:POST中的FormData数据存放在form(字典) 通过字典的方式去取值args:URL参数存放在args(字典) 通过字典的方式去取值values: url + FormData .to_dict()同名key url覆盖Formdatadata: 当 content-type:None 也就是无法处理时,将数据存放在data中 并且以b"{k:v}"形式存储,是bytes类型json: 当 content-type:application/json 数据以Json放存放5.Flask Jinja2{{}} 非逻辑{%%} 包含逻辑{% for i in a %}{% endfor %}{% if True %}{% endif %}前端:| safe :安全标签字符串儿后端: Markup(tag) :安全标签字符串儿@app.template_global() # 定义模板全局函数def func():return 1+1前端:{{ func() }}@app.template_filter() # 定义模板全局函数,类似偏函数def func(a):return a前端:{{ 1 | func() }}extends 模板继承include 加载模板宏定义:很少用{% macro func(ty , na) %}<input type="{{ ty }}" name="{{ na }}" >{% endmacro %}调用:func("text","username")6.flask 中的 sessionapp.secret_key = "alex DSB"session 序列化一个加密字符串,存在前端的cookie。它的键名就是session当发起请求的时候,将字符串发送到后端反序列化,拿出存放在服务器端的sessionsession["key"] = "value" # 就是字典
注意:cookie存储在浏览器中,session存储在服务器中。cookie相当于钥匙,session相当于银行保险柜!
View Code

昨日作业讲解

昨天的作业就是,有3个视图函数,分别是/login,/student_list,/student_detail。写一个装饰器,除了/login以外,其他视图函数都要登录才行!

使用session判断!

原始代码

from flask import Flask,render_template,sessions,request,redirectapp = Flask(__name__)USER = {'username': 'xiao', 'password': "123"}@app.route("/login",methods=["POST","GET"])
def login():if request.method == "GET":# 前端模板中使用了msg,这里就算是传递空,也要出现msgreturn render_template("login.html", msg="")if request.form["username"] == USER["username"] and request.form["password"] == USER["password"]:return redirect("/student_list")return render_template("login.html", msg="用户名密码错误")@app.route("/student_list")
def student_list():return "学生列表"@app.route("/student_detail")
def student_detail():return "学生详情"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

 

使用装饰器

from flask import Flask,render_template,session,request,redirectapp = Flask(__name__)
# 使用session,必须设置secret_key
app.secret_key = "123asdzxc"USER = {'username': 'xiao', 'password': "123"}def auth(func):def inner(*args,**kwargs):if session.get("user"):return func(*args,**kwargs)else:return redirect("/login")return inner@app.route("/login",methods=["POST","GET"])
def login():if request.method == "GET":# 前端模板中使用了msg,这里就算是传递空,也要出现msgreturn render_template("login.html", msg="")username = request.form["username"]  # 获取POST请求时,FormData中的参数# password = request.form.get("password")if request.form["username"] == USER["username"] and request.form["password"] == USER["password"]:# 设置sessionsession["user"] = usernamereturn redirect("/student_list")return render_template("login.html", msg="用户名密码错误")@app.route("/student_list",endpoint="student_list")
@auth
def student_list():return "学生列表"@app.route("/student_detail",endpoint="student_detail")
@auth
def student_detail():return "学生详情"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

 

重启flask,直接访问student_list

http://127.0.0.1:5000/student_list

打开浏览器工具,查看网络。它会跳转至登录页面!

输入正确的用户名和密码

提交之后,跳转页面

 

 注意:使用装饰器的视图函数,必须要定义endpoint参数。

因为使用装饰器之后,视图函数都是inner,所以flask无法区分,路由到底指向哪一个视图函数。

启动flask之后,会直接报错。endpoint参数,是给url起别名,唯一标识。可以做url反向解析!

 

还有一种方法,使用@functools.wraps装饰器,保留原函数信息,比如函数名。

但是不推荐使用。因为定义视图函数,本身就应该定义endpoint参数

 

一、路由系统

Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用

@app.route("/",methods=["GET","POST"])

为什么要这么用?其中的工作原理我们知道多少?

@app.route() 装饰器中的参数

1. @app.route() 装饰器中的参数

如果不明白装饰器 点击这里

methods

methods : 当前 url 地址,允许访问的请求方式

from flask import Flask,requestapp = Flask(__name__)@app.route("/info", methods=["GET", "POST"])
def student_info():stu_id = int(request.args["id"])return f"hello kitty {stu_id}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

访问url,注意:要带上参数id,否则报错

http://127.0.0.1:5000/info?id=1

效果如下:

endpoint

endpoint : 反向url地址,默认为视图函数名 (url_for)

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", methods=["GET", "POST"],endpoint="r_info")
def student_info():print(url_for("r_info"))  # /infostu_id = int(request.args["id"])return f"hello kitty {stu_id}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

刷新页面,效果同上!查看Pycharm控制台输出:

/info

注意:这并不是完整的url。如果要给前端妹子,返回一个完整的URL怎么办呢?

url_for

url_for:用于反向生成url,也可以附带一些参数,比如想要完整的URL,可以设置_external为Ture:

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", methods=["GET", "POST"],endpoint="r_info")
def student_info():stu_id = int(request.args["id"])print(url_for("r_info", _external=True))return f"hello kitty {stu_id}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

刷新页面,效果同上!查看Pycharm控制台输出:

http://127.0.0.1:5000/info

 

但是还不够,参数没有啊?怎么办?再加上url参数。

注意:由于id是动态参数,所以后台获取时,要和实际的参数匹配。这里是id

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", methods=["GET", "POST"],endpoint="r_info")
def student_info():stu_id = int(request.args["id"])print(url_for("r_info", _external=True,id=stu_id))return f"hello kitty {stu_id}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

刷新页面,效果同上!查看Pycharm控制台输出:

http://127.0.0.1:5000/info?id=1

这下,就非常完美了!

defaults

defaults : 视图函数的参数默认值{"nid":100}

注意:视图函数必须要设置形参nid,否则报错!

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", methods=["GET", "POST"],endpoint="r_info",defaults={"nid": 100})
def student_info(nid):# stu_id = int(request.args["nid"])print(url_for("r_info", _external=True))print(nid)return f"hello kitty {nid}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

 

访问url:  http://127.0.0.1:5000/info

效果如下:

strict_slashes

strict_slashes : url地址结尾符"/"的控制 False : 无论结尾 "/" 是否存在均可以访问 , True : 结尾必须不能是 "/"

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", strict_slashes=True)
def student_info():return "hello kitty info"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

 

末尾不带 "/"

 

 

末尾带 "/"

也就是说:strict_slashes = True ,表示开启路由严格匹配模式!即使末尾多了一个"/",也不允许访问!

 

将参数改为False

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", strict_slashes=False)
def student_info():return "hello kitty info"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

 

刷新页面,又可以访问了

如果多加一个s,会报404

总结:strict_slashes 用来控制末尾是否有"/",为Ture,带 "/"不允许!

为False,不管你带不带"/",都可以访问!

redirect_to

redirect_to : url地址重定向

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info", redirect_to="/infos")
def student_info():return "hello kitty info"@app.route("/infos")
def student_infos():return "Hello Tom infos"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)
View Code

访问url:  http://127.0.0.1:5000/info,会发生重定向

查看浏览器工具,查看网络。它经历了2次请求!

它有什么应用场景呢?

比如你的网站域名是xx.com,后来你的网页改版了,换了新的域名qqxx.com。但是老客户还不知道你的新域名啊!怎么办呢?用重定向就可以了!

subdomain

subdomain : 子域名前缀 subdomian="qq" 这样写可以得到 qq.xx.com 前提是app.config["SERVER_NAME"] = "xx.com:5000"

from flask import Flask,request,url_forapp = Flask(__name__)# 一定一定一定要写端口!!!!!!
app.config["SERVER_NAME"] = "xx.com:5000"@app.route("/",endpoint="r_info",subdomain="qq")
def student_info():print(url_for("r_info", _external=True,))return "hello kitty info"if __name__ == '__main__':# 监听端口为5000,注意:要和SERVER_NAME匹配!app.run("0.0.0.0", 5000, debug=True)
View Code

注意:app.config["SERVER_NAME"] = "xx.com:5000"。

一定要加端口!一定要加端口!一定要加端口!重要的事情说三遍!!!

就是因为没有加端口,快要放弃了!google了一把,终于找到原因了!

 

这里是window 10访问。必须要修改本机的Hosts文件,至于怎么修改,为啥没有权限,请自行百度!

修改Hosts文件,添加一条记录

127.0.0.1    qq.xx.com

打开cmd窗口,ping qq.xx.com,请确保返回地址是127.0.0.1

 

打开浏览器访问url,注意:只能是qq.xx.com访问。不能是xx.com!访问时,一定要带上端口!

http://qq.xx.com:5000/

效果如下:

 

关于路由目前就说这么多,之后的课程中会有关于Flask路由系统的源码剖析,再详细说明Flask路由系统的工作原理

 

动态参数路由

2.动态参数路由:

<int:参数名> 参数转换为整形

<int:nid> 就是在url后定义一个参数接收

但是这种动态参数路由,在url_for的时候,一定要将动态参数名+参数值添加进去,否则会抛出参数错误的异常

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info/<int:nid>", endpoint="r_info")
def student_info(nid):print(url_for("r_info", _external=True,nid=nid))return f"hello kitty {nid}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':# 监听端口为5000app.run("0.0.0.0", 5000, debug=True)
View Code

访问url,一定要带上参数,而且参数必须是数字!

查看Pycharm控制台输出:

12 <class 'int'>
http://127.0.0.1:5000/info/12

 

如果是字符串,会报错

 

<string:参数名> 参数转换为字符串

from flask import Flask,request,url_forapp = Flask(__name__)@app.route("/info/<string:nid>", endpoint="r_info")
def student_info(nid):print(nid,type(nid))print(url_for("r_info", _external=True,nid=nid))return f"hello kitty {nid}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':# 监听端口为5000app.run("0.0.0.0", 5000, debug=True)
View Code

刷新页面,就可以访问了

查看Pycharm控制台输出:

ask <class 'str'>
http://127.0.0.1:5000/info/ask

 

参数是数字也是正常的

路由正则

3.路由正则:

一般不用,如果有特殊需求,不怕麻烦的话,这个东西还是挺好用的,前提是你的正则玩儿的很6

from flask import Flask,request,url_for
# 导入转换器基类
from werkzeug.routing import BaseConverterapp = Flask(__name__)# 自定义正则转换器
class RegexConverter(BaseConverter):def __init__(self, url_map, *args):super(RegexConverter, self).__init__(url_map)# 将接受的第1个参数当作匹配规则进行保存self.regex = args[0]# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter# 使用转换器去实现自定义匹配规则
# 当前此处定义的规则是:3位数字
@app.route('/info/<re("[0-9]{3}"):nid>', endpoint="r_info")
def student_info(nid):print(url_for("r_info", _external=True,nid=nid))return f"nid 为 {nid}"  # Python3.6的新特性 f"{变量名}"if __name__ == '__main__':# 监听端口为5000app.run("0.0.0.0", 5000, debug=True)
View Code

访问url,注意:参数必须是3位数字

 

本文参考:

https://www.cnblogs.com/DragonFire/p/9260295.html

二、实例化Flask的参数

Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢?

有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢?

首先展示一下:

from flask import Flaskapp = Flask(__name__)  # type:Flask
app.config["DEBUG"] = Trueif __name__ == '__main__':app.run()
View Code

这句 app.config["DEBUG"] = True 可以实现的功能可刺激了

代码只要发生改动,自动重启Flask程序(app.run)

在控制台打印的信息非常全面

以上两个功能就是传说中的 DEBUG 模式(调试模式)

 

Flask的配置就是在 app.config 中添加一个键值对,但是你存进去的键必须是config中应该存在的,如果不再存在的话,它会默认无用,就这么放着

config中有多少有用的key 呢?

{'DEBUG': False,  # 是否开启Debug模式'TESTING': False,  # 是否开启测试模式'PROPAGATE_EXCEPTIONS': None,  # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True'PRESERVE_CONTEXT_ON_EXCEPTION': None,  # 一两句话说不清楚,一般不用它'SECRET_KEY': None,  # 之前遇到过,在启用Session的时候,一定要有它'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命周期(天)默认31天'USE_X_SENDFILE': False,  # 是否弃用 x_sendfile'LOGGER_NAME': None,  # 日志记录器的名称'LOGGER_HANDLER_POLICY': 'always','SERVER_NAME': None,  # 服务访问域名'APPLICATION_ROOT': None,  # 项目的完整路径'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字'SESSION_COOKIE_DOMAIN': None,  # 在哪个域名下会产生session记录在cookies中'SESSION_COOKIE_PATH': None,  # cookies的路径'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否应被设置 httponly 的标志,'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否应被设置安全标志'SESSION_REFRESH_EACH_REQUEST': True,  # 这个标志控制永久会话如何刷新'MAX_CONTENT_LENGTH': None,  # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码'SEND_FILE_MAX_AGE_DEFAULT': 12,  # hours 默认缓存控制的最大期限'TRAP_BAD_REQUEST_ERRORS': False,# 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,# 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。'TRAP_HTTP_EXCEPTIONS': False,# Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。# 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。# 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。# 如果这个值被设置为 True ,你只会得到常规的回溯。'EXPLAIN_TEMPLATE_LOADING': False,'PREFERRED_URL_SCHEME': 'http',  # 生成URL的时候如果没有可用的 URL 模式话将使用这个值'JSON_AS_ASCII': True,# 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,# Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。# 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。'JSON_SORT_KEYS': True,#默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。# 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。# 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。'JSONIFY_PRETTYPRINT_REGULAR': True,'JSONIFY_MIMETYPE': 'application/json','TEMPLATES_AUTO_RELOAD': None,
}
View Code

以上这些Key,都可以被改写,当然他们也都是有默认值存在的,如果没有特殊情况,不要改写它的默认值

修改配置的方式

修改配置的方式大约是两种

1.直接对app.config进行修改

app.config["DEBUG"] = True

2.使用类的方式导入

首先要有一个settings.py的文件

class FlaskSetting(object):DEBUG = True

 

然后我们在Flask的启动文件中就可以这么写

from flask import Flask
# 导入自定义配置文件的配置类
from settings import FlaskSettingapp = Flask(__name__)
# 应用配置类
app.config.from_object(FlaskSetting)if __name__ == '__main__':app.run()
View Code

这叫做类导入配置

实例化配置

这是针对一个已经实例化的app进行的配置

那么在Flask实例化的时候,传递的参数是什么鬼呢?

其实可以理解为对Flask实例进行的初始配置,这里面的参数是非常好理解,注意关键字是非常非常非常好理解

static_folder = 'static',  # 静态文件目录的路径 默认当前项目中的static目录
static_host = None,  # 远程静态文件所用的Host地址,默认为空
static_url_path = None,  # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
# host_matching是否开启host主机位匹配,是要与static_host一起使用,如果配置了static_host, 则必须赋值为True
# 这里要说明一下,@app.route("/",host="localhost:5000") 就必须要这样写
# host="localhost:5000" 如果主机头不是 localhost:5000 则无法通过当前的路由
host_matching = False,  # 如果不是特别需要的话,慎用,否则所有的route 都需要host=""的参数
subdomain_matching = False,  # 理论上来说是用来限制SERVER_NAME子域名的,但是目前还没有感觉出来区别在哪里
template_folder = 'templates'  # template模板目录, 默认当前项目中的 templates 目录
instance_path = None,  # 指向另一个Flask实例的路径
instance_relative_config = False  # 是否加载另一个实例的配置
root_path = None  # 主模块所在的目录的绝对路径,默认项目目录
View Code

这里面,我们常用的参数有

static_folder = 'static',  # 静态文件目录的路径 默认当前项目中的static目录
static_url_path = None,  # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
template_folder = 'templates'  # template模板目录, 默认当前项目中的 templates 目录

记住这些就好了,一般的项目中,只修改这些参数

 

template_folder 

昨天已经讲到了template_folder,它是用来指定模板目录的,默认是templates

注意:如果设置template_folder = 'templates',这里面的templates它是相对路径!

假设py文件和templates不在同一目录下,比如这样:

./
├── bin
│   └── start.py
└── templates└── home.html

那么start.py使用模板时,应该这么设置  template_folder = '../templates'

完整代码如下:

from flask import Flask,render_templateapp = Flask(__name__,template_folder="../templates")@app.route("/")
def index():return render_template("home.html")if __name__ == '__main__':app.run()
View Code

 

如果找不到模板文件,会提示

 

static_folder

静态文件目录的路径 默认当前项目中的static目录

目录结构如下:

./
├── bin
│   └── start.py
├── static
│   └── meizi.jpg
└── templates└── home.html

 

start.py

from flask import Flask,render_templateapp = Flask(__name__,template_folder="../templates",static_folder="../static")@app.route("/")
def index():return render_template("home.html")if __name__ == '__main__':app.run()
View Code

home.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h3>古装美女</h3>
<img src="/static/meizi.jpg" alt="">
</body>
</html>
View Code

meizi.jpg 这是一个妹子图片,自己百度搜索一下

 

重启flask程序,效果如下:

查看网络,图片的实际路径是:

http://127.0.0.1:5000/static/meizi.jpg

 

static_url_path

静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用

怎么知道static_url_path和static_folder默认同名呢?

修改start.py,打印变量

from flask import Flask,render_templateapp = Flask(__name__,template_folder="../templates",static_folder="../static")@app.route("/")
def index():print(app.static_folder)print(app.static_url_path)return render_template("home.html")if __name__ == '__main__':app.run()
View Code

刷新页面,查看Pycharm控制台输出:

/static
/static

这2个确实是一样的!

 

static_url_path变量是可以修改的,但是和前端保持一致

修改start.py

from flask import Flask,render_templateapp = Flask(__name__,template_folder="../templates",static_folder="../static",static_url_path="/app")@app.route("/")
def index():print(app.static_folder)print(app.static_url_path)return render_template("home.html")if __name__ == '__main__':app.run()
View Code

修改home.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h3>古装美女</h3>
<img src="/app/meizi.jpg" alt="">
</body>
</html>
View Code

重启flask,刷新页面,效果同上!

 

注意:如果使用蓝图,并做了代码拆分。静态目录名不能是static,模板目录不能是templates。必须改名!!!

必须指定3个参数

template_folder="../templates",static_folder="../statics",static_url_path="/statics" 

否则会出现,模板无法渲染。css访问出现404的问题!

视图渲染时,使用

return render_template("index.html")

模板引用css时,使用

<link rel="stylesheet" href="/statics/bootstrap.min.css">

 

本文参考:

https://www.cnblogs.com/DragonFire/p/9260299.html

三、蓝图(BluePrint)

什么是蓝图

Flask中提供了蓝图,专门用作Flask的模块化。对于蓝图,可以看官方介绍,这里翻译过来的:

Flask使用蓝图的概念来制作应用程序组件和支持应用程序内部或跨应用程序的通用模式。蓝图可以大大简化大型应用程序的工作方式,并为Flask扩展提供了在应用程序上注册操作的中心手段。Blueprint对象的工作方式与Flask应用程序对象类似,但实际上它不是一个应用程序。相反,它是如何构造或扩展应用程序的蓝图。

总之,蓝图可以使我们的程序更加模块化,不同功能的路由可以放在不同的模块下,最后集中到启动类中

 

蓝图,听起来就是一个很宏伟的东西

在Flask中的蓝图 blueprint 也是非常宏伟的

它的作用就是将 功能 与 主服务 分开怎么理解呢?

比如说,你有一个客户管理系统,最开始的时候,只有一个查看客户列表的功能,后来你又加入了一个添加客户的功能(add_user)模块, 然后又加入了一个删除客户的功能(del_user)模块,然后又加入了一个修改客户的功能(up_user)模块,在这个系统中,就可以将

查看客户,修改客户,添加客户,删除客户的四个功能做成蓝图加入到客户管理系统中,本篇最后会做一个这样的例子,但是首先我们要搞清楚什么是蓝图 blueprint

初识Flask蓝图

1.初识Flask蓝图(blueprint)

创建一个项目然后将目录结构做成:

./
├── manager.py
└── student_view└── s_view.py

注意:要手动创建目录student_view,并在此目录下创建s_view.py

 

s_view.py

from flask import Blueprint  # 导入 Flask 中的蓝图 Blueprint 模块

sv = Blueprint("sv", __name__)  # 实例化一个蓝图(Blueprint)对象
@sv.route("/svlist")  # 这里添加路由和视图函数的时候与在Flask对象中添加是一样的
def view_list():return "svlist_view_list"
View Code

 

manager.py

from flask import Flask# 导入此前写好的蓝图模块
from student_view import s_viewapp = Flask(__name__)  # type:Flask# 在Flask对象中注册蓝图模块中的蓝图对象 s_view 中的 sv
app.register_blueprint(s_view.sv)if __name__ == '__main__':app.run("0.0.0.0",5000)# 现在Flask对象中并没有写任何的路由和视图函数
View Code

开启服务,然后访问 http://127.0.0.1:5000/svlist 查看结果

 

很明显,我们没有在Flask对象中添加路由,但是我们注册了有路由和视图函数的sv蓝图对象

理解蓝图

2.如何理解蓝图呢?

其实我们可以理解成一个没有run方法的Flask对象,这个理论虽然有很多的漏洞,但是对于刚接触蓝图的你来说,就这么样理解,没有错

下面来看一下,在实例化蓝图的时候可以传递的参数都有什么,你就能完全理解了

目录结构:

./
├── manager.py
├── student_view
│   └── s_view.py
├── sv_static
│   └── meizi.jpg
└── sv_template└── svlist.html

 

s_view.py

from flask import Blueprint  # 导入 Flask 中的蓝图 Blueprint 模块
from flask import render_templatesv = Blueprint("sv",__name__,# 这里是相对路径,要加../template_folder="../sv_template",  # 每个蓝图都可以为自己独立出一套template模板文件夹,如果不写则共享项目目录中的templatesstatic_folder="../sv_static"  # 静态文件目录也是可以独立出来的)  # 实例化一个蓝图(Blueprint)对象
@sv.route("/svlist")
def view_list():return render_template("svlist.html")
View Code

 

svlist.html 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>Hello ! I am sv_template</p><img src="/sv_static/meizi.jpg">
</body>
</html>
View Code

manager.py的代码,不需要改动。

重启flask,刷新页面:

妹子,还是那个妹子

 

从这个例子中我们总结出:

Blueprint 其实可以理解为一个了没有run方法的 Flask 对象

只要Blueprint被 Flask 注册了,就一定会生效

坑来了!坑来了!

蓝图内部的视图函数及route不要出现重复,否则~你们自己试试吧

 

增删改查用户

3.使用蓝图,做一个增删改查用户

要有一个文件存放我们的原始数据

student_data.py 文件中的内容:

STUDENT = [{'id':1,'name': '韩雪', 'age': 24, 'gender': ''},{'id':2,'name': '舒畅', 'age': 23, 'gender': ''},{'id':3,'name': '唐嫣', 'age': 25, 'gender': ''}
]

然后我们根据以上内容进行增删改查

web应用搭建

3.1 使用蓝图进行web应用搭建:

目录结构如下:

./
├── manager.py
├── student
│   └── __init__.py
└── student_data.py

__init__.py 文件中的内容:

from flask import Flaskdef create_app():app = Flask(__name__)return app
View Code

这个文件我们会修改函数 create_app中的代码

 

manager.py 文件中的内容

from student import create_appflask_app = create_app()if __name__ == '__main__':flask_app.run("0.0.0.0",5000,debug=True)
View Code

通过这种方式启动 Flask 程序

查看学生信息

3.2 使用Flask蓝图,查看学生信息

项目结构如下:

./
├── html
│   └── s_list.html
├── manager.py
├── student
│   └── __init__.py
├── student_data.py
└── student_select└── stu_select.py

s_list.html 文件中的内容:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>学生列表</title>
</head>
<body>
<table border="3xp"><thead><tr><td>ID</td><td>name</td><td>age</td><td>gender</td><td>options</td></tr></thead><tbody>{% for foo in student %}<tr><td>{{ foo.id }}</td><td>{{ foo["name"] }}</td><td>{{ foo.get("age") }}</td><td>{{ foo.gender }}</td><td><a href="/s_update/{{ foo.id }}">修改</a> | <a href="/s_del?id={{ foo.id }}">删除</a></td></tr>{% endfor %}</tbody>
</table>
<a href="/s_add"> 添加学生 </a>
</body>
</html>
View Code

 

stu_select.py 文件中的内容:

from flask import Blueprint
from flask import render_template
from student_data import STUDENTss_blueprint = Blueprint("ss_b", __name__, template_folder="../html")@ss_blueprint.route("/s_list")
def s_list():return render_template("s_list.html", student=STUDENT)
View Code

 

student/__init__.py 文件中的内容:

from flask import Flask
from student_select import stu_selectdef create_app():app = Flask(__name__)app.register_blueprint(stu_select.ss_blueprint)return app
View Code

 

赶紧运行一下manager.py 来访问一下,我们的成果

 

什么链接都不要点,因为点啥都不好使,之后咱们一个一个的做

添加一个学生

3.3. 使用Flask蓝图,添加一个学生

增加一个目录,结构如下:

./
├── html
│   ├── s_add.html
│   └── s_list.html
├── manager.py
├── student
│   └── __init__.py
├── student_add
│   └── stu_add.py
├── student_data.py
└── student_select└── stu_select.py

 

s_add.html 文件中的内容

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>学生列表</title>
</head>
<body>
<form method="post">ID:<input type="text" name="id"> <br>姓名:<input type="text" name="name"><br>年龄:<input type="text" name="age"><br>性别:<input type="text" name="gender"><br><input type="submit" value="添加学生">
</form></body>
</html>
View Code

 

stu_add.py 文件中的内容

from flask import Blueprint
from flask import redirect
from flask import request
from flask import render_template
from student_data import STUDENTs_add = Blueprint("s_add", __name__, template_folder="html", static_folder="static")  # type:Blueprint
@s_add.route("/s_add", methods=["GET", "POST"])
def s_add_view():if request.method == "POST":stu_dic = {"id": request.form["id"],"name": request.form["name"],"age": request.form["age"],"gender": request.form["gender"]}STUDENT.append(stu_dic)return redirect("/s_list")return render_template("s_add.html")
View Code

 

这里面我们让他添加完一个学生,就返回到s_list查看学生列表

student/__init__.py 文件中的内容

from flask import Flask
from student_select import stu_select
from student_add import stu_adddef create_app():app = Flask(__name__)app.register_blueprint(stu_select.ss_blueprint)app.register_blueprint(stu_add.s_add)return app
View Code

 

重启flask服务,点击添加学生

 

如果你要是重新启动服务了,那么你刚刚添加的学生信息就没有了

添加完成之后

 

添加学生的Blueprint已经做完了

修改学生信息

3.4. 使用Flask蓝图,修改学生信息

增加一个目录,结构如下:

./
├── html
│   ├── s_add.html
│   ├── s_list.html
│   └── s_update.html
├── manager.py
├── student
│   └── __init__.py
├── student_add
│   └── stu_add.py
├── student_data.py
├── student_select
│   └── stu_select.py
└── student_update└── stu_update.py

 

s_update.html 文件中的内容:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>学生列表</title>
</head>
<body>
<form method="post"><input type="text" name="id" hidden value="{{ student.id }}"><br>姓名:<input type="text" name="name" value="{{ student.name }}"><br>年龄:<input type="text" name="age" value="{{ student.age }}"><br>性别:<input type="text" name="gender" value="{{ student.gender }}"><br><input type="submit" value="修改信息">
</form></body>
</html>
View Code

 

stu_update.py 文件中的内容:

from flask import Blueprint
from flask import render_template
from flask import redirect
from flask import request
from student_data import STUDENTs_update = Blueprint("s_update", __name__, template_folder="html", static_folder="static")@s_update.route("/s_update/<int:nid>",methods=["GET","POST"])
def s_update_view(nid):if request.method == "POST":stu_id = int(request.form["id"])stu_dic = {"id": stu_id,"name": request.form["name"],"age": request.form["age"],"gender": request.form["gender"]}for index,stu in enumerate(STUDENT):if stu["id"] == stu_id:STUDENT[index] = stu_dicreturn redirect("/s_list")for stu in STUDENT:if stu["id"] == nid :return render_template("s_update.html", student=stu)return render_template("s_update.html", student="")
View Code

 

student/__init__.py 文件中的内容:

from flask import Flask
from student_select import stu_select
from student_add import stu_add
from student_update import stu_updatedef create_app():app = Flask(__name__)  # type:Flask
app.register_blueprint(stu_select.ss_blueprint)app.register_blueprint(stu_add.s_add)app.register_blueprint(stu_update.s_update)return app
View Code

 

重启flask,刷新网页。点击一条记录,并修改

 

修改年龄

 点击修改信息,效果如下:

 

 

修改的功能也已经做完了,删除功能也是一样的。

 

删除学生

3.4. 使用Flask蓝图,删除学生信息

增加一个目录,结构如下:

./
├── html
│   ├── s_add.html
│   ├── s_list.html
│   └── s_update.html
├── manager.py
├── student
│   └── __init__.py
├── student_add
│   └── stu_add.py
├── student_data.py
├── student_delete
│   └── stu_delete.py
├── student_select
│   └── stu_select.py
└── student_update└── stu_update.py

注意:删除不需要html文件

 

修改s_list.html,这里的删除链接有问题

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>学生列表</title>
</head>
<body>
<table border="3xp"><thead><tr><td>ID</td><td>name</td><td>age</td><td>gender</td><td>options</td></tr></thead><tbody>{% for foo in student %}<tr><td>{{ foo.id }}</td><td>{{ foo["name"] }}</td><td>{{ foo.get("age") }}</td><td>{{ foo.gender }}</td><td><a href="/s_update/{{ foo.id }}">修改</a> | <a href="/s_delete/{{ foo.id }}">删除</a></td></tr>{% endfor %}</tbody>
</table>
<a href="/s_add"> 添加学生 </a>
</body>
</html>
View Code

 

stu_delete.py 文件中的内容:

from flask import Blueprint
from flask import render_template
from flask import redirect
from flask import request
from student_data import STUDENTs_delete = Blueprint("s_delete", __name__, template_folder="html", static_folder="static")@s_delete.route("/s_delete/<int:nid>",methods=["GET","POST"])
def s_delete_view(nid):for stu in STUDENT:if stu["id"] == nid :STUDENT.remove(stu)  # 列表移除keyreturn redirect("/s_list")return redirect("/s_list")
View Code

 

student/__init__.py 文件中的内容,注册蓝图

from flask import Flask
from student_select import stu_select
from student_add import stu_add
from student_update import stu_update
from student_delete import stu_deletedef create_app():app = Flask(__name__)app.register_blueprint(stu_select.ss_blueprint)app.register_blueprint(stu_add.s_add)app.register_blueprint(stu_update.s_update)app.register_blueprint(stu_delete.s_delete)return app
View Code

 

重启flask,测试效果:

 

增删改查,功能全部完结了!各位看官,有时间的话,可以使用pymysql实现!

建表以及插入数据

# 创建数据库
CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) DEFAULT NULL COMMENT '用户名',`age` int(11) DEFAULT NULL COMMENT '年龄',`gender` enum('','') DEFAULT '' COMMENT '性别',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;# 插入3条数据
INSERT INTO `student` (`id`, `name`, `age`, `gender`) VALUES ('1', '韩雪', '24', '');
INSERT INTO `student` (`id`, `name`, `age`, `gender`) VALUES ('2', '舒畅', '23', '');
INSERT INTO `student` (`id`, `name`, `age`, `gender`) VALUES ('3', '唐嫣', '25', '');
View Code

 

完整代码,请参考:

链接:https://pan.baidu.com/s/1wOOM2xk6YDZRo5HljgszpQ 密码:viel

 

本文参考:

https://www.cnblogs.com/DragonFire/p/9264381.html

四、before_request after_request

Flask我们已经学习很多基础知识了,现在有一个问题

我们现在有一个 Flask 程序其中有3个路由和视图函数,如下:

from flask import Flaskapp = Flask(__name__)@app.route("/login")
def login():return "Login"@app.route("/index")
def index():return "Index"@app.route("/home")
def home():return "Home"if __name__ == '__main__':app.run("0.0.0.0", 5000)
View Code

启动flask,访问home页面

 

现在要求是,如果登陆了,就可以访问 index 和 home 页面,如果没登录就跳转到 login 登录

要怎么解决呢, session 对, 用 session 除了 Login 函数之外的所有函数里面全校验 session 是否登录了

太麻烦了,现在咱们只有3个函数,如果成百上千个怎么整啊

 

装饰器,对没错,装饰器是一个很好的方案,但是啊,我现在还是成败上千个函数,我要在每一个函数定义的时候加上@装饰器,还是很麻烦

那么就引出了我们要学习的第一个知识点:

@app.before_request

from flask import Flask,request,redirect,sessionapp = Flask(__name__)
app.secret_key = "DragonFire"@app.before_request
def is_login():  # 判断是否登录# 白名单设置,判断为登录页面时if request.path == "/login":# 跳过处理return None# 判断session是不存在时if not session.get("user"):# 重定向到登录页面return redirect("/login")@app.route("/login")
def login():return "Login"@app.route("/index")
def index():return "Index"@app.route("/home")
def home():return "Home"if __name__ == '__main__':app.run("0.0.0.0", 5000)
View Code

@app.before_request 也是一个装饰器,他所装饰的函数,都会在请求进入视图函数之前执行

request.path 是来读取当前的url地址如果是 /login 就允许直接通过 return None 你可以理解成通过放行

校验session中是否有user 如果没有的话,证明没有登录,所以毫不留情的 redirect("/login") 跳转登录页面

还有一个要提的 @app.before_first_request 它与 @app.before_request 极为相似或者说是一模一样,只不过它只会被执行一次

 

@app.before_request修饰器在开发中用处非常大,比如判断某个ip是否有恶意访问行为,从而进行拦截等操作

 

重启flask,再次访问home页面,效果如下:

打开浏览器工具,查看网络

 

@app.after_request 

 2. @app.after_request 在响应(response)之前做出响应

from flask import Flask,request,redirect,sessionapp = Flask(__name__)
app.secret_key = "DragonFire"@app.before_request
def is_login():  # 判断是否登录# 白名单设置,判断为登录页面时if request.path == "/login":# 跳过处理return None# 判断session是不存在时if not session.get("user"):# 重定向到登录页面return redirect("/login")@app.after_request
def foot_log(environ):  # 记录访问日志print(environ)  # 响应信息# 判断请求路径不是登录页面if request.path != "/login":# 打印访问路径print("有客人访问了",request.path)return environ@app.route("/login",methods=["POST","GET"])
def login():if request.method == "GET":return "Login"user = request.form["username"]  # form表单获取pwd = request.form["password"]  # form表单获取# 判断form表示数据和 后台数据库匹配# models.UserInfo.objects.filter(username=user,password=pwd).first()if user == 'xiao' and pwd == '123':# 设置sessionsession["user"] = user# 跳转首页return redirect("/index")@app.route("/index")
def index():return "Index"@app.route("/home")
def home():return "Home"if __name__ == '__main__':app.run("0.0.0.0", 5000)
View Code

 

@app.after_request修饰器是在用户请求得到函数响应后被执行,不过需要注意的是这个执行是在函数返回数据前被调用,即请求已经被app.route修饰的函数响应过了,已经形成了response,但还未返回给用户的时候,调用的。

它可以做访问统计,很少应用,但是要了解有这么个东西

 

重启flask,访问home页面,效果同上!它还是会跳转到登录页面

查看Pycharm控制台输出:

<Response 219 bytes [302 FOUND]>
有客人访问了 /home

 使用postman发送post请求

点击发送,查看返回结果

从上图可以看出,验证通过了!跳转到首页

 

可能有人会有疑问,咦?@app.before_request不是装饰器吗?为什么没有在home视图函数中应用,却生效了呢?
应该这样才对啊

@app.route("/home")
@app.before_request
def home():return "Home"

NoNoNo!@app.before_request是一个全局装饰器,它是针对所有视图函数的。只要定义了@app.before_request,那么每一个视图函数都会应用。同理,@app.after_request也是全局装饰器!

你可以把@app.before_request理解为django的中间件,请求到达视图函数之前,先走中间件!

 

如果还是不明白,看下面的流程图

流程图

解释:

is_login()函数被@app.before_request修饰以后,每一次请求到来后,都会先进入函数is_login()中,如上代码,获取请求的路径以及session。如果是登录页面,不处理。如果session中user不存在,跳转到登录页面。当session中user存在时,请求才会正常进入到app.route修饰的函数中响应,如果有多个函数被@app.before_request修饰了,那么这些函数会被依次执行。


比如这样:

@app.before_requestdef malicious_ip(): # 判断恶意IPpass@app.before_requestdef xss(): # 判断xss攻击pass@app.before_requestdef is_login(): # 判断登录pass

@app.before_request修饰器在开发中用处非常大,比如判断某个ip是否有恶意访问行为,从而进行拦截等操作。


此外同理,app.after_request修饰器是在用户请求得到函数响应后被执行,不过需要注意的是这个执行是在函数返回数据前被调用,即请求已经被app.route修饰的函数响应过了,已经形成了response,但还未返回给用户的时候,调用的。

 

本文参考:

https://www.cnblogs.com/DragonFire/p/9269303.html

 

今日总结:

1.flask路由endpoint 反向url标签 url_for 通过endpoint反向生成urlmethods=[] 允许进入视图函数的请求方式,默认GETstrict_slashes 是否严格要求URL地址 /login/ /loginredirect_to 跳转地址,重定向地址动态URL参数 /index/1 /index/<int:id>  def index(id)2.Flask实例化配置template_folder 指定模板路径static_folder 指定静态文件路径static_url_path 静态文件路径访问url3.app对象配置:app.config.from_object(Class)DEBUG # 开启代码调试模式(开发)SECRET_KEY # 用到session时必须添加4.蓝图:Blueprint 相当于是一个不能够被run的flask对象Blueprint("blue",__name__,template_folder,static_folder,static_url_path)可以为蓝图增加独立的模板和静态目录为蓝图增加路由让flask实例 注册蓝图 register_blueprint(蓝图)功能和主程序分离,注册5. send_file jsonifysend_file() # 打开文件并返回,并加入返回头jsonify # 将字典json后,加入返回头applction/json6.特殊装饰器:before_request: 请求进入视图函数之前执行after_request: 响应返回前端之前执行errorhandler(404): 错误响应before_first_request: 第一次访问时,请求进入视图函数之前执行be1 - be2 - af2 - af1be1 - af2 - af17.闪现 flash:flash("内容","标签")get_flashed_messages()get_flashed_messages(category_filter=["标签"])
View Code

 

posted @ 2018-09-06 15:28 肖祥 阅读(...) 评论(...) 编辑 收藏
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. csdn的程序员们,大家佛系一点不好吗?何必剑拔弩张?

    csdn的网友们,大家佛系一点不好吗?说句实话,其实不太想写这篇文章,想着csdn的网友都是大人了,很多都是几十岁的人了,大家的文化涵养、素质应该普遍都比较高才对,但是还是不乏一些喷子和酸子,有小部分网友喜欢留言的时候,带脏字骂人,动不动就他妈的,动不动就是个逼什…...

    2024/4/17 15:33:31
  2. 学生管理系统的示意图

    ...

    2024/4/17 15:32:56
  3. 解决IIS存储空间不足的问题

    一、症状: 浏览器出现400错误 进入浏览器选项中,把友好去掉,则出现BadRequest(InvalidHostname),以为是dns解析错误,ping通过,并且指向正确。 检查应用程序池发现应用程序池停止,尝试启动,出现“存储空间不足”的提示。 经过一番处理,终于解决了“IIS无法启动:存储空间…...

    2024/3/31 19:06:11
  4. jQuery Wookmark-2 jQuery动态表格插件的效果展示

    之前在博客中写过一篇有关于Wookmark的文章,只能算是一个简单的介绍,至于它内部真正的用法和效果的展示,并没有具体的写出来,今天简单将其用法和效果的一些展示在这篇博客中介绍下,如果你想简单看下以前有关于Wookmark的介绍的话,可以访问地址:http://blog.csdn.net/sun…...

    2024/4/18 5:20:43
  5. easyui datagrid 单击事件和双击事件

    要在easyui datagrid 上实现单击和双击事件,使用easyui datagrid 自带的属性onClickRow和onDblClickRow ,比如:$(function(){ $(#tableId).datagrid({//单击事件 onClickRow:function(rowIndex,rowData){ alert("单击");}//双击事件onDblClickRow :function(ro…...

    2024/4/11 17:04:05
  6. 对 Flask 蓝图(Blueprint)的理解

    一、蓝图的定义 蓝图 /Blueprint 是 Flask 应用程序组件化的方法,可以在一个应用内或跨越多个项目共用蓝图。 使用蓝图可以极大地简化大型应用的开发难度,也为 Flask 扩展 提供了一种在应用中注册服务的集中 式机制。 二、蓝图的应用场景把一个应用分解为一个蓝图的集合。这对…...

    2024/4/17 15:33:44
  7. “办公室内部斗争”经验和原则

    (1)要坚定不移的把“骂人”之道进行到底在我曾经工作过的几个地方,所留给同事们的印象,我都属于一个没涵养的人,因为我经常骂人,不过我骂人鲜少带脏字,这对被骂的人而言,会更令其难受,因为骂人带脏字,对现在皮糙肉厚的芸芸众生来说,已基本上失去了对心灵的打击作用。 …...

    2024/4/17 15:33:19
  8. IIS 根本就没有启动

    今天开机,发现 http://localhost 无法访问了。昨天还是好好的。奇怪。 进入 IIS 中查看,一个红色的“Error”映入眼睑,原来 IIS 根本就没有启动。点击“启动”N次,都失败,提示如下:IIS 无法启动 发生意外错误 8ffe2740 纳闷。进入“事件查看器”,在“系统”中,发现 w3s…...

    2024/4/17 15:33:28
  9. UE4学习笔记:学习UE4中的UMG(图形UI设计器)工具(一): Widget Blueprint控件蓝图

    虚幻动态图形UI设计器(UMG)是一款视觉UI创造工具,可帮助设计者将想要呈现的游戏内的HUD,菜单或与界面相关的其他图形呈现给用户,UMG核心基于控件,在专门的控件蓝图中,也就是Widget Blueprint中对控件进行编辑以及实现功能。 一. Widget Blueprint Widget Blueprint控件蓝图…...

    2024/4/17 15:33:14
  10. Bootstrap Table数据表格的使用指南

    Bootstrap-Table:在业务系统开发中,对表格记录的查询、分页、排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,Bootstrap-Table是一款非常好用的开源表格插件,在很多项目中广泛的应用。Bootstrap-Table插件提供了非常…...

    2024/4/17 15:33:50
  11. Asp.net 无法启动IIS Express 解决办法

    问题描述: Asp.net项目 , IIS Express 无法启动。项目拷贝给同事后,点击运行,浏览器显示网页无法访问。可能原因:一 、其他项目都可以,就这么一个不行 二、Git 冲突引起 三、安装Visual Sutudil 2015 Update 3后调试项目出现问题“无法启动iis express web 服务器” 四、…...

    2024/4/17 15:34:31
  12. 武林秘籍――《骂人宝典》

    武林秘籍――《骂人宝典》 2012年01月12日    我们都是文明人,不要随便骂人,更不能象泼妇一样,叉着腰,一嘴脏话。但是有些人不骂不行。怎么办?请看骂人的最高境界:骂人不带脏字。   你是    进化不完全的生命体,基因突变的外星人,    幼稚园程度的高中生…...

    2024/4/14 17:27:27
  13. Blueprint入门之一

    Blueprint是OSGI的一个规范,它来源于spring dm.目前主要有aries和gemini两套实现,本文以aries的实现为基础。大致来说Blueprint是一个OSGI的IOC规范。对于熟悉spring的朋友来说,应该会十分容易上手。 Blueprint也是以xml文档来构建应用,但它也有采用Annotation的方式,我们在…...

    2024/4/17 15:34:44
  14. js事件小结(一般事件)

    (一)事件 浏览器支持 描述onClick HTML: 2|3|3.2|4Browser: IE3|N2|O3 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击onDblClick HTML: 2|3|3.2|4Browser:IE4|N4|O 鼠标双击事件onMouseDown HTML: 2|3|3.2|4Browser:IE4|N4|O 鼠标上的按钮被按…...

    2024/4/17 15:33:19
  15. C语言_学生信息管理系统项目心得

    标题@## C语言_学生信息管理系统项目(文件版)心得 简介:初步实现学生信息的增删改查功能,并将对学生数据的操作结果同步到txt文档。先上一波图看效果:修改学生信息界面思路: 先实现控制台部分的增删改查功能代码,然后在次基础上添加关联文件读写模块代码。 通过字符串及…...

    2024/4/17 15:34:31
  16. IIS 部署网站无法正常加载资源文件问题

    解决IIS网站部署无法加载资源文件(css、js、图片文件),如下图:勾选 >静态内容<选项...

    2024/4/18 16:29:26
  17. jqgrid 表格插件 设置点击当前行,不默认勾选checkbox

    1、jqgrid 设置点击当前行,不默认勾选checkbox。 beforeSelectRow: function (rowid, e) {var $myGrid = $(this),i = $.jgrid.getCellIndex($(e.target).closest(td)[0]),cm = $myGrid.jqGrid(getGridParam, colModel);return (cm[i].name === cb); }...

    2024/4/17 15:34:43
  18. 经典的损人的话  (不带一个脏字,够狠毒)

    你这个进化不完全的生命体  基因突变的外星人  幼稚园程度的高中生  先天蒙古症的青蛙头圣母峰雪人的弃婴      化粪池堵塞的凶手  非洲人搞上黑猪的后裔  阴阳失调的黑猩猩被诺亚方舟压过的河马    新火山喷发口    超大无耻传声扩音喇叭  爱斯基摩…...

    2024/4/17 15:33:32
  19. JQuery------鼠标双击时,不选中div里面的文字

    如图:(去掉选中文字的蓝色背景色)代码://方法一:<div class="test" onselectstart="return false" >文字</div> //方法二: .test{-moz-user-select:none;-webkit-user-select: none; -ms-user-select: none; }...

    2024/4/17 15:34:19
  20. 骂人不带脏字的80后

    A、巴黎圣母院少个敲钟的,就你了。 B、思想有多远,你就滚多远;光速有多快,你就滚多快。 C、你一出门,千山鸟飞绝,万径人踪灭。 D、你哪家学校毕业的啊?你讨人厌的学位都修到博士后了!! E、想咬你一口,可惜我是回民。 F、天下之大,大不过你缺的那块心眼。 G、你出生时…...

    2024/4/18 20:40:15

最新文章

  1. Java入门(JDK安装)

    安装 JDK 下载 Java Downloads | Oracle 安装 下一步直接安装安装过程中&#xff0c;需要确定自己的安装位置 参考&#xff1a;D:\Java\jdk1.8.0_281_x64 演示位置 校验 终端输入 java -version 配置 1&#xff09;删除默认 javapath 默认情况下&#xff0c;可以在cm…...

    2024/4/19 7:43:29
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 如何转行成为产品经理?

    转行NPDP也是很合适的一条发展路径&#xff0c;之后从事新产品开发相关工作~ 一、什么是NPDP&#xff1f; NPDP 是产品经理国际资格认证&#xff0c;美国产品开发与管理协会&#xff08;PDMA&#xff09;发起的&#xff0c;是目前国际公认的唯一的新产品开发专业认证&#xff…...

    2024/4/18 6:17:26
  4. JavaEE 初阶篇-生产者与消费者模型(线程通信)

    &#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 生产者与消费者模型概述 2.0 在生产者与消费者模型中涉及的关键概念 2.1 缓冲区 2.2 生产者 2.3 消费者 2.4 同步机制 2.5 线程间通信 3.0 实现生产者与消费者模…...

    2024/4/17 10:28:59
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/18 0:33:31
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/18 22:36:36
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/18 9:45:31
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/17 2:33:17
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/17 7:50:46
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/18 3:56:01
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/18 3:56:04
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/18 3:55:30
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/18 3:55:54
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/18 3:55:45
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/17 21:50:30
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/15 13:53:08
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/15 9:16:52
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/18 9:24:29
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/18 3:56:18
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/18 3:55:57
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/18 3:55:50
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/15 23:28:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/18 3:56:20
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/18 3:56:11
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57