目录

需求文档

创建工程目录以及flask配置

配置日志信息

数据库设计与迁移

静态文件的配置,使浏览器可以正常访问文件

csrf 防护机制


需求文档

需求功能

1. 主页
    1.1 最多5个房屋logo图片展示,点击可跳转至房屋详情页面
    1.2 提供登陆/注册入口,登陆后显示用户名,点击可跳转至个人中心
    1.3 用户可以选择城区、入住时间、离开时间等条件进行搜索
    1.4 城区的区域信息需动态加载

2. 注册
    2.1 用户账号默认为手机号
    2.2 图片验证码正确后才能发送短信验证码
    2.3 短信验证码每60秒可发送一次
    2.4 每个条件出错时有相应错误提示

3. 登陆
    3.1 用手机号与密码登陆
    3.2 错误时有相应提示

4. 房屋列表页
    4.1 可根据入住离开时间、区域进行筛选,并可进行排序
    4.2 房屋信息分页加载
    4.3 区域信息动态加载
    4.4 筛选条件更新后,页面立即刷新

5. 房屋详情页
    5.1 需展示的详细信息参考设计图
    5.2 提供预定入口
    5.3 若是房东本人查看房屋信息时,预定入口不显示

6. 房屋预定
    6.1 由用户确定入住时间
    6.2 根据用户确定的入住离开时间实时显示合计天数与总金额

7. 我的爱家
    7.1 显示个人头像、手机号、用户名(用户名未设置时为用户手机号)
    7.2 提供修改个人信息的入口
    7.3 提供作为房客下单的查询入口
    7.4 提供成为房东所需实名认证的入口
    7.5 提供作为房东发布房屋信息的入口
    7.6 提供作为房东查询客户订单的入口
    7.7 提供退出的入口

8. 个人信息修改
    8.1 可以修改个人头像
    8.2 可以修改用户名
    8.3 登陆手机号不能修改
    8.4 上传头像与用户名分开保存
    8.5 上传新头像后页面理解显示新头像

9. 我的订单(房客)
    9.1 按时间倒序显示订单信息
    9.2 订单完成后提供评价功能
    9.3 已评价的订单能看到评价信息
    9.4 被拒绝的订单能看到拒单原因

10. 实名认证
    10.1 实名认证只可进行一次
    10.2 提交认证信息后再次进入只能查看信息,不能修改
    10.3 认证信息包含姓名与身份证号

11. 我的房源
    11.1 未实名认证的用户不能发布新房源信息,需引导到实名认证页面
    11.2 按时间倒序显示已经发布的房屋信息
    11.3 点击房屋可以进入详情页面
    11.4 对实名认证的用户提供发布新房屋的入口

12. 发布新房源
    12.1 需要用户填写全部房屋信息
    12.2 房屋的文字信息与图片分开操作

13. 客户订单(房东)
    13.1 按时间倒序显示用户下的订单
    13.2 对于新订单提供接单与拒单的功能
    13.3 拒单必须填写拒单原因
    13.4 若客户进行了订单评价,需显示

14. 退出
    14.1 提供退出功能

本节要求:

  1. 创建工程目录以及配置
  2. 日志的配置
  3. 数据库设计与迁移
  4. 静态文件的配置,使浏览器可以正常访问文件

创建工程目录以及flask配置

在项目目录下创建空目录iHome-python04作为flask项目的主工程目录,在ihome-python04目录下创建以下:

ihome(python包)

--init.py

--api_1_0(python 包)

--init.py

config.py(主配置文件)

首先编写config.py配置文件,主要是配置环境,包括基础环境、开发者模式环境以及生产(线上)环境:

#!/usr/bin/env python
# -*- coding: utf-8 -*-import redisclass Config(object):"""基础配置信息"""SECRET_KEY = "js@dhfkjbkjfbsjdfg2"   # 内容随便填# 数据库SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:root3306@127.0.0.1:3306/ihome-python04"SQLALCHEMY_TRACK_MODIFICATIONS = True# redisREDIS_HOST = "127.0.0.1"REDIS_PORT = 6379# flask-session 配置  详细参见:https://pythonhosted.org/Flask-Session/SESSION_TYPE = "redis"SESSION_REDIS = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT)SESSION_USE_SIGNER = True  # 对cookie中的session_id设置隐藏处理PERMANENT_SESSION_LIFETIME = 86400  # session数据的有效期,单位:秒class DevelopmentConfig(Config):"""开发者模式的配置信息"""DEBUG = Trueclass ProductionConfig(Config):"""生产环境的配置信息"""pass# 映射关系
config_map = {"develop": DevelopmentConfig,"product": ProductionConfig,
}

