Python的Flask框架中实现登录用户的个人资料和头像的教程_python

用户资料页面

在用户资料页面,基本上没有什么特别要强调和介绍的新概念。只需要创建一个含有HTML的新视图函数模板页面即可。

下面是视图函数(项目目录/views.py):
 

@app.route('/user/<nickname>')
@login_required
def user(nickname):
  user = User.query.filter_by(nickname = nickname).first()
  if user == None:
    flash('不存在用户:' + nickname + '!')
    return redirect(url_for('index'))
  posts = [
    { 'author': user, 'body': 'Test post #1' },
    { 'author': user, 'body': 'Test post #2' }
  ]
  return render_template('user.html',
    user = user,
    posts = posts)

这里的@app.route标识主要是用来说明此视图函数不同于之前的那些。我们定义了一个名为<nickname>的参数。在函数里面它会转化成跟它同名的参数,当用户有请求的时候,例如这样的一个URL:URL/user/miguel,次视图函数就会识别为有一个名为nickname值为'miguel'的参数,即nickname = 'miguel'。

没必要为此方法的实现过程感到惊讶。首先我们需要通过把转化后的nickname参数作为条件,尝试着从数据库里把此用户的数据调用出来。如果没有查询到数据,我们就像之前那样,给用户一个错误的提示并且跳转到主页去。

一旦我们找到了改用户,我们就在模板下面来显示该用户的文章。要注意下的是在用户资料页面我们只让显示该用户的文章,所以文章的作者要是该用户。

初始化的视图模板非常的简单(项目目录/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<h1>用户昵称: {{user.nickname}}!</h1>
<hr>
{% for post in posts %}
<p>
 {{post.author.nickname}} 发布了: <b>{{post.body}}</b>
</p>
{% endfor %}
{% endblock %}

用户资料页面就做好了,不过在站点中还没有指向改页面的链接地址。为了让用户很方便的来查看自己的资料信息我们就把链接地址放到最上面的导航上去(项目目录/templates/base.html):

 

<div>Microblog:
    <a href="{{ url_for('index') }}">Home</a>
    {% if g.user.is_authenticated() %}
    | <a href="{{ url_for('user', nickname = g.user.nickname) }}">你的个人资料</a>
    | <a href="{{ url_for('logout') }}">退出登陆</a>
    {% endif %}
  </div>

注意一下我们已经给函数传参了之后的和之前的URL。

现在就来试一试这个项目。点击上面的“你的资料”链接就会跳转到用户资料页面。由于我们还没有指向一个随意用户资料页面的链接地址,所以在这里如果你想看他人的资料,就需要自己手动输入一下地址了。比如你想看miguel的资料,那么地址就是:http://localhost:5000/user/miguelt

头像部分

我相信你会觉得目前的用户资料页面看起来很单调。为了好看,我们就来添加用户头像的功能。

为了避免我们服务器需要来处理大量上传后的头像图片,我们在这里就使用Gravatar给咋们提供的用户头像即可。

鉴于返回一个用户头像是属于用户这块的,所以我们就把代码放在theUserclass里面(项目目录/models.py):

 

from hashlib import md5
# ...
class User(db.Model):
  # ...
  def avatar(self, size):
    return 'http://www.gravatar.com/avatar/' + md5(self.email).hexdigest() +
    '?d=mm&s=' + str(size)

avatar将会返回用户头像图片的地址, 根据你的需要来请求你想要的图片尺寸像素。

从Gravatar上得到图像图片很简单。你只需要用md5把用户的邮箱hash加密之后合并成上面的那种url形式即可。当然你也可以自由选择自 定义图像大小。其中“d=mm”是设置用户在没有Gravatar账号的情况下显示的默认头像。“mm”选项会返回一张只有人轮廓的灰色图片,称之为“谜 样人”。而“s=”选项是用来设置返回你给定的图片尺寸像素。

当然Gravatar也有自己的文档来描述URL的拼接技术!

到这里Userclass就可以返回一个用户头像的图片了,我们就需要把这个整合到用户资料布局去(项目目录/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用户昵称: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
<p>
 {{post.author.nickname}} 发布了: <b>{{post.body}}</b>
</p>
{% endfor %}
{% endblock %}

我们设计Userclass来返回用户头像的亮点在于:如果某一天我们要是觉得Gravatar网站上的头像不是我们所想要的头像的时候,我们只需要我们只需要重写一下头像处理的函数来返回我们想要的地址即可(即使有人盗链指向我们的服务器,我们也可以保护好自己的主机),这样一来只需要修改这么点点,所以的模板都还是自动正常运行。

我们已经把用户头像部分添加到了用户资料详情页面的顶部去了,不过在页面底部我们还有显示文章的没做,在文章前面我们也需要显示一下用户的头像。当 然在用户资料页面需要对所以的文章都显示同样的头像,不过要是把头像函数移动到主页去来给所以的文章都显示作者的头像,那该多好。

我们只需要稍稍修改模板文件即可实现给文章显示相应作者头像的功能(项目目录/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用户昵称: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
<table>
  <tr valign="top">
    <td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}}
   发布了:</i><br>{{post.body}}</td>
  </tr>
</table>
{% endfor %}
{% endblock %}

这就是到此为止我们的用户资料页面:

微博客用户详情页面

重复使用子模板

用户资料页面显示了用户自己的文章,不过网站的首页需要显示此刻不同用户文章。在这里就有两个用于显示 用户文章的模板文件了。我们可以直接复制把处理显示文章的那段代码然后直接粘贴到新的模板,其实那并不是最理想的方法,倘若有一天我们需要修改下显示文章 那块,我们就需要来更新所以的那些含有文章显示代码的模板文件。

反之,我们将会去新建一个子模板文件来处理文章显示的功能,之后在需要显示文章的时候包含一下这个文件即可。

开始我们还是来创建一个子空模板文件,然后把用户资料页面中展示文章的那段代码复制过来(项目目录/templates/post.html):
 

<table>
  <tr valign="top">
    <td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}}
  发布了:</i><br>{{post.body}}</td>
  </tr>
