目录如下:
my_flasky
│ config.py
│ config.pyc
│ data-dev.sqlite
│ manage.py
│
└─app
│ models.py
│ models.pyc
│ __init__.py
│ __init__.pyc
│
├─auth
│ forms.py
│ forms.pyc
│ views.py
│ views.pyc
│ __init__.py
│ __init__.pyc
│
├─main
│ views.py
│ views.pyc
│ __init__.py
│ __init__.pyc
│
└─templates
│ base.html
│ index.html
│
└─auth
login.html
register.html
要实现登录,注册功能,需要实现的具体功能有:
1,数据库(SQLAlchemy):在app/models中构造User和Role模块,使用时只需要调用,代码如下:
#encoding:utf8
from werkzeug.security import generate_password_hash,check_password_hash
from . import db
from flask_login import UserMixin
from . import login_manager
class Role(db.Model):
#定义Role的数据库模型
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
users = db.relationship('User', backref='role', lazy='dynamic')
def __repr__(self):
return '<Role %r>' % self.name
class User(db.Model,UserMixin):
#定义User的数据库模型
__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)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128)) #这里传入的是加密后的密码
@property
def password(self):
#增加密码的不可读属性,防止密码泄露
raise AttributeError('password is not readable')
@password.setter
def password(self,password):
#将传入的密码进行加密
self.password_hash = generate_password_hash(password)
def verify_password(self,password):
#定义比较密码的方法:传入用户输入的密码,返回bool值
return check_password_hash(self.password_hash,password)
def __repr__(self):
return '<User %r>' % self.username
@login_manager.user_loader
def load_user(user_id):
#登录状态管理
return User.query.get(int(user_id))
2,前端表格(wtform):在app/auth/forms.py中使用flask-wtform对前端表格构造,wtforms将前端的东西进行了抽象,我们可以通过python的方法完成前端东西的构造,构造完成之后只需将它用jinja2语法写入模板之中,代码如下:
from flask_wtf import Form
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import Required, Length, Email,Regexp,EqualTo
from ..models import User
from wtforms import ValidationError
class LoginForm(Form):
#登录表格
email = StringField('Email', validators=[Required(),
Length(1,64), Email()]) #验证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.')
模板中代码如下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) }}
<br>
<p>New user? <a href="{{ url_for('auth.register') }}">Click here to register</a>.</p>
</div>
{% endblock %}
app/templates/auth/register.html
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky - Register{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Register</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
最后,在app/init.py中的create_app中进行蓝图注册,app初始化,代码如下:
#encoding:utf8
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from config import Config
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_views = 'auth.login'
bootstrap = Bootstrap()
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
Config.init_app(app)
#初始化所要用到的模块
login_manager.init_app(app)
bootstrap.init_app(app)
db.init_app(app)
#从/main/__init__.py中获取蓝图,并注册蓝图
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
return app
完成之后先用直接在数据库中插入用户密码,测试登录成功。注册之后显示成功,但是用注册的号进行登录无法成功。原因是在app/auth/views.py中没有对插入数据库的内容进行保存,解决方案是在这里面直接加入
db.session.commit()
或者在配置文件中加入
SQLALCHEMY_COMMIT_ON_TEARDOWN = True