Flask纪要
flask学习过程
1框架基础
2redis高性能key-value数据库
3视图具有装饰器的路由函数
4模板html文件 面向对象操作数据库orm
5蓝图
6单元测试
7GitHub
8项目
学习的目的
1清晰的业务逻辑 2解决bug的能力-->先定位bug 3面向百度变成-->搜索问题的精准程度StackOverflow 4能够灵活应用知识点-->内置函数,列表推导式
web的本质world wide web 利用互联网进行数据交流
客户端 浏览器 ios Android发送请求(用户输入,a,img,Ajax,爬虫) 渲染页面
服务端 服务器脚本->WSGI->应用程序 接收请求 解析请求 路由分发 业务逻辑 返回响应
使用web框架 的目的 安全性 高并发 提高开发效率 稳定 拓展性强
框架--协助开发的功能代码-->按照规定的要求 在指定位置上写业务代码
flask 快速完成项目
djiango 商城项目完备 齐全
tornado 异步框架
flask的wsgi werkzeug-->路由正则 jinja2-->模板的渲染
虚拟环境 为了在同一台电脑上使每个项目都有属于自己的python环境 不然会造成环境覆盖
搭建虚拟环境
sudo pip install virtualenv
sudo pip install virtualenvwrapper
创建建python2版本虚拟环境
mkvirtualenv 环境名 在使用python 在左侧会显示虚拟环境的名字 deacative退出虚拟环境
rmvirtualenv 环境名 删除虚拟环境
创建python3版本虚拟环境
mkvirtualenv -p python3 环境名
进入已创建的虚拟环境 workon tab tab 选择 回车
source activate原生启动虚拟环境
pip install flask == 版本号 安装响应版本的flask
查看已安装的包 pip list
which python 查看python或虚拟环境的所在路径
from flask import Flask
static_path 访问静态文件的路径 已弃用
static_url_path 访问静态文件的路径 指定为none 系统默认为/static
templates_folder 模板文件的文件夹 默认是 templates
static_folder 静态文件的问价夹
host 万能端口=" 0.0.0.0" 只要是本台电脑上的网卡都可以访问改ip
flask程序
from flask import Flask # 遵循PEP8的编码格式 使用哪个模块就import指定名称
app = Flask(__name__#是当前模块的名字,指定模块的绝对路径
static_url_path="/static"# 静态文件的路径
static_folder = "static",#指定静态文件夹的名字
template_folder = "templates"#指定模板文件夹的名字)
#加载配置
#1从类对象中加载
class Config(object):
DEBUG = True--->类属性必须是大写内置函数规定的小写不满足条件
app.config.from_object(Config)
#2从配置文件中加载 config 类似于字典类型
在静态文件夹中创建一个配置文件 里面写上DEBUG = True
app.config.from_pyfile("配置文件的路径")
#3环境变量
新建环境变量 里面新建配置文件
app.config.from_envvar("环境变量的名字")
4app.debug = true
5app.config["DEBUG"] = True
获取配置
app.config.get("DEBUG")
路由的本质是 url绑定 @app.route()装饰器用于把一个函数绑定到一个url上
视图函数的返回的响应可以是包含html的简单字符串 也可以是复杂的表单
同一路由指向多个不同的函数,在匹配过程中,至上而下依次匹配下面的函数并不执行
# 视图函数和路由
@app.route("/",methods = ["POST","GET"]) # 路由
def index(): # 视图函数
return "hello python"
浏览器只能获取get请求方式 post需要使用postman插件
# 动态路由 (带参数的路由)
@app.route("/user1/<int:user_id>"])# int:转换器
#自定义转换器 匹配6位数字
1起转换器的名字regex
2定义一个类继承自父类
class RegexConverter(BaseConverter):
regex = r"[0-9]{6}"
3把名字作为键 类对象作为值添加到系统默认的转换器字典中
app.url_map.converters ["regex"]= RegexConverter
向上查找可以找到父类被调用的地方
request接收请求报文的数据,进行处理
request.data.decode() 接收到的数据是二进制 需要解码
request.form.get("键")-->获取值
request.args.get("键")--.获取值
pic_obj = request.files.get("文件名")-->pic_obj.save("新的名字")
def index(user_id):
字典数据名 = {}
# json_data= json.dumps(字典名)--->字典数据转换位json数据--不常用
# 字典数据 = json.load(json数据)-->json数据转换为字典数据--不常用
return jsonify(字典数据名)--->将字典数据转换为json数据内容格式也会改变 需要导入jsonify库--最常用
return redirect(url_for("函数名"))-->通过函数名找到对应函数return"的网址" 需要导入url_for模块
return user_id
return '状态码为 666', 666
if __name__ == '__main__':
app.run()
app.run(host="主机ip" port=端口 debug=True-->1重启修改后的代码2抛出异常的位置利于开发)
子类重写父类的init方法会实例化子类,我自己称之为实例类对象
获取类中的所有实例对象 使用dir()内置函数
状态保持 session(服务端) 与 cookie(客户端)
cookie 是由服务端给客户端的,存储在客户端(通常是加密的),存储cookie的key:value,是纯文本信息 不能存储敏感信息
不同域名的cookie不能共用
cookie同源策略 同域名,同路径,如天猫和淘宝cookie共享
浏览器保存的cookie最大只能由4kb 服务器保存session不限量
cookie
设置cookie response.set_cookie("name", "老王")
cookie 设置过期时间 在设置cookie时设置过期时间 set_cookie(max_age=秒数)
获取cookie request.cookie.get("cookie的名字")
删除cookie在退出时删除cookie delete.cookie("name")
session
session_id 服务器加密之后以cookie的方式发送给浏览器 ,浏览器无法解析,只有服务器能认识session_id
设置session session["name"] = "laowang"设置session需要加密 使用app.secret_key = "aaa"#session秘钥
获取session session.get("name",None)如果没有获取到就返回none
删除session session.pop("name",None) 删除name对应的键值对,没有name就返回None
请求钩子 对所有的视图函数进行管理
@app.before_first_request # 在第一次请求之前会执行 应用场景:链接数据库 因为只需要链接一次
def before_first_request():
@app.before_request # 在每一次请求之前都会执行 可以做权限验证工作
def before_request(): v'c'c'c'c'c'c'c'c'c'c'c'c'c'c'c'c'c'c
@app.after_request # 在每一次请求之后都会执行 可以做扫尾工作 设置响应报文的内容必须接收一个参数作为响应
def after_request(respose):
return response
@app.terar_down_request # 在每一次请求之后都会执行 会捕获到响应中的异常 可以做捕获异常的操作
def terar_down_request(e):
只要访问视图函数都需要走这几步骤 只有第一次链接会触发before_first_request()二次之后就不会
主动抛出异常 abort()
http异常的主动抛出 abort()方法
如果是非法id访问 可以抛出404 -->参数是符合http协议的状态码 404 500 302等
可以主动拦截非法ip
捕获异常
@app.errorhandler(符合http协议的状态码-也可以捕获异常类名)<--如果视图函数出现()里的异常就执行下面的代码
def exception_handle(e):全局捕获
return ""
上下文 在代码执行到某一时刻时,根据之前的代码所做的操作以及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情
请求上下文 request context -包含->request(封装了http请求的内容) 和 session(记录请求会话中的用户信息) 保存了c s交互的数据
应用上下文 application context -->current_app 和 g变量 flask程序运行过程中保存了一些配置信息
current_app -->获取模块名,获取debug的值 和app的功能是类似的
g变量 全局临时变量 g对象-->可以动态添加属性 把g放在请求钩子中所有视图函数都能使用
---!!只能设置在当前文件中
flask script -->sys.argv
app.run 不能通过命令行指定端口,主机ip 以及其它参数 通过flask-script就可以
使用步骤
1 pip install flask-script
2 from flask-script import Manager
3 manager = Manager(app)
4 manager.run()
5 在Edit中添加runserver 参数
模板----->templates
jinja2 是由python开发的一个模板引擎
把变量名给模板替换模板里的内容
创建一个文件夹templates
写一个视图函数进行渲染
指定templates文件夹为templates文件夹
配置模板语言为jinjia2
在视图函数中渲染到模板
return render_template("demo1.html",)多个变量之间使用,隔开
过滤器的本质就是一个函数 |
可以链式操作如 {{ my_str | reverse | lower}}
safe 让带标签的字符串按找格式被浏览器渲染出来
自定义过滤器
1.定义一个过滤器的名字
lireverse
2.定义一个过滤器函数
def do_lireverse(li):
temp = list(li)
retern list(reversed(temp))
3.将名字作为键,函数的引用作为值添加到系统默认的过滤器中
app.add_template_filter(do_lireverse:"lireverse")
f 函数的引用
控制代码块{% for my_dict in my_list%}
{% if loop.index == 1 %}
<li style="background-color: orange">{{ my_dict.value }}</li>
{%endfor%}
模板的继承
父类模板中需要挖坑{% block contentBlock%}{%endblock%} 用来放子类模板自己的内容
子类模板中
{%extens "父类模板名"%}
{% block contentBlock%}
{{super()继承父类他自己的内容}}
子类模板自己的内容
{%endblock%}
相同格式的页面抽取父类模板
1 将两个页面进行对比
2 去异存同 将不同之处删除 再删除的位置挖坑 {%block 名字Block%}{% endblock %}
3 起名字可利用标签名或者class的属性进行起名 以便于在继承时进行一一对应
4 抽取完成的页面就是父类模板
5 在子类页面中继承父类模板 {% extends "base_news.html" %}
6 取出父类模板中的坑在里面填上子类模板自己的内容
{% block scriptBlock %}<script type="text/javascript" src="../static/news/js/detail.js"></script>
{% endblock %} 相同的内容继承自父类模板
导入一个模块中的多个类 在被导的模块中使用__all__ = ["类名","类名"]指定要导入的类 使用import * 导入时就是列表中的中
也可以添加一个字典aa = {} 导入时导字典名
模板中特有的变量和函数
config 可以通过模板直接获取
request
session
url_for 通过函数的名字获取函数对应的url
CSRF 跨站请求伪造
访问a进行转账 a未退出cookie存在 去访问b b中访问a的转账(cookie存在) a无法判别访问自己的对象
防止csrf攻击
确定攻击实在哪个代码块产生
区分请求是到底是谁(在转账界面设置cookie)
在webA中的转账界面生成随机数存入cookie中
将随机的cookie传到界面的form表单的隐藏标签中
在转账界面对cookie和界面中的cookie进行比较 相等才能进行转账
由于webB无法获取到webA的隐藏标签,获取它的表单中的cookie值时显示为None 值不等 无法执行转账操作
实际开发中引入CSRFProected 即可
flask 数据库 ORM 将表关系对应到类中 sql语句对应到类的方法
Flask-SQLAlchemy
创建数据库 create database 数据库名(test) chartset utf8
pycharm 创建数据库
点击右侧database -->点击右侧.QL-->创建数据库 create database 数据库名 cahrtset utf8-->刷新-->在下面More中选择添加-->双击使用
链接数据库 数据库 用户名: 密码 地址 端口 数据库名
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@127.0.0.1:3306/test"
跟踪动态跟踪修改设置,未设置只会提示警告
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
查询时显示原生SQL语句
app.config['SQLALCHEMY_ECHO'] = True
实例化数据库sqlalchemy工具对象
db = SQLALchemy(app)
创建模型类
class BookInfo(db.Model): -->继承自实例对象的Model
__tablename__ = "book-info" # 如果不指明就是类名的小写
# 表结构
name = db.Column(db.String(64), unique=True, nullable=Flask)
pub_date = db.Column(db.String(128), nullable=True)
is_delete = db.Column(db.Boolean, default=False)
id = db.Column(db.Integer, primary_key=True)
# 返回对象的name属性 不写的话返回的是对象的地址引用
def __repr__(self):
return self.name
表操作
创建表
db.create_all()
删除表
db.drop_all()
新增一条数据
创建对象,设置属性
book1 = BookInfo()
book1.name = "西游记"
book1.pub_date = "2001-1-1"
添加到数据库中
db.session.add(book1)-----add_all()可以添加多个对象
真正提交数据
db.session.commit()
删除数据
user = PeopleInfo.query.first() -->查询出一个信息
db.session.delete(user)-->删除这条数据
db.session.commit()-->提交删除的操作到数据库
PeopleInfo.query.all()-->查询全部信息确认是否删除成功
更新数据
user = PeopleInfo.query.first() -->查询出一个信息
user.name = "新的值"-->将对象的属性设为新的值
db.session.commit()-->将更新的操作提交到数据库
PeopleInfo.query.first()-->再次查询这条数据确认修改成功
----------------------------------------------------->>>>>
查询 可以使用ipython3进行查询,需要导入
from 模块名 import *
类名.query.filter().all()
filter()返回的是一个查询集
all()以列表的方式返回查询的所有结果
类名.query.filter(条件).all()-->模糊查询
类名.query.filter_by(条件).first()-->精确查询
多表联合查询
查询出书下面的所有人物
方式-
book = BookInfo.query.filter(BookInfo.name =="三国演义").first()-->查询出book对象
PeopleInfo.query.filter(PeopleInfo.book_id == book.id).all()-->以列表显示的结果
方式二
book = BookInfo.query.filter(BookInfo.name =="三国演义").first()-->查询出book对象
people = db.relationship("PeopleInfo")-->需要在BookInfo表中添加和PeopleInfo的relationshhip
book.people
backref="book"动态的给PeopleInfo添加了一个book属性-->反向引用
等同于book = db.relationship("BookInfo")-->需要在PeopleInfo表中添加和BookInfo的relationshhip
lazy ="dynamic"--->book.people是一个查询集占用小内存使用,可以近一步操作
------------------------------------------------------>>>>>>>>>
使用闪现flash()需要设置密钥 它依赖与session
状态保持
请求钩子
csrf
图书管理案例
数据库迁移 -->可以记录版本信息 可以反悔操作 必须先备份数据 不删除表就可以修改表结构防止数据丢失
跟踪设置数据结构 原始数据可以恢复 监听对数据库的操作 必须先备份数据! ! ! ! !
from flask_migrate import Migrate,MigrateCommand
from flask_migrate import Manager,Shell
在flask 中对数据库进行迁移配置
manager = Manager(app)
migrate= Manager(app,db)-->关联
manager.add_command("db", MigrateCommand)
迁移的命令
python xx.py db init 创建一个迁移文件夹(迁移文件的仓库)
python xx.py db migrate -m "注明(修改的内容)"-->生成一个版本文件 将模型添加到迁移文件中 迁移脚本
python xx.py db upgrade 更新数据库中的表 执行迁移 观察表结构
返回旧版本
python xx.py db history 查看历史版本(迁移记录)
python xx.py db downgrade 版本号 -->返回指定旧版本
多对多案例分析 如:学生 学科 第三表
1 创建数据库
2 数据模型 继承(db.Model)
表名
字段= 约束
关系
建立连接
数据模型 继承(db.Model)
表名
字段= 约束
关系
建立连接
3 第三表建立关系 直接创建一张表不需要使用模型类
tb_student_course = db.Table(
"表名",
db.Colum("字段名",约束))
4 添加数据
蓝图
为什么使用蓝图--->对程序进行模块化管理--进行协同开发--可以解决循环导入问题--降低耦合度
模块化管理-->根据一定的条件对函数进行分类(按照功能,按照开发人员等)
步骤
1.在蓝图对象模块中导入Blueprint
2.实例化蓝图对象 = Blueprint("名字",__name__,url_prefix = "/路由的开头 区分模块之间的路由,防止冲突")
3.定以路由
4.导入蓝图对象
5.将蓝图注册到app中(蓝图实例对象)
一个蓝图模块可以注册多次
单元测试--->严谨性特别高的程序使用单元测试
向功能单一的模块进行测试
断言assert 判断一个函数或方法的一个功能是否符合预期结果
在单元测试中使用
在自己写的工具类供别人使用使用需要断言
例如:
def func(a,b):
assert isinstance(a,int),"参数为int类型"
return a/b
func(参数,参数)
单元测试测试接口------------------------------------数据库测试-------晚间实现
1使用代码模拟浏览器发送一个post请求
2判断errorcode是否存在字典中
3判断errorcode是否为-1
测试代码的步骤
import unittest
import app
import json
class LoginTest(unittest.TestCase):
def setUp(self): # 相当于__init__ 做初始化工作
app.testing = True--->被测试代码有异常会直接抛出
定义模拟客户端=app.test_clicent()
def test_empty_username_password(self):
app.test_clicent().post("url",data={}) #模拟浏览器发送一个post请求
json_data = responde.data
dict_data = josn_data.loads()
print(dict_data)
self.assertIn("键",容器,"返回的消息")
self.assertEqual(数据的[键],状态码,"返回的消息")
def tearDown(): # 类似与__del__()-->析构方法
数据库的断开操作
if __name__ == '__main__':
unittest.run()
nosql--->以键值对存储数据
sql------>适用于关系复杂的数据查询场景
redis-->数据存贮在内存中 速度极快 也支持磁盘存储 重启再次加载使用
支持 list set zset hash 数据据结构存储 支持主从配置 master--slave
应用场景
缓存
社交类应用
session共享 购物车
安装redis
wget url 下载
解压
移动到指定目录
今日redis目录
sudo make 进行编译
sudo make test 测试
sudo make install 安装命令
将配置文件.conf加载到etc目录下
客户端启动 redis-cli
select 0-15 选择使用的数据库
服务端启动 redis-serve
redis 端口 6379
设置守护进程 demaonize yes
默认16个数据库 0-15
redis 哈希 基本的数据类型
哈希槽 利用哈希算法计算出来的存储数据的空间
主从 读写分离 数据备份
Flask纪要的更多相关文章
- JavaScript 字符串实用常操纪要
JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...
- 微信小程序首次官方分享的纪要
先交代备注: 这次有关小程序的分享只有技术的 QA环节,其他如产品.入口.流量.与公众号的整合等等,回答都是暂时无法给出答案或不确定: 小程序最终发布时间官方也还未确定,不过说应该就是近期: 小程序的 ...
- 新编码神器Atom使用纪要
Atom是 Github 专门为程序员推出的一个跨平台文本编辑器.她很大程度上继承了SublimeText的美,而又不仅如此.有费了蛮大力气总结了一篇关于SublimeText文章: 如何优雅地使用S ...
- flask+sqlite3+echarts2+ajax数据可视化
前提: 准备Python + Flask+Sqlite3的平台环境(windows系统) 前面一节介绍flask怎么安装了,剩下sqlite3下载后解压,然后环境变量添加解压路径就行了 附加下载地址: ...
- flask+sqlite3+echarts2+ajax数据可视化报错:UnicodeDecodeError: 'utf8' codec can't decode byte解决方法
flask+sqlite3+echarts2+ajax数据可视化报错: UnicodeDecodeError: 'utf8' codec can't decode byte 解决方法: 将 py文件和 ...
- Windows下快速安装Flask的一次经历
前提: 1.已安装python版本(一般都是2.X) 2.已安装easy_install python安装,记得配置Python的环境变量,例如:我的直接在Path上加 G:\Python 验证安装P ...
- 使用Flask设计带认证token的RESTful API接口[翻译]
上一篇文章, 使用python的Flask实现一个RESTful API服务器端 简单地演示了Flask实的现的api服务器,里面提到了因为无状态的原则,没有session cookies,如果访问 ...
- 使用python的Flask实现一个RESTful API服务器端[翻译]
最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文将会使用python的Flask框架轻松实现一个RESTful的服务 ...
- python flask (一)
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World ...
随机推荐
- markdown 格式测试
Q1: before 与 afer 的而区别在哪? Q2: 如何预防"爆仓"? Q3: 在购买量 much > 库存量 num时, 把much自动改为num? -- 在t2的 ...
- sed - 文本三剑客之编辑功能
sed - stream editor for filtering and transforming text Sed是一个流编辑器.流编辑器用于对输入流(文件或管道输入)执行基本的文本转换.虽然在某 ...
- (四)Kubernetes 资源清单定义
Kubernetes常用资源对象 依据资源的主要功能作为分类标准,Kubernetes的API对象大体可分为五个类别,如下: 类型 名称 工作负载(Workload) Pod.ReplicaSet.D ...
- Codeforces B. Bad Luck Island(概率dp)
题目描述: Bad Luck Island time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- httprunner学习4-variables变量声明与引用
前言 在 HttpRunner 中,支持变量声明(variables)和引用($var)的机制.在 config 和 test 中均可以通过 variables 关键字定义变量,然后在测试步骤中可以通 ...
- DateFormat与SimpleDateFormat区别和使用详解
DateFormat类 此类是一个日期的格式化类,用来格式化日期.具体日期可以通过java.util.Date类来获取. DateFormat类的定义:此类是定义在java.test包中的. publ ...
- 团队项目评审&课程学习总结
一:实验名称:团队项目评审&课程学习总结 二:实验目的与要求 (1)掌握软件项目评审会流程: (2)反思总结课程学习内容. 三:实验步骤 任务一:按照团队项目结对评审名单,由项目组扮演乙方,结 ...
- egg 连接 mysql 的 docker 容器,报错:Client does not support authentication protocol requested by server; consider upgrading MySQL client
egg 连接 mysql 的 docker 容器,报错:Client does not support authentication protocol requested by server; con ...
- HDU6625: three arrays (字典树处理xor)
题意:给出A数组,B数组,你可以对A和B分别进行重排列,使得C[i]=A[i]^B[i]的字典序最小. 思路:对于这类题,显然需要建立字典树,然后某种形式取分治,或者贪心. 假设现在有了两颗字典树A ...
- 不重装nginx实现动态添加模块
如果项目在提供服务的过程中,因为需求使然,需要对nginx进行模块的动态添加,可以按照如下流程进行操作 一.查看nginx当前已经安装了那些模块 1) 进入nginx执行文件目录 cd /usr/ ...