返回顶部

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)  # 订单的评论信息或者拒单原因
View Code

 在 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]
View Code

 

在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
View Code

 

 

把上接口中的蓝图注册到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
View Code

 

在浏览器中测试,输入

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'

  

 

posted @ 2017-11-30 21:18  Crazymagic  阅读(173)  评论(0)    收藏  举报