专栏首页sktjpython flask web基本结构 登录模块 常用

python flask web基本结构 登录模块 常用

需要的包

flask-login werkzeug itsdangerous flask-mail flask-bootstrap flask-wtf

1、 app/models.py from werkzeug.security import generate_password_hash, check_password_hash from flask.ext.login import UserMixin,AnonymousUserMixin from . import login_manager from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from flask import current_app from . import db login_manager.anonymous_user = AnonymousUser class User(UserMixin, db.Model): tablename = 'users' id = db.Column(db.Integer, primary_key = True) email = db.Column(db.String(64), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) password_hash = db.Column(db.String(128)) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) password_hash = db.Column(db.String(128)) confirmed = db.Column(db.Boolean, default=False) def init(self, kwargs): super(User, self).init(kwargs) if self.role is None: if self.email == current_app.config['FLASKY_ADMIN']: self.role = Role.query.filter_by(permissions=0xff).first() if self.role is None: self.role = Role.query.filter_by(default=True).first() def can(self, permissions): return self.role is not None and (self.role.permissions & permissions) ==permissions def is_administrator(self): return self.can(Permission.ADMINISTER) @property def password(self): raise AttributeError('password is not a readable attribute') @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) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}) def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) return True class AnonymousUser(AnonymousUserMixin): def can(self, permissions): return False def is_administrator(self): return False class Permission: FOLLOW = 0x01 COMMENT = 0x02 WRITE_ARTICLES = 0x04 MODERATE_COMMENTS = 0x08 ADMINISTER = 0x80 class Role(db.Model): tablename = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.Integer) users = db.relationship('User', backref='role', lazy='dynamic') @staticmethod def insert_roles(): roles = { 'User': (Permission.FOLLOW |Permission.COMMENT |Permission.WRITE_ARTICLES, True), 'Moderator': (Permission.FOLLOW |Permission.COMMENT |Permission.WRITE_ARTICLES |Permission.MODERATE_COMMENTS, False), 'Administrator': (0xff, False) } for r in roles: role = Role.query.filter_by(name=r).first() if role is None: role = Role(name=r) role.permissions = roles[r][0] role.default = roles[r][1] db.session.add(role) db.session.commit()

2、app/auth/init.py ##蓝本 from flask import Blueprint auth = Blueprint('auth', name) from . import views

3、 app/auth/views.py #视图 from flask.ext.login import logout_user,login_required from flask import render_template, redirect, request, url_for, flash from flask.ext.login import login_user,current_user from . import auth from ..models import User from .forms import LoginForm from ..email import send_email @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 is None: user =User.query.filter_by(username=form.username .data).first() if user is not None and user.verify_password(form.password.data): login_user(user, form.remember_me.data) return redirect(request.args.get('next') or url_for('main.index')) flash('Invalid username or password.') return render_template('auth/login.html', form=form) @app.route('/secret') @login_required def secret(): return 'Only authenticated users are allowed!' @auth.route('/logout') @login_required def logout(): logout_user() flash('You have been logged out.') return redirect(url_for('main.index')) @auth.route('/register', methods=['GET', 'POST']) def register(): form = RegistrationForm() 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_confirmation_token() send_email(user.email, 'Confirm Your Account','auth/email/confirm', user=user, token=token) flash('A confirmation email has been sent to you by email.') return redirect(url_for('auth.login')) return render_template('auth/register.html', form=form) @auth.route('/confirm/<token>') @login_required def confirm(token): if current_user.confirmed: return redirect(url_for('main.index')) if current_user.confirm(token): flash('You have confirmed your account. Thanks!') else: flash('The confirmation link is invalid or has expired.') return redirect(url_for('main.index')) @auth.before_app_request def before_request(): if current_user.is_authenticated() and not current_user.confirmed 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.confirmed: return redirect(url_for('main.index')) return render_template('auth/unconfirmed.html') @auth.route('/confirm') @login_required def resend_confirmation(): token = current_user.generate_confirmation_token() send_email(current_user.email, 'Confirm Your Account','auth/email/confirm', user=current_user, token=token) flash('A new confirmation email has been sent to you by email.') return redirect(url_for('main.index'))

4 app/__init__py #附加蓝本 from flask.ext.login import LoginManager from .auth import auth as auth_blueprint login_manager = LoginManager() login_manager.session_protection = 'strong' login_manager.login_view = 'auth.login' def create_app(config_name): # ... login_manager.init_app(app) app.register_blueprint(auth_blueprint, url_prefix='/auth') return app

5 app/auth/forms.py #登录表单 from flask.ext.wtf import Form from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import Required, Length, Email, Regexp, EqualTo from wtforms import ValidationError from ..models import User

class LoginForm(Form): email = StringField('Email', validators=[Required(), Length(1, 64),Email()]) password = PasswordField('Password', validators=[Required()]) remember_me = BooleanField('Keep me logged in') submit = SubmitField('Log In')

class RegistrationForm(Form): email = StringField('Email', validators=[Required(), Length(1, 64),Email()]) username = StringField('Username', validators=[Required(), Length(1, 64),Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,'Usernames must have only letters:numbers, dots or underscores')]) password = PasswordField('Password', validators=[Required(), EqualTo('password2',message='Passwords must match.')]) password2 = PasswordField('Confirm password', validators=[Required()]) submit = SubmitField('Register') def validate_email(self, field): if User.query.filter_by(email=field.data).first(): raise ValidationError('Email already registered.') def validate_username(self, field): if User.query.filter_by(username=field.data).first(): raise ValidationError('Username already in use.')

