禁止chrome缓存:开发者工具->F1(settings)->Disable cache (while DevTools is open)选中
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Go">
</form>
<div class="Container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message }}
</div>
{% endfor %}
Target database is not up to date
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError)
{{ form.csrf_token }}
在 upgrade 之前,你需要 migrate
修改了 model 之后
需要先 python manage.py db migrate
然后才 python manage.py db upgrade
重置密码功能
在邮箱里点击链接之间修改密码
models.py
def generate_reset_token(self,expiration=3600):
s=Serializer(current_app.config['SECRET_KEY'],expiration)
return s.dumps({'reset':self.id})
def get_reset_token(self,token):
s=Serializer(current_app.config['SECRET_KEY'])
return s.loads(token)
def reset_password(self,token,new_password):
try:
data=self.get_reset_token(token)
except:
return False
if data.get('reset')!=self.id:
return False
self.password=new_password
db.session.add(self)
db.session.commit()
return True
app/auth/views.py
reset_data={}
@auth.route('/reset',methods=['GET','POST'])
def password_reset_request():
global reset_data
form=PasswordResetRequestForm()
if form.validate_on_submit():
user=User.query.filter_by(email=form.email.data).first()
if user:
reset_token=user.generate_reset_token()
reset_data=user.get_reset_token(reset_token)
send_email(user.email,u'重置密码','auth/email/reset_password',user=user,token=reset_token,next=request.args.get('next'))
flash(u'已向您的邮箱发送重置密码邮件')
return redirect(url_for('auth.login'))
return render_template('auth/reset_password.html',form=form)
@auth.route('/reset/<token>',methods=['GET','POST'])
def password_reset(token):
global reset_data
print reset_data
if not current_user.is_anonymous:
return redirect(url_for('main.index'))
form=PasswordResetForm()
if form.validate_on_submit():
user=User.query.filter_by(id=reset_data['reset']).first()
if user.reset_password(token,form.password.data):
flash(u'您的密码已经重置')
return redirect(url_for('auth.login'))
else:
return redirect(url_for('main.index'))
return render_template('auth/reset_password.html',form=form)
git add -A .
git commit -m ”
git push origin master
current_app._get_current_object()和current_app区别
current_app 在 Flask 是一个代理,如果你看 Flask 源码的话会发现其实它外部包裹的是这样的:
源码地址 line: 48-58
def _find_app():
top = _app_ctx_stack.top
if top is None:
raise RuntimeError(_app_ctx_err_msg)
return top.app
...
current_app = LocalProxy(_find_app)
这个 LocalProxy 就不展开讲了,但是我可以告诉你这个LocalProxy 的作用就是可以根据线程/协程返回对应当前协程/线程的对象,也就是说
线程 A 往 LocalProxy 中塞入 A
线程 B 往 LocalProxy 中塞入 B
无论在是什么地方,
线程 A 永远取到得是 A,线程 B 取到得永远是 B
这就是在 Flask 中可以在代码中直接使用 request、current_app 这样的变量的底层原因。
所以,答案来了,因为这里开了一个新线程,如果你不穿真实对象过去,那么你在线程里面使用 current_app 将获取不到对象,因为他没有 flask 上下文。这又是一个 Flask 的重要概念,太多得说。
sudo /usr/local/mysql/support-files/mysql.server start
jquery加载顺序
<script src="{{ url_for('static',filename='jquery-3.2.1.js') }}"></script>
<script src="{{ url_for('static',filename='jquery.validate.js') }}"></script>
javascript语句要加逗号
jinja2-truncate返回字符串的截断副本
from flaskext.markdown import Markdown
Markdown(app)
hover(over,out):一个模仿悬停事件的方法(修正了使用mouseout事件的一个常见错误)。
over (Function) : 鼠标移到元素上要触发的函数
out (Function) : 鼠标移出元素要触发的函数
例:鼠标悬停的表格加上特定的类
$("td").hover(
function () {
$(this).addClass("hover");
},
function () {
$(this).removeClass("hover");
}
);
sudo /usr/local/mysql/support-files/mysql.server start
sudo /usr/local/mysql/support-files/mysql.server stop
show full columns from posts;
alter table posts convert to character set utf8mb4 collate utf8mb4_unicode_ci;
可以插入中文了,但显示是乱码
alter database r character set utf8mb4;
OK了
建库的时候应该
create database test default charaster set utf8mb4 collate utf8mb4_unicode_ci;