Flask框架 之 学生管理分析
先看模板吧。
index.html
<body> <h1>学生列表</h1> <table border="1"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>选项</th> </tr> </thead> <tbody> {% for k,v in stu_dic.items() %} <tr> <td>{{k}}</td> <td>{{v.name }}</td> <td>{{v.age}}</td> <td>{{v.gender}}</td> <td> <a href="/detail/{{k}}">查看详细</a> | <a href="/delete/{{k}}">删除</a> </td> </tr> {% endfor %} </tbody> </table>
detail.html
<body> <h1>学生详细</h1> <ul> {% for item in info.values() %} <li>{{item}}</li> {% endfor %} </ul> </body>
app.py
from flask import Flask,render_template,request,redirect,session,url_for,jsonify,make_response,Markup,flash,get_flashed_messages app = Flask(__name__) STUDENT_DICT = { 1:{'name':'王龙泰','age':38,'gender':'中'}, 2:{'name':'小东北','age':73,'gender':'男'}, 3:{'name':'田硕','age':84,'gender':'男'}, }
我们如何对这些数据进行操作呢?
@app.route('/index') def index(): print('index') return render_template('index.html',stu_dic=STUDENT_DICT) @app.route('/delete/<int:nid>') #指定为Int,否则为str def delete(nid): del STUDENT_DICT[nid] return redirect(url_for('index')) @app.route('/detail/<int:nid>') def detail(nid): info = STUDENT_DICT[nid] return render_template('detail.html',info=info)
后台管理是随便可以看的吗?是不是应该先登录后进行操作呢?
@app.route('/login',methods=["GET","POST"]) def login(): print('login') if request.method == 'GET': return render_template('login.html') user = request.form.get('user') pwd = request.form.get('pwd') if user == 'oldboy' and pwd == '666': session['user'] = user #存入session return redirect('/index') return render_template('login.html',error='用户名或密码错误')
不要忘了存入session需要加盐。app.secret_key="xxxxx"
然后呢?
从session中取到随机字符串,判断是否登录。每个操作都要校验,每个函数都要加(以index为例)。
版本一:
@app.route('/index') def index(): if not session.get('user'): return redirect(url_for('login')) return render_template('index.html',stu_dic=STUDENT_DICT)
每个函数都要加,是不是太麻烦了。我们可以写个装饰器。
版本二:
#装饰器 def auth(func): def inner(*args,**kwargs): if not session.get('user'): return redirect(url_for('login')) ret = func(*args,**kwargs) return ret return inner @app.route('/index') @auth def index(): return render_template('index.html',stu_dic=STUDENT_DICT)
结果你发现会报错。
这是因为每个函数执行装饰器,函数名都会变为inner,重名出错不是很正常吗?关键是我们如何解决?
这里就用到了functools模块。
这个模块加入装饰器,我们执行函数时,虽然看似是inner,但本质是各函数名。
这样就解决了这个问题。可是如果用到装饰器的地方少,可以这样写,如果多呢?我们总不能还是每个函数都加。
装饰器应用场景:比较少的函数中需要额外添加功能。
注意:以后写装饰器时,都要记得使用functools模块。
版本三:
我们需要写一个函数,这个函数执行代表所有的操作,下面的操作就可以简单明了。
before_request装饰的这个函数,在我们的视图函数执行之前,无论哪个请求,都会先执行一下。就跟django中间件中的process_request有点像。每个请求进来都要经过它。
所以在要操作的函数之前再写一个函数。
@app.before_request def xxxxxx(): if request.path == '/login': return None #可以通过 if session.get('user'): return None #已登录,可以通过 return redirect('/login') #否则,回到登录页面
这种方法使用于批量添加操作时。