为了进一步改进资料页面的外观,可在用户界面中显示用户的头像。本应用中,我们使用Gravatar提供的用户头像。Gravatar是一个行业领先的头像服务,能把头像和电子邮件地址关联起来。用户要先到https://cn.gravatar.com/中注册账户,然后上传图像。此服务通过一个特殊的URL对外开放用户的头像,这个URL格式如下:
https://secure.gravatar.com/avatar/ + 邮箱的散列值 + ?s=xxxx&d=xxx&r=xxx&....
如果使用的电子邮件地址还没有关联头像,则会显示一个默认图像。得到基本的图像URL之后,还可以添加一些查询字符串参数,配置图像的特征。
Gravatar查询字符串参数:
参数名 | 说明 |
s | 图像尺寸,单位为像素 |
r | 图像级别,取值:g, pg, r, x |
d | 尚未注册Gravatar服务的用户使用的默认图像生成方式,可选值有404(返回一个404错误);一个指向默认图像的URL;某种图像生成方式,包括:"mm", "identicon", "monsterid", "wavatar", "retro" 和"blank"。 |
fd | 强制使用默认头像 |
小编在开始本章学习前,已经注册了一个gravatar头像(ps:用的是我很喜欢的歌手胡夏的头像~):
使用python生成电子邮件地址中MD5值的方式:
注意:Gravatar要求在计算MD5散列值时规范电子邮件地址,把字母全部转换为小写。
app/models.py:生成Gravatar URL
class User(UserMixin, db.Model):
...
avatar_hash = db.Column(db.String(32))
def __init__(self, **kwargs):
super().__init__(**kwargs)
...
if self.email is not None and self.avatar_hash is None:
self.avatar_hash = self.gravatar_hash()
def change_email(self, token):
...
self.avatar_hash = self.gravatar_hash()
db.session.add(self)
return True
def gravatar_hash(self):
return hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
def gravatar(self, size=100, default='identicon', rating='g'):
url = 'https://secure.gravatar.com/avatar'
# hash = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
hash = self.avatar_hash or self.gravatar_hash()
return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(url=url, hash=hash, size=size, default=default, rating=rating)
由于计算MD5散列值是一项CPU密集型操作。如果要在某个页面中生成大量头像,计算量会非常大。只要电子邮件地址不变,对应的MD5散列值就不会变。鉴于此我们将其缓存在User模型的self.avatar_hash字段中,仅在邮箱地址不为空且头像为空时生成一次MD5值,此外,每当变更email时,也将重新生成一次MD5值。
app/templates/user.html:在资料页面中添加头像
<div class="page-header">
<img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=168) }}">
<div class="profile-header">
...
其中的 img-rounded 这个CSS类用于定位图像在页面中的位置,在style.css文件中可以查看此自定义的CSS属性:
app/static/style.css:自定义CSS属性
.profile-thumbnail {
position: absolute;
}
.profile-header {
min-height: 260px;
margin-left: 280px;
}
app/templates/base.html:在基模板中引入此css文件
{% block head %}
{{ super() }}
...
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
{% endblock %}
运行结果: