def war(func): def inner(*args,**kwargs): if session.get('username'): ret = func(*args,**kwargs) return ret return inner
@app.route('/detail') @war #执行inner --> func() - return ret war(detail) --> inner def detail(): return ....
error: function mapping is overwriting an existing endpoint function :innercss
源码: def route(self,rule,**options) #第一个参数app /detail {} def decorator(f) : f = def details end = options.pop('end',None) #None 在代码 app.add_url_rule(rule,end,f,**options)# '/detail' None def detail {} #本质上是执行这句话 if end is None: end = _end_from_view_func(view_func) #里面 return view_func.__name__ #return 'details' #assert 断言 view_func.__name__ is not None options['end'] = end #{} --> {'end':‘detail’} methods = options.pop('methods',None) #没有返回空 if methods is None: methods = getattr(view_func,'methods',None) or ('GET',) methods = set(item.upper() for item in methods) #集合去重 if view_func is not None: old_func = self.view_functions.get(end) #v_f 全部的视图函数 if old_fun is not None and old_func! = view_func: raise AssertionError() self.view_functions[end] = view_func #view_function = {'details':deatils} 2 新的op = {'methods' : ['GET','get','Get']} 带过去 if old_fun is not None and old_func! = view_func: # 老innner的内存地址和新inner的内存地址 detail 和 deatils 解决方法:(不会出现重名不一样函数的现象) 1 if end is None: end = option 给endpoints = 传参 不为None 2 from functools import wraps #返回原来的函数名 def war(func): #装饰器 @wraps(func) #利用偏函数的原理
为多个视图函数增长同一个装饰器html
参数:前端
endpoint 映射路由-视图函数__name__ = ''(字符串)nginx
@ endpoint='loginasdf' def login(): print(url_for('loginasdf')) #login
methods = []/() #--> 集合set(xxx.lower )数据库
#当前视图函数支持的请求方法 405 请求方式不被容许 defaults = {'id':1} #默认参数 一旦默认参数存在,视图函数必须有一个形参去接收,形参变量名必须与defaults中的一致django
strict_salshes = False/True #是否严格遵循路由匹配(默认是true)json
redirect_to = '/login' #308(环境问题301有时) 永久重定向 不通过视图函数的(不浪费那块空间) (老页面新页面)flask
动态参数路由缓存
#分页session
route('details/int:
print(page,page1,page2) #传参 (必须是定长的传三个)
route('details/int:
route('details/string:
#经过路由地址访问文件
/s1.py url地址
def detail(folder,filename) #folder 跨目录
#写url /template/xx.html(前面是。。/后面对应)
fp=os.path.join(folder,filename)
return send_file()
初始化配置
app = Flask(__name__,template_folder='templatess',static_folder='statics',static_url_path='/static') #存放路径 /开头:路由地址
static_folder='statics' #静态文件存放路径 static_url_path='/static' #静态文件访问路径 - 默认/ + folder static_host = None, #访问这,去另外一个主机去拿 host_matching=False, #定义的是ip/域名 只能按定义的匹配 subdomain_matching=False, #car子域名www主域名 nginx 能够阻拦域名 子域名(替代分发)上两个
config 对象配置
app.config['DEBUG'] = True
app.config #第三方组件 environment 都在这里
DEBUG --- 编码阶段
代码重启(大多数)日志输出级别很低(查错看到error:扔到数据库记上) (大量日志(银行)存到缓存(速度太快))
页面种会显示错误 错误代码(没testing,关了debug,自动开启testing)
TESTING --- 测试阶段 日志输出级别较高 不重启 无限接近线上环境
"SECRET_KEY": None, #不同 可能加连个md5 SECRET_KEY = hashlib.md5(b'12352344553').hexdigest() SERVER_NAME #至关于域名 SESSION_COOKIE_NAME SESSION_COOKIE_DOMAIN #在那个域名下配置 SESSION_COOKIE_PATH #在那个个环境 SESSION_COOKIE_HTTPONLY JSONIFY_MIMETYPE #本身作反爬 (随便改的话下载的)
make_config default_config {'ENV','DEBUG':(不能在这里改)} app.default_config #能够查询 忘了
<img src="/static/2.jpg"> # {#路由地址 不是静态文件访问的地址#} staic_floader = 'static'
app.config['TESTING'] = True
* Debug mode: off 127.0.0.1 - - [11/Jul/2019 11:01:01] "GET /statics/2.jpg HTTP/1.1" 404 -
运维开发都是你,测试也是你的话
那样,成长速度很快
app.config['JSONIFY_MIMETYPE'] = '2534ijij/isjiga' @app.route('/bab') def bab(): return {'k':1} #封装了 jsonify #会下载
from_object
for key in dir(obj): #把每一个变成字典 if key.isupper(): self[key] = getattr(obj, key) #slef = config ... config['DEBUG'] = True
config 写的 均可以序列化
s20 = 'NB'
SESSION_TYPE = 'Redis'
不要把时间浪费在路上 ----哪一个名人
当成是 一个不能被run的flask对象
做用:应用隔离,不用注销了
serv --
--users.py
from flask import Blueprint #不能被 run的 一个flask 蓝图惟一个标识 user = Blueprint('user',__name__) # template_folder = 'serv/user' # 均可以和flask对象差很少init封装 @user.route('/get_user',methods=['GET','post']) #大小写都行 def get_user(): return "I am Users Blueprint"
蓝图没有 run , 由于没有config(run 基于 config)
from flask import Flask from serv.users import user app = Flask(__name__) app.register_blueprint(user) #注册蓝图 if __name__ == '__main__': app.run()
蓝图是须要注册在app实例上的 app.register_blueprint(bp对象)
蓝图共享app.config
访问网页所有都登录
100多个蓝图
@app.before_request #请求进入视图函数以前 def be1(): print('be1') return None #return ‘出错了’ #be1 af2 af1 @app.before_request def be2(): print('be2') #return None return ‘出错了’
django是一个请求一个响应
@app.after_request def af1(res): print('af1') return res @app.after_request def af2(res): print('af2') return res
结果:
be1
be2
af2
af1
替代了session + 装饰器
部分的很差用
@user.before_request def look(): print('user1') return '棍' @user.after_request def look(res): print('user2') return res
be1 be2 user2 af2 af1
1 .before_request 请求进入视图函数以前进行处理 return None 继续执行不然阻断
2 .after_request 视图函数结束 响应客户端以前
正常周期 be1 2 3 - vf - af3 - af2 -af1
异常周期
3.1 有参数的装饰器errorhandle(监听错误状态码5xx 4xx int)
3.2 必须有一个形参接收 error_message
@app.errorhandler(404) #监听的端口在这 def error(error_message): print(error_message) # return '你要访问的页面不存在' #使404 页面好看点 # 蓝图也可使用 全局的 # return redirect('https://www.autohome.com.cn/beijing/adgasgsdg') return send_file('2.jpg') #能够打个广告
af : (时间密度?纠错) (解决不分前后,哪一个有思路?)(缺点,珍惜)
把页面分开了
@app.route('/detail') def detail(): if session['username']: session['count'] += 1 a = session['count'] #把session['count'] 赋值给a 而后传到前端 name = session['username'] print(request.args.get('id')) return render_template('zuoye1.html', stu_dict=STUDENT_DICT, time=a,name=name) else: return redirect('/login') @app.route('/xiangqing') def xiangqing(): if session['username']: name = session['username'] tag = request.args.get('id') tag = int(tag) return render_template('xiangqing.html', stu_dict=STUDENT_DICT, tag=tag , name=name) else: return redirect('/login')
两个html
zuoye.html
<table> <td>id</td> <td>name</td> <td>详情</td> {% for id in stu_dict %} <tr> <td>{{ id }}</td> <td>{{ stu_dict[id].name }}</td> <td><a href="/xiangqing?id={{ id }}">点击查看</a></td> </tr> {% endfor %} </table>
xiangqing.html
<table> <td>id</td> <td>name</td> <td>age</td> <td>gender</td> {% for id in stu_dict %} {% if tag == id %} <tr> <td>{{ id }}</td> <td>{{ stu_dict[id].name }}</td> <td>{{ stu_dict.get(id).get('age') }}</td> <td>{{ stu_dict.get(id).get('gender') }}</td> </tr> {% endif %} {% endfor %} </table>
KeyError: 'count' #还没给他赋值,因此不能判断
先设置 session['count'] =0 当login了以后,自动就是1了(每次登录都赋值为0,本身没想起来,听的老师的提醒)
if uname == '123' and pwd == '123': session['username'] = uname #if session['count'] is None: #区分第一次仍是第二次登陆 if session.get('count') is None: session['count'] = 0 return render_template('index.html',a=session['count']) elif uname == 'a23' and pwd == 'a23': if session.get('count') is None: session['count'] = 0 session['username'] = uname return render_template('index.html',) 登陆用到session的路由函数: if session['username']: session['count'] += 1 name = session['username'] return render_template('zuoye1.html', stu_dict=STUDENT_DICT,tag= tag ,time=session['count'] ,name=name) 用户{{ name }}第{{ time }}次session登陆
有session存值,即便推出了程序也会记录,默认31周,并且分别记录各个用户的登陆次数,很方便
错误写法: 逻辑不对, 两个if , 有了username就返回能够登陆其余的了,可是没有,因此要去从新登陆,可是登陆没有放行,没有return None ,只给了有了username,可是login没有,一直走login了 因此一直302重定向
# @app.before_request # def be1(): # # if session.get('username'): # # return None # if not session.get('username'): # return redirect("/login")
参考了老师的写法
@app.before_request def be1(): if request.path == "/login": #给login放行 return None if not session.get("username"): return redirect("/login") #别的默认放行 或者再加上 if session.get("username"): return None
3 装饰器
6 原理 ? : 解决方法: (1 加options)
cars.py 里写错了 ,改一下 user = Blueprint('car',__name__) --> car = Blueprint('car',__name__)
5 floder url why
7 after 什么意思?
8 笔记
9 css 样式
正确:
app.run('0.0.0.0',9000)
好像是函数def get_login():
不能写成login 与 login的蓝图标识重名
detail = Blueprint('detail',__name__,template_folder='templates',static_url_path='statics')
AttributeError: 'function' object has no attribute 'name'
def detail(): #重名了
from zuoye import STUDENT_DICT