日課書

编程100小时挑战

利用Flask创建一个mini微博

Mini-Weibo 简介

Flask官方文档提供了一个微型博客的教学案例:Flaskr。虽然这个小示例可以让我们掌握,一个基于Flask框架的Web程序的大致结构,但是功能过于简单、外形比较粗糙,并不是一个拿得出手的小项目。所以,我将参考Flask源码中的minitwit例子,制作一个功能稍复杂些、界面经过美化的「mini微博」—— Mini-Weibo。

这个mini微博可供使用者注册账户,发布消息,并且关注别的用户。实现了微博的骨干功能。同时我们将使用BootStrap来对交互界面进行美化。为了简单,数据库仅采用基本的SQLite。

Step 0:功能分析

考虑一下我们是如何使用微博的。

  • 如果我们没有成为注册用户,那么我们只能浏览部分最近发表的微博信息,即公开时间线
  • 如果想要发布微博,我们需要成为注册用户,那么网站就需要一个页面来实现注册功能
  • 注册的用户会用到登录登出功能。
  • 完成注册后,我们可以发布微博
  • 通常在微博上我们还会关注其他用户。有关注就会对应取消关注
  • 当关注的用户多了我们想要找到某个用户,就需要有一个关注列表,用来快速定位用户。
  • 因此,当一个注册用户登录时,他的界面显示的是他所关注用户发表的信息,我们称之为关注时间线
  • 有时我们只想看某个人的微博,那么会进入一个个人微博页面,仅浏览该用户发表的信息。

上面的每一个功能都会有对应的URL链接,如果有信息需要显示,和这个URL绑定的视图函数会返回给我们相应的页面。如果只是需要修改一些数据,那么URL绑定的视图函数在进行完相应的修改后,会重定向到后继显示的页面。

我们通过分析微博的功能,发现了在这个应用中存在以下几种数据:

  • 用户数据:只要注册过的用户都会有它的用户名和其他基本信息。
  • 微博数据:每条微博数据除了内容还会有其作者的名称。
  • 关注数据:每一次关注动作的发生,都涉及到两方面,关注者和被关注着。

有了上面的功能分析和数据类型分析,我们就可以设计出大概需要的各种页面,需要后台程序响应的数据,以及储存数据的模型。

Step 1:配置开发环境

在GitHub上创建项目

在GitHub上创建一个新的仓库,用于托管项目代码。添加项目描述、初始化文件、.gitignore和License。本教程基于Mac操作系统。

把GitHub上的远程仓库克隆回本地:

1
$ git clone git@github.com:wYibin/miniweibo.git

搭建开发虚拟环境

安装并激活虚拟环境

1
2
3
4
5
$ cd miniweibo

$ virtualenv venv

$ source venv/bin/activate

使用pip安装Python包

1
pip install flask

创建flask需要的文件夹

1
2
3
/flask
/static
/templates

测试开发环境

写一个最简单的Flask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# miniweibo.py
from flask import Flask

#configuration
DATABASE = 'miniweibo.db'
DEBUG = True
SECRET_KEY = 'development key'

# create application
app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('MINIWEIBO_SETTING', silent=True)

@app.route('/')
def index():
return '<h1>Hello, MiniWeibo!</h1>'

测试开发环境是否正确设置

1
2
3
export FLASK_APP=miniweibo
export FLASK_DEBUG=1
flask run

访问127.0.0.1:5000,如果能正式显示信息则配置成功。

接着我们把它同步到GitHub上。

1
2
3
4
5
$ git add *

$ git commit -m "Set up the dev environment."

$ git push origin master

Step 2:数据库设计

定义数据模型

通过功能分析的部分,我们找出了微博程序中所需要的三种数据类型,分别表示:用户、微博、和关注关系。现在我们需要做的就是,利用数据库Schema具体定义出这三种抽象数据模型模型。下面我们队这三种模型进一步进行分析。

  • 用户。只有注册用户才能发表微博,所以用户模型是最基本的。每个用户会有用户名,注册时也会有邮箱和密码,密码必定不能明文存储在数据库中,一般以散列算法计算后存储,以免发生泄漏风险。用户名的检索不太方便也不利于排序,所以我们采用整数类型为用户分配id.
  • 微博。每条微博对着这内容和其作者。为了索引方便我们为每条微博分配id。同时作者也用id的方式进行存储。同时每条微博发布的时间也比较重要。
  • 关注。微博做为一种社交应用,必然会有人和人之间的关系。在微博中每一次关注,对应着一个关注者和被关注者。把所有的关注放在一起,我们就可以还原出整个关系网络。这里我们也用用户id来表示关注者和被关注者。

具体的数据库定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
drop table if exists users;
create table users (
user_id integer primary key autoincrement,
user_name text not null,
email text not null,
pw_hash not null
)

drop table if exists messages;
create table messages (
message_id integer primary key autoincrement,
user_id integer not null,
text text not null,
pub_time integer not null
)

drop table if exists follows;
create table follows (
follower_id integer not null,
followed_id integer not null
)

创建数据库连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sqlite3
from flask import g

DATABASE = 'database.db'

def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db

@app.teardown_appcontext
def close_db(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()

初始化数据库

利用schema来初始化数据库:

1
2
3
4
5
6
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()

在Python shell中完成初始化:

1
2
3
$ python
>>> from miniweibo import init_db
>>> init_db()

简化数据查询

对于常用的查询操作,我们定义专门的函数来简化它。

1
2
3
def query_db(query, args=(), one=False):
rv = get_db().execute(query, args).fetchall()
return (rv[0] if rv else None) if one else rv

由于用户输入的通常是用户名,而在数据库中微博和关注表中更多的是存储用户id。所以通过用户名检索用户id是个高频操作,因此我们特别定义一个函数:

1
2
3
def get_user_id(username):
rv = query_db('SELECT * FROM users WHERE user_name=?', [username], one=True)
return rv[0] if rv else None

待续

Step 3:创建视图函数

用户登录首页时会进行判断,如果是登录用户则显示,用户关注的时间线,如果没登录则显示公共的时间线。

在首页会有登录登出的选项,这个具体的选项会根据目前用户状态进行判断。如果是未登录则点击进入登录页面,登录成功后返回用户关注的时间线。如果用户已登录,则显示登出,登出后返回公共时间线。

如果是未登录状态,首页还会有注册选项。点击进入注册页面,注册成功后跳转至登录页面。

其次登录用户还可以进入特定的其他用户界面,以浏览某用户的全部微博。在用户的个人界面,可以选择关注或者取消关注某用户。并且可以查看该用户的关注列表。

Step 4:制作模板

Step 5:测试程序

Step 6: 部署程序