2 数据库迁移和短信验证
数据库迁移
在ihome目录下创建modls.py,代码如下
# -*- coding:utf-8 -*- from datetime import datetime from . import db class BaseModel(object): """模型基类,为每个模型补充创建时间与更新时间""" create_time = db.Column(db.DateTime, default=datetime.now) # 记录的创建时间 update_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now) # 记录的更新时间 class User(BaseModel, db.Model): """用户""" __tablename__ = "ih_user_profile" id = db.Column(db.Integer, primary_key=True) # 用户编号 name = db.Column(db.String(32), unique=True, nullable=False) # 用户暱称 password_hash = db.Column(db.String(128), nullable=False) # 加密的密码 mobile = db.Column(db.String(11), unique=True, nullable=False) # 手机号 real_name = db.Column(db.String(32)) # 真实姓名 id_card = db.Column(db.String(20)) # 身份证号 avatar_url = db.Column(db.String(128)) # 用户头像路径 # 在一的一方, 添加relationship, 同时添加反向引用 houses = db.relationship("House", backref="user") # 用户发布的房屋 orders = db.relationship("Order", backref="user") # 用户下的订单 class Area(BaseModel, db.Model): """城区""" __tablename__ = "ih_area_info" id = db.Column(db.Integer, primary_key=True) # 区域编号 name = db.Column(db.String(32), nullable=False) # 区域名字 houses = db.relationship("House", backref="area") # 区域的房屋 # 房屋设施表,建立房屋与设施的多对多关系 # 如果是多对多, 直接操作底层的表 house_facility = db.Table( "ih_house_facility", db.Column("house_id", db.Integer, db.ForeignKey("ih_house_info.id"), primary_key=True), # 房屋编号 db.Column("facility_id", db.Integer, db.ForeignKey("ih_facility_info.id"), primary_key=True) # 设施编号 ) class House(BaseModel, db.Model): """房屋信息""" __tablename__ = "ih_house_info" id = db.Column(db.Integer, primary_key=True) # 房屋编号 title = db.Column(db.String(64), nullable=False) # 标题 price = db.Column(db.Integer, default=0) # 单价,单位:分 address = db.Column(db.String(512), default="") # 地址 room_count = db.Column(db.Integer, default=1) # 房间数目 acreage = db.Column(db.Integer, default=0) # 房屋面积 unit = db.Column(db.String(32), default="") # 房屋单元, 如几室几厅 capacity = db.Column(db.Integer, default=1) # 房屋容纳的人数 beds = db.Column(db.String(64), default="") # 房屋床铺的配置 deposit = db.Column(db.Integer, default=0) # 房屋押金 min_days = db.Column(db.Integer, default=1) # 最少入住天数 max_days = db.Column(db.Integer, default=0) # 最多入住天数,0表示不限制 order_count = db.Column(db.Integer, default=0) # 预订完成的该房屋的订单数 index_image_url = db.Column(db.String(256), default="") # 房屋主图片的路径 user_id = db.Column(db.Integer, db.ForeignKey("ih_user_profile.id"), nullable=False) # 房屋主人的用户编号 area_id = db.Column(db.Integer, db.ForeignKey("ih_area_info.id"), nullable=False) # 归属地的区域编号 # 如果是多对多, 只需要在一方增加relationship, 同时需要告诉他第三张表的名字 facilities = db.relationship("Facility", secondary=house_facility) # 房屋的设施 images = db.relationship("HouseImage") # 房屋的图片 orders = db.relationship("Order", backref="house") # 房屋的订单 class Facility(BaseModel, db.Model): """设施信息""" __tablename__ = "ih_facility_info" id = db.Column(db.Integer, primary_key=True) # 设施编号 name = db.Column(db.String(32), nullable=False) # 设施名字 class HouseImage(BaseModel, db.Model): """房屋图片""" __tablename__ = "ih_house_image" id = db.Column(db.Integer, primary_key=True) url = db.Column(db.String(256), nullable=False) # 图片的路径 house_id = db.Column(db.Integer, db.ForeignKey("ih_house_info.id"), nullable=False) # 房屋编号 class Order(BaseModel, db.Model): """订单""" __tablename__ = "ih_order_info" id = db.Column(db.Integer, primary_key=True) # 订单编号 user_id = db.Column(db.Integer, db.ForeignKey("ih_user_profile.id"), nullable=False) # 下订单的用户编号 house_id = db.Column(db.Integer, db.ForeignKey("ih_house_info.id"), nullable=False) # 预订的房间编号 begin_date = db.Column(db.DateTime, nullable=False) # 预订的起始时间 end_date = db.Column(db.DateTime, nullable=False) # 预订的结束时间 days = db.Column(db.Integer, nullable=False) # 预订的总天数 house_price = db.Column(db.Integer, nullable=False) # 房屋的单价 amount = db.Column(db.Integer, nullable=False) # 订单的总金额 status = db.Column( # 订单的状态 db.Enum( "WAIT_ACCEPT", # 待接单, "WAIT_PAYMENT", # 待支付 "PAID", # 已支付 "WAIT_COMMENT", # 待评价 "COMPLETE", # 已完成 "CANCELED", # 已取消 "REJECTED" # 已拒单 ), default="WAIT_ACCEPT", index=True) comment = db.Column(db.Text) # 订单的评论信息或者拒单原因
在 api_1_0/index.py中导入数据库模型
from ihome import models
创建迁移脚本
python manage.py db init
执行迁移
python manage.py db migrate
更新数据库
python manage.py db upgrate
访问静态文件
把所有需要的静态文件放到static目录下
在utils下的commons.py中自定义一个转换器代码如下:
# coding:utf8 from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self, map, *args): super(RegexConverter, self).__init__(map) self.regex = args[0]
在ihome/__init__中把自定义的转化器添加到路由转换列表中
app.url_map.converters['re'] = RegexConverter
在ihome下创建web_html.py的文件中定义一个可以访问静态文件的接口,并设置csfr_cookie代码如下:
# coding:utf8 from flask import Blueprint, current_app,make_response from flask_wtf.csrf import generate_csrf html = Blueprint('html', __name__) @html.route("/<re(r'.*'):file_name>") def get_html_file(file_name): if not file_name: file_name = 'index.html' if file_name != 'favicon.ico': file_name = 'html/' + file_name # 设置csrf csrf_tokrn = generate_csrf() resp = make_response(current_app.send_static_file(file_name)) resp.set_cookie('csrf_token', csrf_tokrn) return resp
把上接口中的蓝图注册到app中
在ihome/__init__中注册html的蓝图
from web_html import html app.register_blueprint(html)
在浏览器中输入
http://127.0.0.1:5000/login

