Flaskプロジェクトの構築とログイン、登録(メールボックス検証)の実現
13922 ワード
一、プロジェクト構造:
1、プロファイル:
2、起動項目
3、三方ライブラリ集合requirements.txt
ワンタッチでプラグインライブラリをインストールするには:
4、メールボックスプロファイルの送信
5、仮想環境:前述したように、cmdで仮想環境を作成するルートディレクトリを開き、コマンドvirtualenv venv(仮想環境名、カスタマイズ)を実行して作成します.
仮想環境の作成
6、app:つまりアプリケーション全体の核心で、私は手動で作成したフォルダで、appと命名しました.
6.1、初期ファイル:工場関数(create_app(config)を含む.その中のパラメータは配置ファイルの中の配置名、データベースのインスタンス化データベース、メールボックス、時間フォーマット、bootstrapなどである.
6.2、データベースモデル(models):
######6.3、ユーザーファイル(auth):(初期ファイル(青写真作成)、formsファイル(フォーム作成)、viewsファイル(ビュー関数)を含む).
6.3.1、ユーザー初期化(青写真作成):
6.3.2、formsファイル(フォーム作成):
フォームlogin
6.3.3、viewsビュー関数:
6.4、mainファイル:(初期ファイルも青写真作成)、viewsビュー関数.
6.4.1、初期関数:
6.4.2、ビュー関数:
7.静的スタイルファイル:(主にスタイル(css、jsなど)を含む)
8.静的テンプレートファイル:(主にHTMLテンプレート)
最後に、青写真、ビュー関数に基づいて、各モジュールとテンプレートを並べて、クリック登録を実現することができます.フォームに追加された資料をデータベースに書き込み、同時にメールボックス検証を送信します(初期検証フィールドはデータベースのデフォルト値が0(Flase)、ユーザーが自分のメールボックスに送信した検証リンクをクリックし、データのフィールドを1(True)に変更します.あ、秘密暗号化もあります.flaskには暗号化データに便利なモジュールがあります.itsdangerousパッケージのT i m e d J S S S o n W e b SignatureSerializerはフィールドを暗号解読することができます.アカウント、ユーザー名が使用されたかどうかは、フォームに入力された内容をデータライブラリのフィールドと最も一致させ、存在するかどうかを確認します.
|--mytest
|--app/
|--init.py--
|--models.py--
|--auth/
|--init.py--
|--forms.py--auth
|--views.py--auth
|--main/
|--init.py--main
|--views.py--
|--static/--
|--templates/--
|--venv--
|--config.py--
|--emailTest.py--
|--etc.py--
|--manage.py--
|--requirements.txt--
1、プロファイル:
#-- coding:utf-8 --
class Config(object):
'''
1
2
'''
SECRET_KEY = "Ay98Cct2oNSlnHDdTl8"
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
# SQLALCHEMY_TRACK_MODIFICATIONS = True
@staticmethod
def init_app(app):
pass
class LastConfig(Config):
'''
'''
DEBUG = True
#SQLALCHEMY_ECHO = True
# 、 username ,password
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://username:password@localhost:3306/test_three"
config = {'default':LastConfig, 'test':TestConfig}
2、起動項目
# -- coding:utf-8 --
from app import create_app, db
from flask_script import Manager, Shell
from etc import default
# app
app = create_app(default)
# Manager
manager = Manager(app)
def make_shell_context():
return dict(app=app, db=db)
#
manager.add_command("shell", Shell(make_context=make_shell_context))
#
if name == "main":
manager.run()
3、三方ライブラリ集合requirements.txt
alembic==0.8.8
blinker==1.4
click==6.6
dominate==2.2.1
Flask==0.11.1
Flask-Bootstrap==3.3.7.0
Flask-Mail==0.9.1
Flask-Migrate==2.0.0
Flask-Moment==0.5.1
Flask-Script==2.0.5
Flask-SQLAlchemy==2.1
Flask-WTF==0.12
itsdangerous==0.24
Jinja2==2.8
Mako==1.0.4
MarkupSafe==0.23
python-editor==1.0.1
SQLAlchemy==1.0.15
visitor==0.1.3
Werkzeug==0.11.11
WTForms==2.1
Flask-Login==0.3.1
ワンタッチでプラグインライブラリをインストールするには:
pip install -r requirements.txt
4、メールボックスプロファイルの送信
# -- coding:utf-8 --
from flask import Flask,render_template
from flask_mail import Mail, Message
app = Flask(name)
'''
1
2
3
4
'''
app.config.update(
MAIL_SERVER='smtp.qq.com',
MAIL_PORT='465',
MAIL_USE_SSL=True,
MAIL_USERNAME='QQ ',
MAIL_PASSWORD=' '#( )
)
mail = Mail(app)
def send_email(to,subject,template,user,token):
'''
1 Message
2
3
'''
msg = Message(subject, sender=' QQ ', recipients=[to])
msg.html = render_template(template + '.txt', user=user,token=token)
mail.send(msg)
5、仮想環境:前述したように、cmdで仮想環境を作成するルートディレクトリを開き、コマンドvirtualenv venv(仮想環境名、カスタマイズ)を実行して作成します.
仮想環境の作成
virtualenv venv
python -m venv venv
6、app:つまりアプリケーション全体の核心で、私は手動で作成したフォルダで、appと命名しました.
6.1、初期ファイル:工場関数(create_app(config)を含む.その中のパラメータは配置ファイルの中の配置名、データベースのインスタンス化データベース、メールボックス、時間フォーマット、bootstrapなどである.
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from config import config
#
bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
mail.init_app(app)
moment.init_app(app)
db.init_app(app)
login_manager.init_app(app)
# ,
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
return app
6.2、データベースモデル(models):
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
### flask_login UserMixin
###USerMixin 。
from . import db, login_manager
### login_manager
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
##
from flask import current_app
class Role(db.Model):
'''
1 、 id、
'''
__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 '' % self.name
class User(UserMixin, db.Model):
'''
1 User UserMixin db.Model
2 users、id、email、username、role_id、password_hash( ),confirmed( )
3 、
4 Unicode
5 , , None。
'''
__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))
confirmed = db.Column(db.Boolean,default=False)
@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)
def __repr__(self):
return '' % self.username
#expiration ,
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
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
######6.3、ユーザーファイル(auth):(初期ファイル(青写真作成)、formsファイル(フォーム作成)、viewsファイル(ビュー関数)を含む).
6.3.1、ユーザー初期化(青写真作成):
from flask import Blueprint
auth = Blueprint('auth',__name__)
from . import views
6.3.2、formsファイル(フォーム作成):
from flask_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
フォームlogin
class LoginForm(Form):
'''
1 。StringField validators , 。
2 WTForms Length() Email() 。
3 PasswordField type="password" < input> 。
4 BooleanField 。
'''
email = StringField('Email', validators=[Required(), Length(1, 64), Email()])
password = PasswordField(' ', validators=[Required()])
remember_me = BooleanField(' ')
submit = SubmitField(' ')
# Registration
class RegistrationForm(Form):
'''
1
2 ( 、 、 、 、 )
3
4
'''
email = StringField('Email',validators=[Required(),Length(1,64),Email()])
username = StringField(' ',validators=[Required(),Length(1,64),Regexp('^[A-Za-z][A-Za-z0-9_.]*$',\
0,'Usernames must have only letter,numbers,dots or underscores')])
password = PasswordField(' ',validators=[Required(),EqualTo('password2',message=' .')])
password2 = PasswordField(' ',validators=[Required()])
submit = SubmitField(' ')
def validate_email(self,field):
if User.query.filter_by(email=field.data).first():
raise ValidationError('Email .')
def validata_username(self,field):
if User.query.filter_by(username=field.data).first():
raise ValidationError(' .')
6.3.3、viewsビュー関数:
from flask import render_template, redirect, request, url_for, flash
from flask_login import login_user, logout_user, login_required
from . import auth
from ..models import User
from .forms import LoginForm
from .forms import RegistrationForm
from .. import db
from emailTest import send_email
from flask.ext.login import current_user
@auth.route('/login', methods=['GET', 'POST'])
### GET , , POST , , 。
def login():
flash(' .')
'''
1
2 ,
3 email
4 user , , , Flask_Login login_user() ,
5 flash 。
6 login_user , ‘ ’ 。
7 url ,Flask-Login next , request.args 。 next , 。
'''
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.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(' .')
return render_template('auth/login.html', form=form)
@auth.route('/logout')
###
@login_required
###
def logout():
'''
1 , logout_user() , 。
'''
logout_user()
flash(' !')
return redirect(url_for('main.index'))
###
@auth.route('/register',methods=['GET','POST'])
def register():
'''
1
2 , , ,
'''
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,' ','auth/email/confirm',user,token)
flash(' !')
return redirect(url_for('main.index'))
# return redirect(url_for('auth.login'))
##
return render_template('auth/register.html',form=form)
#
@auth.route('/confirm/')
@login_required
def confirm(token):
'''
1 confirmed True, flash ,
'''
if current_user.confirmed:
return redirect(url_for('main.index'))
if current_user.confirm(token):
flash(' , ')
else:
flash(' , ')
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():
'''
confirmed True, False(0),
'''
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, ' ',
'auth/email/confirm', current_user, token)
flash(' , .')
return redirect(url_for('main.index'))
6.4、mainファイル:(初期ファイルも青写真作成)、viewsビュー関数.
6.4.1、初期関数:
from flask import Blueprint
main = Blueprint('main', __name__)
from .views import *
6.4.2、ビュー関数:
from . import main
from .. import auth
from flask import render_template, request
from app import db
from sqlalchemy import or_
from flask import redirect, url_for
@main.route('/')
def index():
# return render_template('index.html')
return redirect(url_for('auth.login'))
@main.route('/index')
def index1():
return render_template('index.html')
7.静的スタイルファイル:(主にスタイル(css、jsなど)を含む)
8.静的テンプレートファイル:(主にHTMLテンプレート)
最後に、青写真、ビュー関数に基づいて、各モジュールとテンプレートを並べて、クリック登録を実現することができます.フォームに追加された資料をデータベースに書き込み、同時にメールボックス検証を送信します(初期検証フィールドはデータベースのデフォルト値が0(Flase)、ユーザーが自分のメールボックスに送信した検証リンクをクリックし、データのフィールドを1(True)に変更します.あ、秘密暗号化もあります.flaskには暗号化データに便利なモジュールがあります.itsdangerousパッケージのT i m e d J S S S o n W e b SignatureSerializerはフィールドを暗号解読することができます.アカウント、ユーザー名が使用されたかどうかは、フォームに入力された内容をデータライブラリのフィールドと最も一致させ、存在するかどうかを確認します.