flask爱家租房项目
前后端不分离:前端展示的效果由后端控制,后端返回一个渲染好数据的模板页面
前后端分离:前端展示效果由前端自己控制,后端只返回json
数据,可以提高后端接口的复用,网站和app可以公用一个后端;是趋势;
前后端分离缺点:
不利于SEO
,搜索引擎(爬虫)在访问页面的时候,页面当中没有数据(需要js请求),造成无法收录;哪个页面需要爬虫爬取,可以单独把那个页面写成前后端不分离
Flask扩展列表
pip install Flask==1.1.2
pip install Flask-Script==2.0.6
pip install Flask-session==0.3.2
flask中默认把session
放到浏览器中,这样会有安全问题,所以手动指定放到redis
中,借助Flask-Session
扩展
当需要向后台提交数据post
时,就要加上csrf
防护机制,flask
本身没有该验证,需要借助wtf
扩展实现
所有flask扩展都有两种创建方式
1、直接创建
db = SQLAlchemy(app)
2、先创建对象,再使用app初始化
db = SQLAlchemy()
db.init_app(app)
蓝图
Flask
使用蓝图可以实现模块化,把蓝图注册到app
中才会生效
循环导包问题
A导入B,B导入A,导致程序卡住,不能向下执行
解决办法:延迟导入,在需要使用时再进行导入操作。
ImportError: cannot import name 'db'
从执行文件一步步分析得出,两个文件之间存在循环导包
问题,解决办法,推迟其中一个的导入,用到的时候再导入包
项目目录
flask_ihome
|- ihome #蓝图
|- __init__.py #app属性配置
|- models.py #数据库字段
|- api_1_0 #蓝图视图类
|- libs #引用完整的第三方库
|- static #静态文件
|- utils #自己写的第三方库
|- logs #日志
|- migrations #初始化数据库
|- config.py #配置文件
|- manage.py #启动文件
项目启动流程
启动文件--》项目的init文件,配置app--》注册蓝图的init文件--》视图函数
配置文件里的配置选项:db、redis session csrf
数据库设计
不要以用户信息手机号等
作为主键,因为一旦用户修改,与其相关的所有数据都需要修改;以自己给的值作为主键和对其关联;
临时存储的数据放到redis
中
查询语句distinct
去重,当数据量大的时候会成为瓶颈,解决办法是单独设置一个表,设置成外键;
当数据库中某个字段有大量数据是空的,那就会产生冗余字段;可以新建一个表解决
多对多关系表,需要一个中间表关联;
评论信息
和订单
是一对一关系
index_image_url
、order_count
以空间换时间,存储一个默认字段,减少一次关联查询
设计model类,之后执初始化
、迁移
命令
python manage.py db init # 初始化
python manage.py db migrate -m "init table"
python manage.py db upgrade
配置静态资源访问蓝图
1、在utils
中自定义正则过滤类ReConvert
2、自定义访问静态资源的视图函数,再初始化文件中将自定义的过滤器注册到app
中
app.url_map.converters["re"] = commons.ReConvert
3、添加蓝图路由,最后统一到app
路由中
# flask返回静态文件的方法
current_app.send_static_file(file_name)
# 添加静态文件蓝图
from . import web_html
app.register_blueprint(web_html.html)
csrf
防护机制
1、服务器在cookie
和请求体(body)中设置csrf_token
值,处理请求时比对值是否相同,如果不同返回400错误;
2、浏览器的同源策略
,限制不同网站间不能相同操作cookie
等资源;cookie
有域
的限制
3、用到防护的常用请求方式post
、put
、delete
4、前后端不分离时,在模板文件中设置csrf_token
的值
5、前后端分离时,在用户访问时,默认给一个csrf_token
值
csrf
伪造请求:黑客伪造一个类似的网站,骗用户输入用户名,密码;再提交表单中加入自己想要的数据,用户正常看不到;如果网站在前台加一个csrf_token
的值,并在后台验证是否正确,就可以防止该攻击;黑客拿不到这个值。
接口文档格式
图片验证码验证机制
创建图片验证码编号时,使用UUID
UUID 是指Universally Unique Identifier,翻译为中文是通用唯一识别码,UUID 的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其它人冲突的 UUID,就不需考虑数据库创建时的名称重复问题。
python模块
import uuid
uid = str(uuid.uuid4())
suid = ''.join(uid.split('-'))
短信验证--容联云通讯
https://doc.yuntongxun.com/space/5a5098313b8496dd00dcdd7f
调用SDK,默认是python2.7
的版本,需要修改成python3
调用时修改模板为单例模式
,减少与云通讯服务的交互次数;
对以下三个参数配置
flask后端接收参数
GET请求:request.args.get("image_code")
POST请求:request.get_json()
添加密码时使用setter
装饰器
# 使用setter对password属性进行设置操作,不需要有返回值,设置属性时被调用
@password.setter
def password(self, value):
self.password_hash = generate_password_hash(value)
后端密码加密,一般用
salt + sha1
sha1(salt$password)
# 目前比较安全的加密算法sha256
一次请求中有多个函数之间传递参数,可以使用g
对象
文件存储
项目里文件直接保存在本地会有很多问题:
1、硬盘满了需要扩容
2、备份问题,防止文件丢失;
3、识别是否是一张图片的问题,用md5
、sha1
计算出hash值,如果值一样就是一个文件
文件存储解决方案:
1、自己搭建文件存储系统, FastDFS 适合电商,快速分布式文件存储系统,HDFS hdoop文件存储系统
2、第三方服务:七牛云存储;秒传功能,判断文件是否存在,直接返回给你
七牛云
https://portal.qiniu.com/create
创建存储空间
调用SDK
上传成功返回文件名,失败报异常
前端表单提交文件,用jquery.form.js
,可以自动处理表单类型,并且能自定义回调函数;
下载地址:
http://www.h-ui.net/lib/jQuery.form.js.shtml
缓存机制
接口访问的数据量不经常变动且访问次数多的时候,可以配置缓存,一般用内存型数据库redis
缓存数据的同步问题:
? 保证mysql
与redis
数据的一致相同
? 1、在操作mysql
的时候,删除缓存数据
? 2、给redis
缓存数据设置有效期,保证过了有效期,缓存数据会被删除
数据库字段设置成None
和空字符串
时看上去一样,但筛选时不一样
前端js模板 art-template
http://aui.github.io/art-template/
使用场景:如果一个页面需要填充的数据较多,用jqeury
一个一个填有点麻烦,可以使用该模板
单例模式
对于一个类而言,只有一个全局唯一的实例
@staticmethod
def instance(cls):
if not hasattr(cls, "_instance"):
cls._instance = cls()
return cls._instance
session
由于http是无状态的,所以要引入记录用户行为
用户数据放在浏览器(cookie)中是不安全的,所以前端存储的session_id,具体数据存储在后端的session中
https保证从前后传数据到后端,整个过程都是加密的,不需要单独对用户密码等信息加密
装饰器返回的结果是inner定义的函数执行结果,
装饰器会修改原函数的__name__
属性,在inner函数上加@functools.wraps()
文件服务器存储
对每个文件生成hash值,再去比较,如果hash值相同,说明是同一个文件,不需要再重新上传,浪费空间
tornado中直接调用接口的方式一定会导致程序阻塞,所以要改写接口调用方式;
jquery.form插件
拿到的数据不是第一次全部加载完,而是向下滚动时再加载,前端根据屏幕高度判断,发送接口请求即可
微信公众号开发流程
tornado接口编写
微信采用xml传输数据,python使用xmltodict
模块,常用方法parse
和unparse