网站后端.Flask.实战-社交博客开发-资料信息?

1.为了让用户的资料页面更吸引人,我们在User模型中添加一些关于用户的其它信息(真实姓名/所在地/自我介绍/注册日期/最后访问日期)

FlaskWeb/app/models.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
from datetime import datetime
from . import db, loginmanager
from flask import current_app
from flask_login import UserMixin, AnonymousUserMixin
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from werkzeug.security import generate_password_hash, check_password_hash

@loginmanager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

class Permission(object):
    FOLLOW = 0x01
    COMMENT = 0x02
    WRITE_ARTICLES = 0x04
    MANAGE_COMMENTS = 0x08
    ADMINISTER_POWER = 0x80

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False, index=True)
    permission = db.Column(db.Integer)
    default = db.Column(db.Boolean, default=False, index=True)
    users = db.relationship('User', backref='role', lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles = {
            'user': (
                Permission.FOLLOW |
                Permission.COMMENT |
                Permission.WRITE_ARTICLES, True),
            'manager': (
                Permission.FOLLOW |
                Permission.COMMENT |
                Permission.WRITE_ARTICLES |
                Permission.MANAGE_COMMENTS, False),
            'administrator': (
                Permission.ADMINISTER_POWER, False)
        }
        for cur_role in roles:
            role = Role.query.filter_by(name=cur_role).first()
            if not role:
                role = Role(name=cur_role)
            role.permission = roles[cur_role][0]
            role.default = roles[cur_role][-1]
            db.session.add(role)
            db.session.commit()

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, nullable=False, index=True)
    username = db.Column(db.String(64), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(128), nullable=False)
    is_confirmed = db.Column(db.Boolean, default=False)
    realname = db.Column(db.String(64))
    location = db.Column(db.String(128))
    about_me = db.Column(db.Text())
    register_date = db.Column(db.DateTime(), default=datetime.utcnow())
    last_access_date = db.Column(db.DateTime(), default=datetime.utcnow())
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def refresh_access_date(self):
        self.last_access_date = datetime.utcnow()

    def allow(self, permission):
        return self.role is not None and (self.role.permission & permission) == permission

    def is_administrator(self):
        return self.allow(Permission.ADMINISTER_POWER)

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        if not self.role:
            if self.email == current_app.config['FLASK_ADMIN']:
                self.role = Role.query.filter_by(permission=128).first()
            if not self.role:
                self.role = Role.query.filter_by(default=True).first()

    @property
    def password(self):
        raise AttributeError(u'password 不允许读取.')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_confirm_token(self, expires_in=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=expires_in)
        data = s.dumps({'confirm_id': self.id})
        return data

    def verify_confirm_token(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except BaseException, e:
            return False
        if data.get('confirm_id') != self.id:
            return False
        self.is_confirmed = True
        db.session.add(self)
        db.session.commit()
        return True

class AnonymousUser(AnonymousUserMixin):
    def allow(self, permission):
        return False

    def is_administrator(self):
        return False
loginmanager.anonymous_user = AnonymousUser

说明:添加的about_me字段类型为db.Text(),register_date字段类型为db.DateTime(),db.String()和db.Text的区别在于后者不需要指定最大长度,两个时间戳的默认值都是当前时间,但是last_access_date需要每次访问时自动刷新,所以我们提供一个refresh_access_date的方法来刷新访问时间

FlaskWeb/app/auth/views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
from .. import db
from . import auth
from ..models import User
from ..email import send_mail
from .forms import LoginForm, RegisterForm
from flask import render_template, flash, url_for, redirect, request
from flask_login import login_required, fresh_login_required, login_user, logout_user, current_user

@auth.before_app_request
def before_app_request():
    if current_user.is_authenticated:
        current_user.refresh_access_date()
        if not current_user.is_confirmed \
                and request.endpoint \
                and request.endpoint[:5] != 'auth.'\
                and request.endpoint != 'static':
            return redirect(url_for('auth.unconfirmed'))

@auth.route('/unconfirmed')
def unconfirmed():
    if current_user.is_anonymous or current_user.is_confirmed:
        return redirect(url_for('main.index'))
    return render_template('auth/unconfirmed.html')

@auth.route('/')
@fresh_login_required
def index():
    pass

@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and user.verify_password(form.password.data):
            flash(u'已成功登录', 'success')
            login_user(user, form.remeber_me.data)
            return redirect(url_for('main.index'))
        flash(u'用户名或密码错误', 'danger')
        return redirect(url_for('auth.login'))
    return render_template('auth/login.html', form=form)

@auth.route('/logout', methods=['GET', 'POST'])
@fresh_login_required
def logout():
    logout_user()
    flash(u'已退出登录', 'success')
    return redirect(url_for('main.index'))

@auth.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = User(email=form.email.data,
                    username=form.username.data,
                    password=form.password.data)
        db.session.add(user)
        db.session.commit()
        token = user.generate_confirm_token(expires_in=3600)
        flash(u'确认已发送至你的邮箱,点击激活邮件', 'success')
        send_mail(form.email.data,
                  u'Flasky - 注册确认邮件',
                  'auth/email/confirm',
                  user=user, token=token)
        return redirect(url_for('main.index'))
    return render_template('auth/register.html', form=form)

@auth.route('/confirm')
@login_required
def resend_confirmation():
    token = current_user.generate_confirm_token()
    send_mail(current_user.email,
              u'Flasky - 注册确认邮件',
              'auth/email/confirm',
              user=current_user, token=token)
    flash(u'一封新的确认邮件已经发送至你的邮箱')
    return redirect(url_for('main.index'))

@auth.route('/confirm/<token>')
@login_required
def confirm(token):
    if current_user.verify_confirm_token(token):
        flash(u'邮箱验证通过', 'success')
        return redirect(url_for('main.index'))
    flash(u'确认连接已失效', 'danger')
    return redirect(url_for('main.index'))
loginmanager.anonymous_user = AnonymousUser

说明:每次收到请求时调用current_user对象的refresh_access_date方法,由于auth中注册的是全局的before_app_request处理程序,在每次请求前运行,所以很容易实现更新访问时间的功能

转载于:https://my.oschina.net/pydevops/blog/702399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值