VIP 模块开发及日志处理
VIP、权限模块功能
- VIP 分类
- 非会员
- 一级会员
- 二级会员
- 三级会员
- 权限分类
- 超级喜欢
- 每日反悔 3 次
- 查看喜欢过我的人
- 权限分配
- 非会员: 无任何权限
- 一级会员: 超级喜欢
- 二级会员: 超级喜欢 + 反悔3次
- 三级会员: 超级喜欢 + 反悔3次 + 查看喜欢过我的人
开发难点
- User 与 VIP 的关系
- 一种 VIP 对应多个 User
- 一个 User 只会有一种 VIP
- 结论: 一对多关系
- VIP 与权限 的关系
- 一种 VIP 级别对应多种权限
- 一个权限会属于在多种级别的 VIP
- 结论: 多对多关系
- 如何针对每个接口进行相应的权限检查 ?
模型设计
-
VIP (会员)
Field Description name 会员名称 level 登记 price 价格 -
Permission (权限)
Field Description name 权限名称 description 权限说明
RBAC权限管理模型(需进行相关了解,工作中会用到)
相关文章
https://baike.baidu.com/item/RBAC/1328788
http://www.woshipm.com/pd/440765.html
https://www.sojson.com/blog/141.html
日志相关功能
- 开发统计函数,将每日登录数据统计到日志
- 登录时间
- 登录者的 uid
- 使用 Linux 命令统计出每天的 DAU (日活跃)
日志处理
-
日志的作用
- 记录程序运行状态
- 线上环境所有程序以 deamon 形式运行在后台, 无法使用 print 输出程序状态
- 线上程序无人值守全天候运行, 需要有一种能持续记录程序运行状态的机制, 以便遇到问题后分析处理
- 记录统计数据
- 开发时进行 Debug (调试)
- 记录程序运行状态
-
基本用法
import logging # 设置日志格式 fmt = '%(asctime)s %(levelname)7.7s %(funcName)s: %(message)s' formatter = logging.Formatter(fmt, datefmt="%Y-%m-%d %H:%M:%S") # 设置 handler handler = logging.handlers.TimedRotatingFileHandler('myapp.log', when='D', backupCount=30) handler.setFormatter(formatter) # 定义 logger 对象 logger = logging.getLogger("MyApp") logger.addHandler(handler) logger.setLevel(logging.INFO)
-
日志的等级
- DEBUG: 调试信息
- INFO: 普通信息
- WARNING: 警告
- ERROR: 错误
- FATAL: 致命错误
-
对应函数
logger.debug(msg)
logger.info(msg)
logger.warning(msg)
logger.error(msg)
logger.fatal(msg)
-
日志格式允许的字段
%(name)s
: Logger 的名字%(levelno)s
: 数字形式的日志级别%(levelname)s
: 文本形式的日志级别%(pathname)s
: 调用日志输出函数的模块的完整路径名, 可能没有%(filename)s
: 调用日志输出函数的模块的文件名%(module)s
: 调用日志输出函数的模块名%(funcName)s
: 调用日志输出函数的函数名%(lineno)d
: 调用日志输出函数的语句所在的代码行%(created)f
: 当前时间, 用 UNIX 标准的表示时间的浮点数表示%(relativeCreated)d
: 输出日志信息时的, 自 Logger 创建以来的毫秒数%(asctime)s
: 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896”。逗号后面的是毫秒%(thread)d
: 线程 ID。可能没有%(threadName)s
: 线程名。可能没有%(process)d
: 进程 ID。可能没有%(message)s
: 用户输出的消息
-
Django 中的日志配置
LOGGING = { 'version': 1, 'disable_existing_loggers': True, # 格式配置 'formatters': { 'simple': { 'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, 'verbose': { 'format': ('%(asctime)s %(levelname)s [%(process)d-%(threadName)s] ' '%(module)s.%(funcName)s line %(lineno)d: %(message)s'), 'datefmt': '%Y-%m-%d %H:%M:%S', } }, # Handler 配置 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'level': 'DEBUG' if DEBUG else 'WARNING' }, 'info': { 'class': 'logging.handlers.TimedRotatingFileHandler', 'filename': f'{BASE_DIR}/logs/info.log', # 日志保存路径 'when': 'D', # 每天切割日志 'backupCount': 30, # 日志保留 30 天 'formatter': 'simple', 'level': 'INFO', }, 'error': { 'class': 'logging.handlers.TimedRotatingFileHandler', 'filename': f'{BASE_DIR}/logs/error.log', # 日志保存路径 'when': 'W0', # 每周一切割日志 'backupCount': 4, # 日志保留 4 周 'formatter': 'verbose', 'level': 'WARNING', } }, # Logger 配置 'loggers': { 'django': { 'handlers': ['console'], }, 'inf': { 'handlers': ['info'], 'propagate': True, 'level': 'INFO', }, 'err': { 'handlers': ['error'], 'propagate': True, 'level': 'WARNING', } } }