flask2 & get方法
-1 装饰器
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 ....
-1.1 不同的函数用装饰器,抛出异常
error: function mapping is overwriting an existing endpoint function :inner
源码: 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) #利用偏函数的原理
为多个视图函数增加同一个装饰器
1 Flask 中的路由
参数:
endpoint 映射路由-视图函数_name_ = ''(字符串)
@ endpoint='loginasdf'
def login():
print(url_for('loginasdf')) #login
methods = []/() #--> 集合set(xxx.lower )
#当前视图函数支持的请求方法 405 请求方式不被允许 defaults = {'id':1} #默认参数 一旦默认参数存在,视图函数必须有一个形参去接收,形参变量名必须与defaults中的一致
strict_salshes = False/True #是否严格遵循路由匹配(默认是true)
redirect_to = '/login' #308(环境问题301有时) 永久重定向 不经过视图函数的(不浪费那块空间) (老页面新页面)
动态参数路由
#分页
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()
2 .Flask中的配置
-
初始化配置
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'
名言
不要把时间浪费在路上 ----哪个名人
3 flask 蓝图
当成是 一个不能被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多个蓝图
4 . Flask 特殊装饰器
@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 errorhandler 重定向错误信息
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 : (时间密度?纠错) (解决不分先后,哪个有思路?)(缺点,珍惜)
1 改成大众型
把页面分开了
@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>
2 使用session验证登录状态 思考:如何记录登录次数
问题1 if session['count'] is None:
KeyError: 'count' #还没给他赋值,所以不能判断
解决方法 : if session.get('count') is None: # get方法取值,没有也不会报错
先设置 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 两个人的session值是一样的了?
3 装饰器
6 原理 ? : 解决方法: (1 加options)
4 user car 怎么写
cars.py 里写错了 ,改一下
user = Blueprint('car',__name__) --> car = Blueprint('car',__name__)
5 floder url why
7 after 什么意思?
8 笔记
9 css 样式
错误1 app.run('0.0.0.0:9000')
正确:
app.run('0.0.0.0',9000)
错误2 AttributeError: 'function' object has no attribute 'name'
好像是函数def get_login():
不能写成login 与 login的蓝图标识重名
jinja2.exceptions.TemplateNotFound: login.html
detail = Blueprint('detail',__name__,template_folder='templates',static_url_path='statics')
AttributeError: 'function' object has no attribute 'name'
def detail(): #重名了
错误3 ImportError: cannot import name 'STUDENT_DICT'
from zuoye import STUDENT_DICT