Flask 学习 九 用户资料
资料信息
app/models.py
class User(UserMixin,db.Model):
#......
name = db.Column(db.String(64))
location = db.Column(db.String(64))
about_me=db.Column(db.Text())# 和String的区别是不需要指定最大长度
member_since=db.Column(db.DateTime(),default=datetime.utcnow)# default 可以接受函数为默认值,在需要的时候回自定调用指定的函数,所以不需要加()
last_seen=db.Column(db.DateTime(),default=datetime.utcnow)# 初始值是当前时间
#.....
def ping(self):
self.last_seen=datetime.utcnow() # 获取当前时间
db.session.add(self)# 提交时间到数据库
app/auth/views.py
利用auth蓝本中的before_app_first_request方法,来完成每次请求前都要运行ping方法,来实现更新已登录用户的访问时间
@auth.before_app_first_request
def before_request():
if current_user.is_authenticated:
current_user.ping()
if not current_user.confirmed and request.endpoint[:5] !='auth.': # 不在认证蓝本中
return redirect(url_for('auth.unconfirmed'))
用户资料页面
为每个用户都创建资料页面
app/mian/views.py 资料页面路由
from flask import abort @main.route('/user/<username>')
def user(username):
user = User.query.filter_by(username=username).first()
if user is None:
abort(404)
return render_template('user.html',user=user)
user.html
{% extends 'base.html' %}
{% block title %}flasky -page-not-find{% endblock %} {% block page_content %}
<div class="page-header">
<img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}">
<div class="profile-header">
<h1>{{ user.username }}</h1>
{% if user.name or user.location %}
<p>
{% if user.name %}{{ user.name }}{% endif %}
{% if user.location %}
From <a href="http://map.baidu.com/?{{ user.location }}">{{ user.location }}</a>
{% endif %}
</p>
{% endif %}
{% if current_user.is_administrator() %}
<p><a href="mailto:{{ user.email }}">{{ user.email }}</a></p>
{% endif %}
{% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
<p>
注册时间:{{ moment(user.member_since).format('L') }}.
最后登陆时间:{{ moment(user.last_seen).fromNow() }}
</p>
</div>
</div>
{% endblock %}
base.html 添加一条导航,更方便的访问自己的个人资料,未认证的用户看不到导航条
<ul class="nav navbar-nav">
<li><a href="/">主页</a></li>
{% if current_user.is_authenticated %}
<li>
<a href="{{ url_for('main.user',username=current_user.username) }}">个人资料</a>
</li>
{% endif %}
</ul>
资料编辑器-用户级别的资料编辑器
app/main/forms.py 资料编辑表单
class EditProflieForm(FlaskForm):
name = StringField('真实姓名', validators=[Length(0,64)])
location = StringField('位置', validators=[Length(0,64)])
about_me = TextAreaField('关于我')
submit = SubmitField('提交')
app/main/views.py 资料编辑路由
@main.route('/edit-profile',methods=['get','post'])
@login_required
def edit_profile():
form = EditProflieForm()
if form.validate_on_submit():
current_user.name = form.name.data
current_user.location=form.location.data
current_user.about_me=form.about_me.data
db.session.add(current_user)
flash('你的资料已经更新')
return redirect(url_for('.user',username=current_user.username))
form.name.data = current_user.name
form.location.data=current_user.location
form.about_me.data=current_user.about_me
return render_template('edit_profile.html',form=form)
user.html 资料编辑链接
<p>
{% if user ==current_user.user %}
<a class="btn btn-default" href="{{ url_for('.edit_profile') }}">编辑资料</a>
{% endif %}
</p>
管理员级别的用户编辑器
main/forms.py
class EditProflieAdminForm(FlaskForm):
email=StringField('邮箱', validators=[DataRequired(), Length(1, 64),Email()])
username = StringField('用户名', validators=[DataRequired(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$',0,'用户名必须是字母,数字,点号,下划线')])
confirmed = BooleanField('确认')
role = SelectField('角色',coerce=int)# 因为角色id是个整数,所以把字段值转化为整数而不是字符串
name = StringField('真实姓名', validators=[Length(0, 64)])
location = StringField('位置', validators=[Length(0, 64)])
about_me = TextAreaField('关于我')
submit = SubmitField('提交')
def __init__(self,user,*args,**kwargs):
super(EditProflieAdminForm,self).__init__(*args,**kwargs)
#选项由元祖组成,选项的标识符和显示空间中的文本字符串
self.role.choices=[(role.id,role.name) for role in Role.query.order_by(Role.name).all()]
self.user=user
def validate_email(self, filed):
#首先检查字段是否发生了变化,并保证新值不和其他用户的字段值重复
if filed.data != self.user.email and User.query.filter_by(email=filed.data).first():
raise ValidationError('邮箱已被注册') def validate_username(self, filed):
# 首先检查字段是否发生了变化,并保证新值不和其他用户的字段值重复
if filed.data != self.username and User.query.filter_by(username=filed.data).first():
raise ValidationError('用户名已被使用')
main/views.py 管理员的资料路由
@main.route('/edit-profile/<int:id>',methods=['get','post'])
@login_required
@admin_required
def edit_profile_admin(id):
user = User.query.get_or_404(id)
form =EditProflieAdminForm(user=user)
if form.validate_on_submit():
user.email=form.email.data
user.username=form.username.data
user.confirmed=form.confirmed.data
user.role =Role.query.get(form.role.data)
user.name=form.name.data
user.location=form.location.data
user.about_me=form.about_me.data
db.session.add(user)
flash('资料已经更新')
return redirect(url_for('.user',username = user.username))
form.email.data=user.email
form.username.data = user.username
form.confirmed.data=user.confirmed
# choice属性设置的元祖列表使用数字标识符表示各选项
form.role.data=user.role_id
form.name.data = user.name
form.location.data = user.location
form.about_me.data = user.about_me
return render_template('edit_profile.html',form=form,user=user)
user.html 管理员使用的资料编辑链接
<p>
{% if current_user.is_administrator() %}
<a class="btn btn-danger" href="{{ url_for('.edit_profile_admin',id=user.id) }}">编辑资料[管理员]</a>
{% endif %}
</p>
edit_profile.html
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky - 编辑资料{% endblock %} {% block page_content %}
<div class="page-header">
<h1>编辑你的资料</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
用户头像 app/models.py
import hashlib
from flask import request def gravatar(self,size=100,default='identicon',rating='g'):
if request.is_secure:
url = 'https://secure.gravatar.com/avatar'
else:
url='http://www.gravatar.com/avatar'
hash = self.avatar_hash or hashlib.md5(self.email.encode('utf-8')).hexdigest()
return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(url=url,hash=hash,size=size,default=default,rating=rating)
添加资料页面头像 user.html
<img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}">
将邮件生成的md5值保存到数据库,如果更新继续创建
class User(UserMixin,db.Model):
def __init__(self,**kwargs):
if self.email is not None and self.avatar_hash is None:
self.avatar_hash=hashlib.md5(self.email.encode('utf-8')).hexdigest()
avatar_hash = db.Column(db.String(32))# 头像哈希值存储到数据库
def change_email(self, token):
....
self.email = new_email
self.avatar_hash=hashlib.md5(self.email.encode('utf-8')).hexdigest()
db.session.add(self)
return True
def gravatar(self,size=100,default='identicon',rating='g'):
if request.is_secure:
url = 'https://secure.gravatar.com/avatar'
else:
url='http://www.gravatar.com/avatar'
hash = self.avatar_hash or hashlib.md5(self.email.encode('utf-8')).hexdigest()
return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(url=url,hash=hash,size=size,default=default,rating=rating)
self.last_seen=datetime.utcnow()
db.session.add(self)
Flask 学习 九 用户资料的更多相关文章
- Flask学习之六 个人资料和头像
英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vi-profile-page-and-avatars ...
- Flask学习之五 用户登录
英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins 中文翻译地址:http:// ...
- Flask 学习 八 用户角色
角色在数据库中表示 app/models.py class Role(db.Model): __tablename__='roles' id = db.Column(db.Integer,primar ...
- Flask 学习 七 用户认证
使用werkzeug 实现密码散列 from werkzeug.security import generate_password_hash,check_password_hash class Use ...
- flask学习(九):模板渲染和参数传递
一. 如何渲染模板 1. 模板放在templates文件夹下 2. 从flask中导入render_template函数 3. 在视图函数中,使用render_template函数,渲染模板 注意:只 ...
- 鼠标划过用户名时在鼠标右下角显示div展示用户资料
最近做一个网站论坛,为了方便会员之间相互了解,又不想再做一个页面展示用户资料,就想到了鼠标划过用户名时在鼠标右下角显示div展示用户资料这个效果, 这里要注意的该方法不是给每个用户名的旁边都绑定一个d ...
- Linux常用命令学习8---(用户和用户组管理)
1.用户和用户组 用户和用户组概念 用户:使用操作系统的人(Linux支持多个用户在同一时间登陆同一个操作系统) 用户组:具有相同权限的一组用户(Linux系统中可 ...
- Github上PHP资源汇总大全,php学习的好资料
Github上PHP资源汇总大全,php学习的好资料 国外程序员ziadoz 在Github上收集整理了PHP的各种资源,内容包括模板.框架.数据库.安全等方面的库和工具.汇总了各种PHP资源,供各位 ...
- 机器学习(Machine Learning)&深度学习(Deep Learning)资料【转】
转自:机器学习(Machine Learning)&深度学习(Deep Learning)资料 <Brief History of Machine Learning> 介绍:这是一 ...
随机推荐
- Keras官方中文文档:常见问题与解答
所属分类:Keras Keras FAQ:常见问题 如何引用Keras? 如何使Keras调用GPU? 如何在多张GPU卡上使用Keras "batch", "epoch ...
- Ubuntu出现ERR_PROXY_CONNECTION_FAILED错误解决方案
我是Ubuntu新手,因为想查看国外的资料,然后安装了灯笼,结果打开谷歌浏览器出现了ERR_PROXY_CONNECTION_FAILED错误,未连接到互联网,代理服务器出现错误,然后Firefox也 ...
- 主席树总结(经典区间第k小问题)(主席树,线段树)
接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...
- 期望$DP$ 方法总结
期望\(DP\) 方法总结 这个题目太大了,变化也层出不穷,这里只是我的一点心得,不定期更新! 1. 递推式问题 对于无穷进行的操作期望步数问题,一般可用递推式解决. 对于一个问题\(ans[x]\) ...
- 【BZOJ1006】神奇的国度(弦图)
[BZOJ1006]神奇的国度(弦图) 题面 BZOJ 题解 直接参考弦图的做法 #include<iostream> #include<cstdio> #include< ...
- 【BZOJ1207】【HNOI2004】打鼹鼠(动态规划)
[BZOJ1207][HNOI2004]打鼹鼠 题面 BZOJ题面 题解 考虑到m的范围只有10000 O(m^2)的复杂度是可以接受的 所以直接暴力DP 每次枚举前面出现的鼹鼠 检查是否能够转移过来 ...
- 【洛谷T7243】【CJOJ2225】【BYVoid S3】珠光宝气阁(潜入辛迪加)
Description "我们最新的研究成果<毒药研究方案>被可恶的辛迪加偷走了!"作为拉文霍德的一员,你一定感到很震惊,因为它是我们最尖端的科研人员的一年的研究成果. ...
- [THUWC 2017]在美妙的数学王国中畅游
bzoj5020 \[答案误差只要小于 10^{-7}\] 题解 Taylor展开式: \[若f(x)的n阶导数在[a, b]内连续,则f(x)在x_{0}\in[a, b]可表示为\] \[f(x) ...
- tp5 日志文件名称问题
原文:http://www.upwqy.com/details/17.html 我的项目在运行一段时间后 我发现在日志中生成了 1508467147-20.log 这种文件名的日志 开始还以为是bug ...
- 12.C++-构造函数与析构函数调用顺序,const成员函数,const对象
单个对象创建时,构造函数的调用顺序 1.首先判断该对象的类是否拥有父类,若有则先调用父类的构造函数 2.判断该对象的成员是否是其它类的成员,若是则调用成员变量的构造函数(调用顺序和声明顺序相同) 3. ...