flask2

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:/int:/int:/')

​ print(page,page1,page2) #传参 (必须是定长的传三个)

​ route('details/int:/')

​ route('details/string:/') 什么都不写 默认string

​ #通过路由地址访问文件

​ /s1.py url地址

​ def detail(folder,filename) #folder 跨目录

​ #写url /template/xx.html(前面是。。/后面对应)

​ fp=os.path.join(folder,filename)

​ return send_file()

2 .Flask中的配置

  1. 初始化配置
    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 可以阻拦域名 子域名(替代分发)上两个
    
    
  2. 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
posted @ 2019-07-11 12:38  learnacode  阅读(415)  评论(0编辑  收藏  举报