图片验证码
这里使用的是capacha的包生成的验证码,把这个包放到ihome/utls的包中.
在api_1_0的包中创建verify_code.py的验证码的接口
其内部主要实现的逻辑是,引用api的蓝图把接口放到api的蓝图中,
把图片验证码对应的id和值保存到redis中,在返回给前端
使用图片验证码的流程

代码如下:
# coding=utf-8 import logging from . import api from ihome.utils.captcha.captcha import captcha from ihome import redis_store from ihome.response_code import RET from flask import jsonify, make_response # 图形验证码 & 短信验证接口 # /api/v1_0/image_codes # image_codes--> 符合第三四条 : 只需要名词变复数 / 获取单个商品需要/后加id @api.route('/image_codes/<image_code_id>') def get_image_code(image_code_id): # 生成了验证码 name, text, image_data = captcha.generate_captcha() # 保存到redis中 setex: 可以设置数据并设置有效期 # 需要三个参数: key , expiretime, value try: redis_store.setex('image_code_' + image_code_id, 180, text) except Exception as e: # 需要存储到日志文件中去 logging.error(e) # 需要返回JSON数据, 以键值对返回 resp = { 'errno': RET.DBERR, 'errmsg': '保存验证码失败' } return jsonify(resp) # 返回响应数据 resp = make_response(image_data) resp.headers['Content-Type'] = 'image/jpg' return resp
在浏览器中测试,输入
http://127.0.0.1:5000/api/v1_0/image_codes/1

图片验证码前端编写代码实现
// 生成验证码编号 uuid imageCodeId = generateUUID(); // 将uuid拼接成url设置到html页面中 var url = "/api/v1_0/image_codes/" + imageCodeId; $(".image-code>img").attr("src", url);
短信验证码(云通讯的使用)
直接下载云通讯中的模块,运行里面的SendTemplateSMS.py即可
对以上知识点的总结:
1 在models.py多对多表的创建的固定写法
# 房屋设施表,建立房屋与设施的多对多关系 # 如果是多对多, 直接操作底层的表 house_facility = db.Table( "ih_house_facility", db.Column("house_id", db.Integer, db.ForeignKey("ih_house_info.id"), primary_key=True), # 房屋编号 db.Column("facility_id", db.Integer, db.ForeignKey("ih_facility_info.id"), primary_key=True) # 设施编号 )
2 app.send_static_file(file_name)方法说明
会在static目录下找传入的file_name文件
3 from flask_wtf.csrf import generate_csrf
调用
csrf_tokrn = generate_csrf()
生成一个唯一的值
4 浏览器会自动的请求 favicon.ico
5 把验证码设置到redis中
redis.setex("键",过期时间,值)
redis_store.setex('image_code_' + image_code_id, 180, text)
6 设置返回的媒体类型
from flask import make_response res = make_respose() resp.headers['Content-Type'] = 'image/jpg'

浙公网安备 33010602011771号