编写ihome下的init.py文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-import redisfrom flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_session import Session
from flask_wtf import CSRFProtectfrom config import config_map# 数据库
db = SQLAlchemy()# 创建redis连接对象
redis_store = None# 工厂模式
def create_app(config_name):"""创建flask的应用对象:param config_name:  str  配置模式的名字  ("develop", "product"):return: app"""# 根据配置模式的名字获取模式的类app = Flask(__name__)config_class = config_map.get(config_name)app.config.from_object(config_class)# 使用app初始化dbdb.init_app(app)# 初始化redisglobal redis_storeredis_store = redis.StrictRedis(host=config_class.REDIS_HOST, port=config_class.REDIS_PORT)# 利用flask-session,将session数据保存到redis中Session(app)# 为flask添加CSRF防护CSRFProtect(app)return app

编写api_1_0下的init.py文件,创建蓝图

from flask import Blueprint# 创建蓝图对象
api = Blueprint("api_1_0", __name__)

创建完蓝图后需要在ihome下的init.py中注册

def create_app(config_name):app = Flask(__name__)config_class = config_map.get(config_name)app.config.from_object(config_class)# 使用app初始化dbdb.init_app(app)...# 注册蓝图from ihome import api_1_0app.register_blueprint(api_1_0.api, url_prefix="/api/v1.0")return app

编写启动文件manage.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-from ihome import create_app, db
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand# 创建flask应用
app = create_app("develop")
manage = Manager(app)
Migrate(app, db)
manage.add_command("db", MigrateCommand)if __name__ == '__main__':manage.run()

在api_1_0目录下创建测试文件demo.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-# 导入蓝图对象
from . import api@api.route("/index")
def index():return "index page"

在api_1_0下的init.py文件中导入蓝图的视图demo

# 导入蓝图的视图
from . import demo

在终端进入到ihome-python04,即manage.py所在的目录,输入python manage.py runserver启动项目

在不报错的情况下,打开浏览器,地址栏输入127.0.0.1:5000/index

页面打印“index page”

如果报错了,可根据错误提示自行百度

配置日志信息

flask貌似没有提供日志的模块,不过 python 提供了,即 logging 模块

在工程根目录下(ihome-python04)创建logs目录,用来存放日志文件

在ihome下的init.py文件中配置日志模块

# 创建redis连接对象
redis_store = Noneimport logging
from logging.handlers import RotatingFileHandler# 设置日志的记录等级
logging.basicConfig(level=logging.DEBUG)  # 调试debug级
# 创建日志记录器,指明日志的保存路径,每个日志文件的最大大小,保存的日志文件个数上限
file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024*1024*100, backupCount=10)
# 创建日志记录的格式                等级      输入日志信息的文件名    行数       日志信息
formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
# 为刚创建的日志记录器设置日志记录格式
file_log_handler.setFormatter(formatter)
# 为全局的日志工具对象(current_app)添加日志记录器
logging.getLogger().addHandler(file_log_handler)

在api_1_0下的demo.py文件中写日志测试

# 导入蓝图对象
from . import api
from flask import current_app@api.route("/index")
def index():current_app.logger.error('dmngdcfnf')current_app.logger.warn('dmngdcfnf')current_app.logger.info('dmngdcfnf')current_app.logger.debug('dmngdcfnf')return "index page"

重新启动一下工程,刷新浏览器,看logs目录下应该会生成一个log文件,内容大致如下:

INFO _internal.py:122  * Restarting with stat
WARNING _internal.py:122  * Debugger is active!
INFO _internal.py:122  * Debugger PIN: 872-898-311
INFO _internal.py:122  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
ERROR demo.py:11 dmngdcfnf
WARNING demo.py:12 dmngdcfnf
INFO demo.py:13 dmngdcfnf
DEBUG demo.py:14 dmngdcfnf
INFO _internal.py:122 127.0.0.1 - - [09/Aug/2019 19:36:41] "GET /api/v1.0/index HTTP/1.1" 200 -

数据库设计与迁移

根据前端的需求,可先设计数据库的e-r(如下)图,然后根据e-r图编写models