6 app/templates/base.html ##基础模板中添加登录、登出 {% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block head %} {{ super() }} <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}"> {% endblock %}

{% block navbar %} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="{{ url_for('main.index') }}">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="{{ url_for('main.index') }}">Home</a></li> {% if current_user.is_authenticated %} <li><a href="{{ url_for('main.user', username=current_user.username) }}">Profile</a></li> {% endif %} </ul> <ul class="nav navbar-nav navbar-right"> {% if current_user.can(Permission.MODERATE_COMMENTS) %} <li><a href="{{ url_for('main.moderate') }}">Moderate Comments</a></li> {% endif %} {% if current_user.is_authenticated %} <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <img src="{{ current_user.gravatar(size=18) }}"> Account <b class="caret"></b> </a> <ul class="dropdown-menu"> <li><a href="{{ url_for('auth.change_password') }}">Change Password</a></li> <li><a href="{{ url_for('auth.change_email_request') }}">Change Email</a></li> <li><a href="{{ url_for('auth.logout') }}">Log Out</a></li> </ul> </li> {% else %} <li><a href="{{ url_for('auth.login') }}">Log In</a></li> {% endif %} </ul> </div> </div> </div> {% endblock %}

{% block content %} <div class="container"> {% for message in get_flashed_messages() %} <div class="alert alert-warning"> <button type="button" class="close" data-dismiss="alert">×</button> {{ message }} </div> {% endfor %}

{% block page_content %}{% endblock %}

</div> {% endblock %}

{% block scripts %} {{ super() }} {{ moment.include_moment() }} {% endblock %}

7 app/templates/auth/login.html #登录页面 {% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky - Login{% endblock %} {% block page_content %} <div class="page-header"> <h1>Login</h1> </div> <div class="col-md-4"> {{ wtf.quick_form(form) }} </div> <p> New user? <a href="{{ url_for('auth.register') }}"> Click here to register </a> </p> {% endblock %}

8 app/templates/index.html ##首页 Hello, {% if current_user.is_authenticated() %} {{ current_user.username }} {% else %} Stranger {% endif %}!

9 app/templates/auth/email/confirm.txt #确认邮件 Dear {{ user.username }}, Welcome to Flasky! To confirm your account please click on the following link: {{ url_for('auth.confirm', token=token, _external=True) }} Sincerely, The Flasky Team Note: replies to this email address are not monitored.

10 app/decorators.py ##自定义权限修饰器 from functools import wraps from flask import abort from flask.ext.login import current_user def permission_required(permission): def decorator(f): @wraps(f) def decorated_function(*args, *kwargs): if not current_user.can(permission): abort(403) return f(args, **kwargs) return decorated_function return decorator def admin_required(f): return permission_required(Permission.ADMINISTER)(f)

11、app/main/init.py @main.app_context_processor def inject_permissions(): return dict(Permission=Permission)

数据库: python manage.py db upgrade

手动添加用户:

(venv) $ python manage.py shell

u = User(email='john@example.com', username='john', password='cat') db.session.add(u) db.session.commit()

插入角色

(venv) $ python manage.py shell

Role.insert_roles() Role.query.all()

权限表

image.png

image.png

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • flask 数据库关系(flask 28)

    class Writer(db.Model): books=db.relationship('Book',back_populates='writer') ...

    用户5760343
  • python flask web开发实战 DB flask-sqlalchemy

    MySQL mysql://username:password@hostname/database Postgres postgresql://usernam...

    用户5760343
  • flask 邻接列表关系(flask 48)

    class Comment(db.Model): id = db.Column(db.Integer, primary_key=True) author =...

    用户5760343
  • mongo的身份验证和授权

    刚装好的mongo,准备登陆进去测一把的,结果就给我报这个错,鄙人是新手,还不太清楚这个,现学一下~

    拓荒者
  • 网站---不要相信浏览器

    1、当提交的时候用。return checkForm() 这个方法。 2、服务器断的代码不可少,JavaScript 校验只是“可用性”考虑,而服务器端的校验才...

    静心物语313
  • Docker容器无法启动,里面的配置文件如何修改

    当修改一个容器, 如mysql里的配置文件/etc/mysql/my.cnf , 修改完成后重启mysql 容器, 使用docker ps -a 查看容器,显示...

    louiezhou001
  • flask 数据库迁移(flask 29)

    app=Flask(name) db=SQLAlchemy(app) migrate=Migrate(app,db)

    用户5760343
  • 简单代码让WordPress 支持电子邮箱(Email)作为登录名

    在谷歌中以“Email 登陆 WordPress”为关键词搜索,发现代码都是很长很复杂的,都快比上旧社会女人的裹脚布了。偶然发现一段较简单的代码可以实现Word...

    Jeff
  • vn.py2-行情记录的使用

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    钱塘小甲子
  • Ps回调函数.拦截驱动模块原理+实现.

    主要是讲解.内核中如何拦截模块加载的. 需要熟悉.内核回调的设置 PE知识. ShellCode

    IBinary

扫码关注云+社区

领取腾讯云代金券