本文主要是介绍关于日志流量监控预警小小项目 | 对数据库的管理工具:migrate,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
manage.py的具体内容:
#命令行管理flask
#flask_script flask的命令行管理工具
#安装 pip install flask_script
# 首先,创建一个Python模板运行命令脚本,可起名为manager.py;
# 在该文件中,必须有一个Manager实例,Manager类追踪所有在命令行中调用的命令和处理过程的调用运行情况;
# Manager只有一个参数——Flask实例,也可以是一个函数或其他的返回Flask实例;
# 调用manager.run()启动Manager实例接收命令行中的命令;
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from model import db
from app import create_app
app = create_app()
manager = Manager(app)
#创建db管理工具
migrate = Migrate()#实例化一个migrate对象
migrate.init_app(app,db)#把db和app都和migrate绑定在一起
#添加迁移命令到manager中(manage是命令行管理工具)
#(db是只是一个名字,可以不叫db)
#(然后只要有这行命令 python manage.py --help就会出现新的属性db
#(表示把MigrateCommand命令添加到db命令子集下面去)
#于是我们就可以通过python manage.py db 来管理运行manager命令了
manager.add_command('db', MigrateCommand)
if __name__ == "__main__":
manager.run()
#初始化migration仓库(第一次创建migrations目录的时候使用)
# python manage.py db init
#提交版本变更
#python manage.py db migrate
#生效数据库
#python manage.py db upgrade
#python manage.py
对数据库的操作:
对数据库的管理工具:migrate
我们这个项目内容简单 但是所用的库很多 面试的时候可以提及
内容单一的原因:还在完善 使用过什么功能 做过什么
from datetime import datetime
from sqlalchemy import Column,Integer,String,DateTime
add_time=db.Column(db.DateTime,default=datetime.now)
在数据库里面添加一列时间,给的类型是类型,里面默认值是当前时间
python manage.py runserver :
-d:开启debug模式
-D:关闭debug模式
在代码里面临时新增一列属性,数据库不会自动新增
线上环境顶多对于数据库就查询和插入,而不是所有人都可以拥有所有权限(db.create_all只适用于测试环境,只能在没有这张表,创建的时候才生效,而创建好了之后再修改orm映射关系里的任何东西并不会变化)所以新添加字段就在创建新表的时候才添加
高级dba有时候比开发工资都高
对数据库敬畏
数据量比较大 我们一般是备份 而不是回收站(回收站没啥必要)
而我们会借助一个新的工具migrate:只要表的结构任意一个地方改了 就会同步生效到数据库里面去
这是在命令行管理工具里面做的 所以我们要写道manage里面去
首先在命令行先安装flask-migrate(要下载2.5.3版本)
在manage.py里面添加:from flask_migrate import Migrate, MigrateCommand
我们现在创建的模型都是基于db的
怎么生效数据库修改呢?
先初始化migration仓库(只要做一次就好 第一次创建migrations目录的时候使用)
python manager.py db init
然后我们的目录里面会自动创建新出现一个文件夹migrations作为仓库
然后提交版本变更(生效版本号)python manage.py db migrate(实质就是判定它需要生效哪些东西)
生成版本号在仓库目录里面就会有一个versions 里面存放着每次提交要做的语句 提交一次就会有一个版本号
然后生效数据库
python manage.py db upgrade就是把这个刷新到数据库里面 就可以看到修改生效(其实就是执行新的版本脚本)
而生效到数据库后 数据库里也自动生成了一张表(alembic_version)这张表里面记录的也就是版本号(这里的版本号和你目录里面的是一致的才能提交成功 否则会提交失败)
所以如果版本不一致了 就把目录和表都删掉 重新init
设计数据模型(数据库):
也就是orm层的关系映射
我们现在再创建一个班级表与学生表关联:
创建表的时候如果不指定tablename就会自动把你的类名小写
需要在学生那边添加班级id字段 于是我们要添加外键约束(我们添加的外键在那个表里面得是主键) 不能随意添加了
在sutdent里添加:(这个对象属性里面多了一个stuclass属性)
class_id=db.Column(db.ForeignKey('stuclass.class_id'))
(#外键约束 这个class_id只能写入stuclass.class_id里有的元素)
在stuclass里面添加:(属性多了stuinfo属性 这个属性里面就包含这这个班级里面有哪些学生对象 不需要sql联表查询了 )
stuinfo=db.relationship("Student",backref="stuclass")
(#关联两个数据模型 并且为student模型创建反向查询字段stuclass)
这一行是给stuclass创建与student的关系 然后给stuclass创建了一个stuinfo属性 里面包含着这个班级的学生对象 backref是设置反向查询字段 也就是在student那边创建了一个stuclass属性 里面包含着你所在的班级对象 这样两张表可以相互查找对象 访问对象的属性直接用点去访问就好了
db.Column是创建字段 生效到数据库
db.relationship是创建orm关系 创建关系其实也就是创建属性 只生效到orm
基于外键约束才能创建关系 会自动识别关联到外键 否则两张毫无关联的表不能做关联
认证:
常见的认证方式:基于http基本认证去做的
认证都放在libs里面的authorize 去做一个权限的管理
认证是基于http基本认证去做的
http协议支持两种认证方式:基本认证和摘要认证
没有绝对安全的认证
http基本认证:发起请求的时候 携带一个头部字段(里面包含用户名和密码)
在postman里面点击Authorization 选择basic auth(基本认证) 表示选择认证方式为基本认证 然后填写用户名密码 于是在headers里面就可以看到一个Athorization里面带有basic base34(username:password)这个格式不能变 其中选择基本认证的话 会是basic 然后base64是网页的编码方式 说明这是把用户名和密码经过base64加密之后放入athorzation的头部字段里面
在postman的右上角里面有个code按钮 按进去 这个code的意思就是实现这个请求用代码怎么实现 代码里面athorization所带的就是经过base64加密的用户名密码 这是客户端要做的事情
服务端就是拿到这个加密后的用户名密码 然后解密 然后响应
api授权认证:
只能拿到权限之后才能调用api
这是基于http基本认证去做的
在libs文件夹里面先加入一个文件 authorize.py
from flask_httpauth import HTTPBasicAuth
from flask import request
auth=HTTPBasicAuth()
#当执行auth.login_required时,会执行auth,verify_password对应的函数
#这个函数返回为真就表示认证成功,返回为假就表示认证失败
@auth.verify_password
def verify_password(token,password):#这两参数名字随便定 前面时用户名 后面是密码
#支持多种认证方式
if token and password:
#如果authorization头部字段里传了用户名和密码过来就认证成功
return True
elif token and token =="api":
#authorization:basic base64(api:)才进行api授权
return api_authorize()
def api_authorize():
params=request.args #获得url后面的参数
appid=request.get("appid")
passwd=request.get("passwd")
if appid=="root" and passwd=="123456":
return True
return False
所以只能在url?
然后在相应的api文件里面导入 from libs.authorize import auth
然后在需要认证的地方加一个装饰器@auth.login_required
这样加上装饰器之后是需要认证之后才能请求
192.168.0.105:8000/v1/monitor?appid=root&passwd=123456这样就能get到数据表里面的内容
浏览器有登录弹窗出来一般都是基本认证
401代表就是认证失败
要做api授权的表
##############
#API授权表的模型
#多对多的关系
app_permission = db.Table("app_permission",
db.Column("api_id",db.ForeignKey("api_token.id")),
db.Column("permission_id",db.ForeignKey("api_permission.id"))
)
# api_token表
#存放的是授权密钥,以及授权id
class ApiToken(db.Model):
__tablename__ = "api_token"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
appid = db.Column(db.String(128), nullable=False)
secretkey = db.Column(db.String(128), nullable=False)
#通过中间表去创建多对多的关系
manage = db.relationship("ApiPermission", secondary=app_permission, backref="token")
#存放的是授权的url
class ApiPermission(db.Model):
__tablename__ = "api_permission"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
url = db.Column(db.String(128), nullable=False)
method_type = db.Column(db.String(128), nullable=False)
#监控项数据模型
#id
#user_id
#prov
#isp
#bd
#实现restful api接口的增删改查
说明是把每个用户申请表的权限存入这张表 然后用户要携带这个表里面的信息去查询此表 如果表里能够查询到则代表有权限 没有查询到则代表没有权限
然后我们添加完这段代码把它生效到数据库里面 我们多了三张表
两个表是多对多的关系:
一个是员工表 而一个是业务表
一个人负责好几个业务 而一个业务好几个人负责
于是我们会创建一个中间表来维持多对多的关系 中间表的维持内容就是员工id以及业务id 然后会把每一条都计入中间表 如1-3,1-2,2-1,2-3等来表明多对多的关系 而中间表里面的员工id就外键到员工表里面 业务id就外键到业务表里面
Authorize.py里面的内容
#基于 http基本认证
#api授权认证
from flask_httpauth import HTTPBasicAuth
from flask import request
from model.student import ApiToken
from hashlib import md5
auth = HTTPBasicAuth()
#当执行auth.login_required时,会执行auth.verify_password对应的函数,
#这个函数返回为真就表示认证成功,返回为假就表示认证失败
@auth.verify_password
def verify_password(token, password):
#支持多种认证方式
if token and password:
#如果authorization头部字段里传了用户名和密码过来就认证成功
return True
elif token and token == "api":
#authorization: basic base64(api:)
return api_authorize()
#签名认证
#1、接口方提供出appid和secretkey
#2、调用方根据appid和secretkey,按照一定的算法生成sign
#3、接口方来验证签名
def api_authorize():
params = request.args
# 我们需要客户端传递过来的这三个参数来对你进行认证
appid = params.get("appid")
# 盐值就是为了防止你的密码被轻易推导出来 于是给它加一段随机的字符串 这样就不会被推导出来
salt = params.get("salt") #盐值
sign = params.get("sign") #签名
api_token = ApiToken.query.filter_by(appid = appid).first()
if not api_token:
return False
#验证有没有此url和方法的权限
# 这一步是判断你所携带的url和方法是否有权限
# api_token 刚刚得到的对象 request.path 这是request请求过来的url路径
# request.method.lower() request方法进行小写的转换
if not has_permission(api_token, request.path, request.method.lower()):
return False
#获取数据库里的密钥 密钥只有天知地知你知我知 第三方不知
secretkey = api_token.secretkey
#生成服务端的签名
#可以加上时间戳来防止签名被别人盗取,重复访问
user_sign = appid + salt + secretkey
m1 = md5() #所以这样在网络端传输的都是密文 不会泄漏密码
m1.update(user_sign.encode(encoding="utf-8"))
#判断客户端传递过来的签名和服务端生成签名是否一致
# 所以客户端和服务端的签名加密方式要是一模一样的才行
# 这就是前面认证
if sign != m1.hexdigest():
return False
else:
return True
#url验证
def has_permission(api_token, url, method):
#客户端请求的方法和url
mypermission = method+url
#获取此api_token对象的所有url权限
all_permission = [permission.method_type+permission.url
for permission in api_token.manage]
if mypermission in all_permission:
return True
else:
return False
签名认证的缺点:容易被人获取到 于是可以在签名里面添加一个时间戳(规定半个小时之后就不能获取数据了) 每一次请求的时候都会携带新的时间戳来请求
我们只要运行manage.py 或者server.py 其他都被导入运行
运行是按模块去运行的 只要导入 整个模块都会运行 (模块是最小运行单位)
这篇关于关于日志流量监控预警小小项目 | 对数据库的管理工具:migrate的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!