在ihome目录下创建models.py

# -*- coding:utf-8 -*-from datetime import datetime
from . import dbclass 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))  # 用户头像路径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)  # 房屋编号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)  # 归属地的区域编号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="")  # 房屋主图片的路径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)house_id = db.Column(db.Integer, db.ForeignKey("ih_house_info.id"), nullable=False)  # 房屋编号url = db.Column(db.String(256), 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)  # 订单的评论信息或者拒单原因

在控制台先初始化models(自行创建数据库)

python manage.py db init

初始化后会在根目录下生成migrations目录

执行命令,提交这些文件

python manage.py db migrate -m 'db tables'

如果报如下错误

说明models没有被引用,可以在demo.py中引用一下

from ihome import models

再执行以下以上命令,会出现以下结果,表示执行完成

完成之后执行命令进行数据库的迁移

python manage.py db upgrade

可在数据库中查看,是否迁移成功

重新启动一下,浏览器刷新,可正常显示页面“index page”

接下来就开始项目的正式工作了,

首先让浏览器可以正常的访问页面,并通过静态文件的配置,让浏览时更加民主化。

静态文件的配置,使浏览器可以正常访问文件

首先在ihome目录下创建static静态目录,用来存放css、js、html以及images等静态资源。

为什么要配置静态文件?

如果不配置的话,浏览器访问页面时需要输入“127.0.0.1:5000/static/html/index.html”,这样有点太不友好了,我们需要的是输入“127.0.0.1:5000”或者“127.0.0.1:5000/index.html”,就可以访问主页面,因此,配置静态文件还是需要的。

我们可以自定义一个蓝图,用来提供静态文件的资源

首先在ihome目录下创建python包utils,用来存放自己编写的工具类。在utils目录下创建commoms.py文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-from werkzeug.routing import BaseConverter# 定义正则转换器
class ReConverter(BaseConverter):def __init__(self, url_map, regex):# 调用父类的初始化方法super(ReConverter, self).__init__(url_map)# 保存正则表达式self.regex = regex

为flask添加自定义的转换器,在ihome目录下的init.py文件中添加:

from ihome.utils.commons import ReConverter# 为flask添加自定义的转换器
app.url_map.converters['re'] = ReConverter

在ihome目录下创建一个web_html.py文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-from flask import Blueprint, current_app# 提供静态文件的蓝图
html = Blueprint("web_html", __name__)# 127.0.0.1:5000/()
# 127.0.0.1:5000/(index.html)
# 127.0.0.1:5000/(register.html)
# 127.0.0.1:5000/(favico.ico)@html.route("/<re(r'.*'):html_file_name>")
def get_html(html_file_name):"""提供html文件"""# 如果html_file_name为空,表示访问的路径为/ , 请求的是主页if not html_file_name:html_file_name = 'index.html'# 如果html_file_name不是favicon.icoif html_file_name != 'favicon.ico':html_file_name = 'html/' + html_file_name# flask 提供的返回静态文件的方法return current_app.send_static_file(html_file_name)

使用正则表达式来匹配 “127.0.0.1:5000/” 后边的参数

共分为三种,分别是:

  • 空---->主页
  • xxx.html
  • favicon.ico----->标识

返回时使用的是send_static_file,默认会去static目录下找,但是文件有可能在子目录html目录下,所以作出了以上两种判断。

编写了蓝图后需要注册

在ihome目录写的init.py中完成html蓝图的注册

from ihome import web_html
app.register_blueprint(web_html.html)

从新启动,浏览器清除一下缓存,并重新输入“127.0.0.1:5000”或者“127.0.0.1:5000/index.html”或者“127.0.0.1:5000/favicon.ico”等看是否可以正常访问,并可以正常跳转至指定的页面(页面中点击登陆,则跳转至登陆界面,点击注册,则跳转至注册界面)

csrf 防护机制

为静态路由添加csrf_token的cookie值

在web_html.py文件中添加或修改以下内容

from flask import Blueprint, current_app, make_response
from flask_wtf import csrfdef get_html(...):...# 创建一个csrf_token的值csrf_token = csrf.generate_csrf()# flask 提供的返回静态文件的方法resp = make_response(current_app.send_static_file(html_file_name))# 设置cookie值resp.set_cookie('csrf_token', csrf_token)return resp

重新启动程序,浏览器清除之前的cookie值,并刷新浏览器

本节完

