4.用户登录
1.配置
 对于登录系统,使用到扩展:Flask-Login。配置情况如下(app/init.py)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#-*- coding:utf-8 -*-
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
# 初始化flask应用
app = Flask(__name__)
app.config.from_object('config')
# 初始化数据库
db = SQLAlchemy(app)
# 初始化flask-Login
lm = LoginManager()
lm.setup_app(app)
from app import views, models
2.重构用户模型
Flask-Login 扩展需要在我们的 User 类中实现一些特定的方法,但是类如何去实现这些方法却没有什么要求,让我们为 Flask-Login 实现的 User 类(app/models.py)
| 1 | class User(db.Model): | 
is_authenticated 方法有一个具有迷惑性的名称。一般而言,这个方法应该只返回 True,除非表示用户的对象因为某些原因不允许被认证;is_active 方法应该返回 True,除非是用户是无效的,比如因为他们的账号被禁止;is_anonymous 方法应该返回 True,除非是伪造的用户不允许登录系统;get_id 方法应该返回一个用户唯一的标识符,以 unicode 格式返回我们使用数据库生成的唯一的id。
3.user_loader 回调
我们已经准备好用 Flask-Login 扩展来开始实现登录系统。
首先,我们必须编写一个函数用于从数据库加载用户,这个函数将会被 Flask-Login 使用(app/views.py)
| 1 | 
 | 
Flask-Login 中的用户的id永远是 unicode 字符串,因此在我们把id 发送给 Flask-SQLAlchemy 之前,需要把id转成整型是必须的,否则会报错。
4.登陆视图函数(app/views.py)
| 1 | #-*- coding:utf-8 -*- | 
整个流程就是,验证用户,验证用户是否已经注册,如果注册则从数据库中加载用户并转到用户页面。如果要让这些都起作用的话,Flask-Login 需要知道哪个视图允许用户登录。我们在应用程序模块初始化中配置(app/init.py)1
2lm = LoginManager()
lm.setup_app(app)
5.首页视图
前面我们的 index 视图函数使用了伪造的对象,因为那时候我们并没有用户或者 blog。现在我们有用户了,让我们使用它。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def index():
    user = 'Man'
    posts = [
        {
            'author': {'nickname': 'John'},
            'body': 'Beautiful day in Portland!'
        },
        {
            'author': {'nickname': 'Susan'},
            'body': 'The Avengers movie was so cool!'
        }
    ]
    return render_template(
        "index.html",
        title="Home",
        user=user,
        posts=posts)
6.登录
我们已经实现了登录,现在增加登陆的功能,即对登录视图函数进行修改(app/views.py)
| 1 | 
 | 
其中login_required是为了验证用户必须是登陆的前提,才会有登出。
7.注册
- 再注册前,我们需要修改app/forms.py文件以绑定数据库
| 1 | # -*- coding:utf-8 -*- | 
在这里添加了类SignUpForm,用户的用户名和邮件的注册提交
- 接着,实现用户注册视图(app/views.py)1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34from forms import LoginForm, SignUpForm 
 def sign_up():
 form = SignUpForm()
 user = User()
 if form.validate_on_submit():
 user_name = request.form.get('user_name')
 user_email = request.form.get('user_email')
 register_check = User.query.filter(db.or_(
 User.nickname == user_name, User.email == user_email)).first()
 if register_check:
 flash("error: The user's name or email already exists!")
 return redirect('/sign-up')
 if len(user_name) and len(user_email):
 user.nickname = user_name
 user.email = user_email
 user.role = ROLE_USER
 try:
 db.session.add(user)
 db.session.commit()
 except:
 flash("The Database error!")
 return redirect('/sign-up')
 flash("Sign up successful!")
 return redirect('/index')
 return render_template(
 "sign_up.html",
 form=form)
在提交注册信息的时候验证数据库中是否已经注册该用户信息,如果没有注册则在数据库中提交该信息,并显示注册成功,转到首页。
- 在修改主页index.html - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- {% extends "base.html" %} 
 {% block content %}
 {% if not current_user.is_authenticated() %}
 <h1>Hi, Guys!</h1>
 {% else %}
 <h1>Welcome back, {{ current_user.nickname }}!</h1>
 {% endif %}
 {% for post in posts %}
 <p>{{ post.author.nickname }} says: <b>{{ post.body }}</b></p>
 </div>
 {% endfor %}
 {% endblock %}
- 修改登录模版(login.html) 
| 1 | {% extends "base.html" %} | 
当现在如果运行程序的话,肯定会说用户名不存在,因为还需要建立一个注册模版(sign_up.html)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20{% extends "base.html" %}
{% block content %}
<form action="/sign-up", method="POST" name="sign_up">
    {{ form.hidden_tag() }}
    <p>Nick name: {{ form.user_name }}</p>
    {% for error in form.errors.user_name %}
    <p style="color:red;">[-] {{ error }}</p>
    {% endfor %}
    <p>E-mail: {{ form.user_email }}</p>
    {% for error in form.errors.user_email %}
    <p style="color:red;">[-] {{ error }}</p>
    {% endfor %}
    <p>{{ form.submit }}</p>
</form>
{% endblock %}
但是还没有在模版中添加登出和注册的链接。将要把这个链接放在基础层中的导航栏里(app/templates/base.html)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<html>
  <head>
    {% if title %}
    <title>{{title}} - microblog</title>
    {% else %}
    <title>microblog</title>
    {% endif %}
  </head>
  <body>
    <div>Microblog: 
        <a href="{{ url_for('index') }}">Home</a>
        {% if not current_user.is_authenticated() %}
        | <a href="{{ url_for('login') }}">Log in</a>
        or <a href="{{ url_for('sign_up') }}">Sign up</a>
        {% else %}
        | <a href="{{ url_for('logout') }}">Logout</a>
        {% endif %}
    </div>
    <hr />
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    {% block content %}{% endblock %}
  </body>
  {% block js %}{% endblock %}
</html>