定义模板
父类模板 -- base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
{% endblock %}
</title>
{% block extCss %}
{% endblock %}
{% block extJs %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
父类基础模板 -- base_main.html
链接资源文件中的父目录下的css文件/JS文件和后缀名为.min.xxx的文件。
{% extends 'base.html' %}
{% block extCss %}
<link href="{{ url_for('static',filename='/css/reset.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/bootstrap-datepicker/css/bootstrap-datepicker.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/bootstrap-switch/css/bootstrap-switch.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/font-awesome/css/font-awesome.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/swiper/css/swiper.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static',filename='/plugins/uniform/css/uniform.default.min.css') }}" rel="stylesheet">
{% endblock %}
{% block extJs %}
<link href="{{ url_for('static',filename='/js/jquery.blockui.min.js') }}" rel="script">
<link href="{{ url_for('static',filename='/js/jquery.form.min.js') }}" rel="script">
<link href="{{ url_for('static',filename='/js/jquery.min.js') }}" rel="script">
<link href="{{ url_for('static',filename='/js/template.js') }}" rel="script">
{% endblock %}
注册界面
{% extends 'base_main.html' %}
{% block title %}
爱家-注册
{% endblock %}
{% block extCss %}
{{ super() }}
<link href="{{ url_for('static', filename = 'css/ihome/main.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename = 'css/ihome/register.css') }}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="container">
<div class="logo-bar"><a href="/"><img src="/static/images/logo@128x59.png"></a></div>
<form class="form-register">
<div class="form-group form-group-lg">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-mobile fa-2x fa-fw"></i></div>
<input type="number" class="form-control" name="mobile" id="mobile" placeholder="手机号" required>
</div>
</div>
<div class="error-msg" id="mobile-err"><i class="fa fa-exclamation-circle"></i><span></span></div>
<div class="form-group form-group-lg">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-image fa-lg fa-fw"></i></div>
<input type="text" class="form-control" name="imagecode" id="imagecode" placeholder="图片验证码" required>
<div class="input-group-addon image-code" onclick="generateImageCode();"><img src=""></div>
</div>
</div>
<div class="error-msg" id="image-code-err"><i class="fa fa-exclamation-circle"></i><span></span></div>
<div class="form-group form-group-lg">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-envelope-o fa-lg fa-fw"></i></div>
<input type="text" class="form-control" name="phonecode" id="phonecode" placeholder="短信验证码" required>
<div class="phonecode input-group-addon">
<a class="phonecode-a" href="javascript:;" onclick="sendSMSCode();">获取验证码</a>
</div>
</div>
</div>
<div class="error-msg" id="phone-code-err"><i class="fa fa-exclamation-circle"></i><span></span></div>
<div class="form-group form-group-lg">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-lock fa-lg fa-fw"></i></div>
<input type="password" class="form-control" name="password" id="password" placeholder="密码" required>
</div>
</div>
<div class="error-msg" id="password-err"><i class="fa fa-exclamation-circle"></i><span></span></div>
<div class="form-group form-group-lg">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-lock fa-lg fa-fw"></i></div>
<input type="password" class="form-control" name="password2" id="password2" placeholder="确认密码" required>
</div>
</div>
<div class="error-msg" id="password2-err"><i class="fa fa-exclamation-circle"></i><span></span></div>
<button type="submit" class="btn btn-lg btn-theme btn-block">立即注册</button>
<p class="login-a">已有账号,<a href="/login.html">立即登陆</a></p>
</form>
</div>
{% endblock %}
{% block extJs %}
{{ super() }}
<script src="{{ url_for('static',filename = 'plugins/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static',filename = 'js/ihome/register.js') }}"></script>
{% endblock %}
定义模型
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class BaseModel(object):
# 定义基础的模型
create_time = db.Column(db.DATETIME, default=datetime.now)
update_time = db.Column(db.DATETIME, default=datetime.now, onupdate=datetime.now)
def add_update(self):
db.session.add(self)
db.session.commit()
def delete(self):
db.session.delete(self)
db.session.commit()
class User(BaseModel, db.Model):
__tablename__ = 'ihome_user'
id = db.Column(db.INTEGER, primary_key=True, autoincrement=True)
phone = db.Column(db.String(11), unique=True)
pwd_hash = db.Column(db.String(200))
name = db.Column(db.String(30), unique=True)
avatar = db.Column(db.String(100)) # 头像
id_name = db.Column(db.String(30)) # 实名认证的姓名
id_card = db.Column(db.String(18), unique=True) # 实名认证的身份证号码
houses = db.relationship('House', backref='user')
orders = db.relationship('Order', backref='user')
# 读
@property
def password(self):
return ''
# 写
@password.setter
def password(self, pwd):
self.pwd_hash = generate_password_hash(pwd)
# 对比
def check_pwd(self, pwd):
return check_password_hash(self.pwd_hash, pwd)
def to_auth_dict(self):
return {
'id_name': self.id_name,
'id_card': self.id_card
}
def to_basic_dict(self):
return {
'id': self.id,
'avatar': self.avatar if self.avatar else '',
'name': self.name,
'phone': self.phone
}
修改启动文件,绑定数据库,完成相关配置
from app.models import db
app.config['SECRET_KEY'] = 'secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@127.0.0.1:3306/aj'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
实现注册功能
在用户逻辑文件user_views.py中,引入蓝图管理路由并进入启动文件中绑定
app.register_blueprint(blueprint=user_blueprint, url_prefix='/user')
业务逻辑
生成数据表 --> 生成验证码 --> 获取注册信息验证合法后注册用户写入数据库
@user_blueprint.route('/create_db/', methods=['GET'])
def create_db():
"""
创建数据表
"""
db.create_all()
return '创建成功'
@user_blueprint.route('/get_code/', methods=['GET'])
def get_code():
"""
生成验证码
"""
code = ''
s = '1234567890qwertyuiopasdfghjklzxcvbnm'
for i in range(4):
code += random.choice(s)
session['code'] = code
return jsonify(code=200, msg='请求成功', data=code)
@user_blueprint.route('/register/', methods=['GET', 'POST'])
def register():
"""
注册
"""
if request.method == 'GET':
"""
跳转至注册页面
"""
return render_template('register.html')
if request.method == 'POST':
"""
注册用户
"""
mobile = request.form.get('mobile')
imageCode = request.form.get('imageCode')
password = request.form.get('password')
password2 = request.form.get('password2')
# 效验参数完整
if not all([mobile, imageCode, password, password2]):
return jsonify(status_code.USER_NOT_ALL)
# 效验手机号是否合法
if not re.match(r'^1[3456789]\d{9}$', mobile):
return jsonify(status_code.USER_MOBILE_ERROR)
# 效验验证码是否正确
if session.get('code') != imageCode:
return jsonify(status_code.USER_IMAGECODE_ERROR)
# 效验密码一致性
if password != password2:
return jsonify(status_code.USER_PASSWORD_ERROR)
# 效验用户是否已存在
if User.query.filter(User.phone == mobile).count():
return jsonify(status_code.USER_ERROR)
# 创建用户信息
user = User()
user.phone = mobile
user.password = password
user.name = mobile
try:
user.add_update()
return jsonify(status_code.SUCCESS)
except:
return jsonify(status_code.DATABASE_ERROR)
局部刷新图片验证码的Ajax
function generateImageCode() {
$.ajax({
url: "/user/get_code/",
type: "GET",
dataType: "json",
success: function(data){
if(data.code == '200'){
$('#yanzhengma').html(data.data)
}
}
});
}
局部提交注册信息的Ajax
$.ajax({
url:'/user/register/',
type:'POST',
dataType:'json',
data:{'mobile':mobile, 'imageCode':imageCode,'password':password, 'password2':password2},
success: function(msg){
alert(msg.msg);
if(msg.code == '200'){
location.href='/user/login/';
}
},
error: function(msg){
console.log(msg)
}
});