The Flask Mega-Tutorial, Part I: Hello, World!

Signed-off-by: Wang <wangwangwar@gmail.com>
Add basic template for index

Signed-off-by: Wang <wangwangwar@gmail.com>
Add 'if' in template

Signed-off-by: Wang <wangwangwar@gmail.com>
Add 'for' in template

Signed-off-by: Wang <wangwangwar@gmail.com>
Use template inheritance

We put common parts like <head>, <title> in templates/base.html,
and let templates/index.html inherit from it.

Signed-off-by: Wang <wangwangwar@gmail.com>
The Flask Mega-Tutorial, Part III: Web Forms

We use Flask-WTF and OpenID to create forms.

* We put config in config.py and in app/__init__.py
we import it:
`app.config.from_object('config')`
* Add login() in views.py for /login

Signed-off-by: Wang <wangwangwar@gmail.com>
Receive form data

We receive form data in func login(), and use 2 new flask func,
* flash
* redirect

Signed-off-by: Wang <wangwangwar@gmail.com>
Handle form errors

Signed-off-by: Wang <wangwangwar@gmail.com>
Deal with OpenIDs

Signed-off-by: Wang <wangwangwar@gmail.com>
The Flask Mega-Tutorial, Part IV: Database

* Use Flask-SQLAlchemy to handle db CRUD
* Use Flask-Migrate & Alembic to handle db migration,
we use manage.py to do it. Note We must import app.models.{User,Post}
in manage.py
* We take dir migrations under version control, which help for migrations
* We ignore app.db (sqlite)

Signed-off-by: Wang <wangwangwar@gmail.com>
The Flask Mega-Tutorial, Part V: User Logins

We add login support using OpenID
* Use Flask-Login and Flask-OpenID, NOTE: official github
mitsuhiko/Flask-OpenID, which depends on python-openid, which only
supports python2, in order to use in python3, using
DennisGlindhart/flask-openid fork, which depends on python3-openid,
which supports python3.
* Original tutorial has this code in app/models.py::User class:
	class User(db.Model):
		def get_id(self):
			return unicode(self.id)
NOTE the function `unicode` is in python2, for converting id to
unicode type. As in python3, function `unicode` becomes `str`.

Signed-off-by: Wang <wangwangwar@gmail.com>
Add logout support

Signed-off-by: Wang <wangwangwar@gmail.com>
The Flask Mega-Tutorial, Part VI: Profile Page And Avatars

We add user profile page to the site:
* Add `user` functions and /route/<nickname> to route, and the templ
templates/user.html
* Add a user profile link to templates/base.html

Signed-off-by: Wang <wangwangwar@gmail.com>
Add avatar using Gravatar in user profile page

* Add avatar at profile page top
* Add avatar at each post

Signed-off-by: Wang <wangwangwar@gmail.com>
Reuse the post template at the sub-template level

We extract the post template from templates/user.html to
templates/post.html, for reusing later. When using, We just need to
include it

Signed-off-by: Wang <wangwangwar@gmail.com>
Add "Last seen" to user profile page

* Add last_seen and about_me columns in models.User, then use
`python manager.py db migrate && python manager.py db upgrade`
to migrate the db.
* Add "Last seen" and "about me" parts in templates/user.html.
* Record the time before request in views.py

Signed-off-by: Wang <wangwangwar@gmail.com>
Add "Edit about me" in user profile page

Signed-off-by: Wang <wangwangwar@gmail.com>
Fix it to be run itself or run with other uwsgi server such as gunicorn

Signed-off-by: Wang <wangwangwar@gmail.com>
The Flask Mega-Tutorial, Part VII: Unit Testing

* Add /404 and /500 error page for production runtime.
* When error, we send email to the managers. TODO: when connect to
local python smtp server, fail with time out error.
* Log info in tmp/microblog.log.

Signed-off-by: Wang <wangwangwar@gmail.com>
Add 'run without debug' script runp.py and fix bug

Before we run manage.py we have no workable db tables.
We have to explicitly run manage.py to initial tables, which is
not convenient. So we run `db.create_all()` at the very beginning.

Signed-off-by: Wang <wangwangwar@gmail.com>