</table>

然后我们使用Jinja2的包含功能调用一下该子模板文件(项目目录/templates/user.html)
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用户昵称: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

一旦有了完整的页面我们就可以按照上面的方法去调用下子模板来显示文章,不过现在还不急说,将在后面章节的教程中说到。

更多相关个人信息

尽管到此用户信息页面比较精密了,不过还是有许多信息没有显示出来。用户大多喜欢在网站上显示自己更多的信息,因此我们就可以让用户填写自己的信息显示在这里。当然我们也可以记录下用户每次登陆到本站的的时间,显示到他们自己的资料详情页。

为了显示等多的信息我们就需要更新下数据库。特别需要在Userclass里面新加字段(项目目录/models.py):


class User(db.Model):
  id = db.Column(db.Integer, primary_key = True)
  nickname = db.Column(db.String(64), unique = True)
  email = db.Column(db.String(120), index = True, unique = True)
  role = db.Column(db.SmallInteger, default = ROLE_USER)
  posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
  about_me = db.Column(db.String(140))
  last_seen = db.Column(db.DateTime)

我们每次修改数据库的时候就需要生成新的记录(migration)。需要注意下我们在处理数据更新到数据库的时候记得创建一个(migration),现在我们就来看下最后结果。我们只需要下面的代码就可以把新加的两个字段更新到数据库里去了:
 

./db_migrate.py

当然相应的响应脚本是
 

New migration saved as db_repository/versions/003_migration.py
Current database version: 3

现在我们新加的两个字段就保存到数据库了。不过需要提醒的是在window系统下面调用此脚本是有点不一样的。

如果不支持数据迁移的话你还得手动修改数据库,否则你就需要删除之后重新从头开始创建数据。

接下来我们就需要修改下用户详情页来显示我们刚添加的字段(项目目录/templates/user.html):

 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td>
      <h1>用户昵称: {{user.nickname}}</h1>
      {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %}
      {% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %}
    </td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

由于我们需要只有当用户自己填写了这两个字段的时候才显示出来,所以我们主要利用Jinja2的判断条件来显示这些字段即可。

对于这点,对所有的用户而言,这两个字段都是空的,什么都不会显示的。
 

最后显示的字段(last_seen)就特别的好处理。需要注意的是在上面我们已经设置了用于注册用户请求的(flask.g和global, asg.user)接收参数。也就是需要在这个最佳段来记录用户的登陆时间(项目目录/views.py):
 

from datetime import datetime
# ...
@app.before_request
def before_request():
  g.user = current_user
  if g.user.is_authenticated():
    g.user.last_seen = datetime.utcnow()
    db.session.add(g.user)
    db.session.commit()