flask爱家租房项目开发(一)相关推荐

  1. flask爱家租房项目开发(十三)

    本节文档下载地址:https://download.csdn.net/download/geek_xiong/11615541 目录 蚂蚁金服--支付宝的使用 订单支付 前后端代码编写 测试 蚂蚁金服 ...

  2. flask爱家租房项目开发(十二)

    下载地址:https://download.csdn.net/download/geek_xiong/11585216 预定房间功能 在房间详情页提供预定功能,点击进入预定页面,提交预定后页面跳转到我 ...

  3. flask爱家租房项目开发(十)

    本文代码文档下载地址:https://download.csdn.net/download/geek_xiong/11576968 目录 房屋管理 发布的房屋信息管理 后端代码编写 前端代码编写 我的 ...

  4. Flask爱家租房--订单支付(支付过程)

    文章目录 0.支付流程 1. 重点总结 2.后端代码 3.前端js 4.前端html 0.支付流程 1. 重点总结 1)用户进入"我的订单"页面,点击"去支付" ...

  5. Flask爱家租房--房屋管理(搜索房屋列表)

    文章目录 0.效果展示 1.后端接口 2.前端js 3.前端html 0.效果展示 1.后端接口 house.py部分接口: # GET /api/v1.0/houses?sd=2017-12-01& ...

  6. Flask爱家租房--房屋管理(获取房屋详情)

    文章目录 0.效果展示 1.思路总结 2.后端接口 3.前端js 4.前端html 0.效果展示 1.思路总结 1)房屋详情页面开始加载时,detail.js首先通过定义的函数(重点:document ...

  7. Flask爱家租房--订单(房东接单、拒单)

    文章目录 0.效果展示 1.效果展示 2.后端接口 3.前端js 4.前端html 0.效果展示 1.效果展示 1)当房东点击"客户订单",js向后端接口get_user_orde ...

  8. Flask爱家租房--房屋管理(获取主页幻灯片展示的房屋基本信息)

    文章目录 0.效果展示 1.重点总结 2.后端代码 3.前端js 4.前端html 0.效果展示 1.重点总结 1)当用户访问首页时,开始加载页面信息,此时index.js文件首先调用后端接口chec ...

  9. Flask爱家租房--房屋管理(获取房东发布的房源信息条目)

    文章目录 0.效果展示 1.重点总结 2.后端代码 3.前端html 4.前端js 0.效果展示 1.重点总结 1)用户点击"我的房源",页面开始加载,此时myhouse.js限定 ...

最新文章

  1. SAP MM 采购订单与相关合同的价格差异问题分析
  2. 微服务架构的基础框架选择:Spring Cloud还是Dubbo?
  3. Maven详解(五)------ 坐标的概念以及依赖管理
  4. java反射成员变量_java反射之成员变量的反射
  5. oracle线程阻塞_Oracle Service Bus –线程阻塞案例研究
  6. XPath CheatSheet
  7. Python中的依赖注入实现原理
  8. 使用jquery.form.js实现form表单无刷新提交简单示例
  9. apache配置Options详解
  10. 软中断上下文能够睡眠吗?
  11. 领域驱动设计系列关键概念
  12. otn与stn网络_otn与stn网络_光通信网络
  13. Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)
  14. 霏霏暮雨 eclipse+HBASE开发环境搭建(已实践
  15. php储存网页内容的简单示范
  16. 进制之间的相互转换(超详细)
  17. 实战分享:USB PCB布线经验教训!
  18. 埃隆麝香下一件大事是向宽带发射4万颗卫星
  19. 计算机键盘银音乐,从键盘到键盘 ——一名音乐生到计算机老师的华丽转型
  20. Springboot + WebSocket 实现在线聊天

热门文章

  1. 如何创建海外美区Apple ID,并使用支付宝购买Apple Store礼品卡,十分钟学会
  2. Ant入门教程(上)
  3. 基于Java技术的Web环境下分布式数据库互操作性的实现
  4. 按要求自动生成无向/有向图(基于C++实现)
  5. 论文降重的方法是什么?
  6. 最后的舞,请与我一起跳
  7. matlab制作数字华容道,从技术角度实现实现数字华容道
  8. 联想拯救者Y9000X 22款的啸叫问题和设置页面黄白切换问题
  9. 思科c系列服务器cimc密码,UCS C系列服务器故障排除提示.PDF
  10. 怎样快速将pdf转成excel