如果你登陆了之后就会在资料详情页面显示最后的登陆时间,当然如果你每刷新一次页面的话相应的登陆时间就会自动更新。这是由于当浏览器没刷新一次就会去请求我们上面设置的接收参数并更新数据库的处理函数。

在这里我们记录的是国际标准时间UTC时区。在之前的章节中我们也提到了怎么去储存一个适合所有时区的时间戳,这就会在有一个负面的错误信息,因为在所有用户的资料页面显示的都是UTC的时区的时间,这个问题我会在接下来说关于出来时间和日期的章节中详细讲解。

想显示关于用户的更多信息,我们得给他们一个链接, 最适合放在用户资料的编辑页面。
 
编辑用户详细资料

创建一个用户资料编辑页面那真是太简单了,我们只需要创建下面的web表单即可(项目目录/forms.py):
 

from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
from flask.ext.wtf import Required, Length

class EditForm(Form):
  nickname = TextField('nickname', validators = [Required()])
  about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])

视图模板文件(项目目录/templates/edit.html):
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<h1>Edit Your Profile</h1>
<form action="" method="post" name="edit">
  {{form.hidden_tag()}}
  <table>
    <tr>
      <td>你的昵称:</td>
      <td>{{form.nickname(size = 24)}}</td>
    </tr>
    <tr>
      <td>关于自己:</td>
      <td>{{form.about_me(cols = 32, rows = 4)}}</td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" value="保存"></td>
    </tr>
  </table>
</form>
{% endblock %}

最后当然就是创建视图的方法(项目目录/views.py):
 

from forms import LoginForm, EditForm

@app.route('/edit', methods = ['GET', 'POST'])
@login_required
def edit():
  form = EditForm()
  if form.validate_on_submit():
    g.user.nickname = form.nickname.data
    g.user.about_me = form.about_me.data
    db.session.add(g.user)
    db.session.commit()
    flash('Your changes have been saved.')
    return redirect(url_for('edit'))
  else:
    form.nickname.data = g.user.nickname
    form.about_me.data = g.user.about_me
  return render_template('edit.html',
    form = form)

方便用户编辑,我们需要在用户的个人资料页面添加一个到此页面的链接地址(项目目录/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td>
      <h1>用户昵称: {{user.nickname}}</h1>
      {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %}
      {% if user.last_seen %}<p><i>最后登陆时间: {{user.last_seen}}</i></p>{% endif %}
      {% if user.id == g.user.id %}<p><a href="{{url_for('edit')}}">修改资料</a></p>{% endif %}
    </td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

不过你需要判断的一下,条件就是只有当用户浏览自己的个人资料页面的时候才显示该链接,而不是浏览任何人的个人资料页面都显示出来。

下面是最新个人资料页面的截图,包含了我们新加的所以字段,也含有“关于我”的文字:

最后一点留给你自己去研究了

貌似通过上面的一些列制作,个人资料页面感觉已经很完善了,对不?仔细想来,是这样不过我们还有一些bug需要修复下。

不知道你有没有发现?

提醒下你吧,在之前的章节中我们浏览用户登陆的时候其实我就已经提到过这个bug的。现在我们在上面的代码片中也犯了同样错。

仔细想想吧,如果你知道是什么问题的话可以在下面评论中说下。我将会在下一个章节详细地说此bug,并说怎么去修正它。

跟以前一样我会把今天说讲到的代码打包提供下载

下载地址 microblog-0.6.zip.

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索python
python web框架 flask、python flask框架、python的flask框架、flask框架、flask 前端框架,以便于您获取更多的相关知识。

时间: 2024-10-30 20:42:17

Python的Flask框架中实现登录用户的个人资料和头像的教程_python的相关文章

Python的Flask框架中实现简单的登录功能的教程

  Python的Flask框架中实现简单的登录功能的教程,登录是各个web框架中的基础功能,需要的朋友可以参考下 回顾 在前面的系列章节中,我们创建了一个数据库并且学着用用户和邮件来填充,但是到现在我们还没能够植入到我们的程序中. 两章之前,我们已经看到怎么去创建网络表单并且留下了一个实现完全的登陆表单. 在这篇文章中,我们将基于我门所学的网络表单和数据库来构建并实现我们自己的用户登录系统.教程的最后我们小程序会实现新用户注册,登陆和退出的功能. 为了能跟上这章节,你需要前一章节最后部分,我们

如何在Python的Flask框架中使用模版的入门教程

  如何在Python的Flask框架中使用模版的入门教程?          概述 如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用: microblog |-flask文件夹 |-<一些虚拟环境的文件> |-app文件夹 | |-static文件夹 | |-templates文件夹 | |-__init__.py文件 | |-views.py文件 |-tmp文件夹 |-run.py文件 以上给你介绍了在Python的Flask

如何在Python的Flask框架中实现全文搜索?

  这篇文章主要介绍了在Python的Flask框架中实现全文搜索功能,这个基本的web功能实现起来非常简单,需要的朋友可以参考下 全文检索引擎入门 灰常不幸的是,关系型数据库对全文检索的支持没有被标准化.不同的数据库通过它们自己的方式来实现全文检索,而且SQLAlchemy在全文检索上也没有提供一个好的抽象. 我们现在使用SQLite作为我们的数据库,所以我们可以绕开SQLAlchemy而使用SQLite提供的工具来创建一个全文检索索引.但这么做不怎么好,因为如果有一天我们换用别的数据库,那么

在Python的Flask框架中使用日期和时间的教程

  这篇文章主要介绍了在Python的Flask框架中使用日期和时间的教程,包括对各个时区之间转换的一些处理,需要的朋友可以参考下 时间戳的问题 我们的微博应用的一个忽略了很久的问题就是日间和日期的显示. 直到现在,我们在我们的User和Post对象中使用Python它自己的方式来渲染时间对象,但这并不是一个好的解决方案. 考虑下这样的例子.我正在写这篇文章,此时正是12月31号下午3:54.我的时区是PST(或者你们更习惯的:UTC-8). 在Python解释器中运行,我得到下面输出: ? 1

Python的Flask框架中web表单的教程

  下面为你介绍了Python的Flask框架中web表单的教程,表单是学习各个web框架中的基础知识,需要的朋友可以参考下 概要 在前面章节我们为主页定义了一个简单的模板,部分尚未实现的模块如用户或帖子等使用模拟的对象作为临时占位. 本章我们将看到如何利用web表单填补这些空白. web表单是web应用中最基本的构建要素,我们将通过表单来实现用户发帖和应用登录功能. 完成本章内容你需要基于前面章节完成的微博应用代码,请确认这些代码已安装并能正常运行. 配置 Flask-WTF是WTForms项

Python的Flask框架中实现分页功能的教程

  这篇文章主要介绍了Python的Flask框架中实现分页功能的教程,文中的示例基于一个博客来实现,需要的朋友可以参考下 Blog Posts的提交 让我们从简单的开始.首页上必须有一张用户提交新的post的表单. 首先我们定义一个单域表单对象(fileapp/forms.py): ? 1 2 class PostForm(Form): post = TextField('post', validators = [Required()]) 下面,我们把这个表单添加到template中(file

在Python的Flask框架中实现单元测试的教程

  在Python的Flask框架中实现单元测试的教程,属于自动化部署的方面,可以给debug工作带来诸多便利,需要的朋友可以参考下 概要 在前面的章节里我们专注于在我们的小应用程序上一步步的添加功能上.到现在为止我们有了一个带有数据库的应用程序,可以注册用户,记录用户登陆退出日志以及查看修改配置文件. 在本节中,我们不为应用程序添加任何新功能,相反,我们要寻找一种方法来增加我们已写代码的稳定性,我们还将创建一个测试框架来帮助我们防止将来程序中出现的失败和回滚. 让我们来找bug 在上一章的结尾

Python的Flask框架中实现简单的登录功能的教程_python

 回顾 在前面的系列章节中,我们创建了一个数据库并且学着用用户和邮件来填充,但是到现在我们还没能够植入到我们的程序中. 两章之前,我们已经看到怎么去创建网络表单并且留下了一个实现完全的登陆表单. 在这篇文章中,我们将基于我门所学的网络表单和数据库来构建并实现我们自己的用户登录系统.教程的最后我们小程序会实现新用户注册,登陆和退出的功能. 为了能跟上这章节,你需要前一章节最后部分,我们留下的微博程序.请确保你的程序已经正确安装和运行. 在前面的章节,我们开始配置我们将要用到的Flask扩展.为了登

在Python的Flask框架中使用模版的入门教程_python

 概述 如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用:   microblog     |-flask文件夹     |-<一些虚拟环境的文件>     |-app文件夹     |  |-static文件夹     |  |-templates文件夹     |  |-__init__.py文件     |  |-views.py文件     |-tmp文件夹     |-run.py文件 亲,想要运行这个程序么?那就运行这