日志封装

后台日志封装

项目肯定要记录日志
    日志都可以打印到控制台
    日志可以写到日志文件中
    日志存到某个库中
    所有项目日志统一管理   sentry:django写的服务,收集日志的,可以展示  开源


在项目中不要出现print了,以后都用日志
logger.info(),以后项目上线,只需要调整日志级别,低级别的日志就不打印了,于是日志输出不用删掉

操作步骤:django中集成日志步骤,django使用的就说python内置的日志模块
    第一步:在配置文件中加入 日志配置 ---大字典      
        详情见项目配置文件
    第二步:在utils新建common_logger.py,得到日志对象
       import logging
       logger = logging.getLogger('django')
     第三步:在任意想用日志的地方,导入使用即可
from django.http import JsonResponse
from utils.common_logger import logger

def test_logger(request):
    logger.info('info级别的日志')
    logger.error('error级别的日志')
    return JsonResponse({'name':'lqz'})


# 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            # 实际开发建议使用WARNING
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            # 实际开发建议使用ERROR
            'level': 'WARNING',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),
            # 日志文件的最大值,这里我们设置300M
            'maxBytes': 300 * 1024 * 1024,
            # 日志文件的数量,设置最大日志数量为10
            'backupCount': 10,
            # 日志格式:详细格式
            'formatter': 'verbose',
            # 文件内容编码
            'encoding': 'utf-8'
        },
    },
    # 日志对象
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'propagate': True,  # 是否让日志信息继续冒泡给其他的日志处理系统
        },
    }
}

前后端分离的rbac项目演示

后台:

https://gitee.com/liuqingzheng/rbac_manager
前端:

https://gitee.com/liuqingzheng/vue_admin

全局异常处理

前端 要接收的格式 要统一,无论后端是否出错

三大认证,视图类的方法中只要出了异常,就会执行一个函数,但是这个函数只能处理drf的异常---》我们需要自己写个函数,既能处理drf异常,又能处理django异常,这样统一返回格式,前端看到格式都统一了

使用步骤
   第一步:在utils中新建 common_exceptions.py
   第二步:写个函数 
切到项目目录下先安装drf
pip install djangorestframework

         看项目代码
   第三步:配置配置文件,以后只要出了异常,都会走咱们的函数
    REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'utils.common_exceptions.exception_handler',
        }
    第四步:勇敢大胆写代码,即便报错,程序不会崩,并且会记录日志,并且处理成统一格式


from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from utils.common_logger import logger


# 只要走到这个函数中,一定是出异常了 要记录日志
def exception_handler(exc, context):
    # 1.记录日志,哪个ip地址,用户id是多少,访问哪个路径,执行哪个视图函数,出了什么错
    request = context.get('request')
    view = context.get('view')
    ip = request.META.get('REMOTE_ADDR')

    user_id = request.user.pk

    path = request.get_full_path()
    # logger.error('用户【%s】,ip地址为【%s】,访问地址为【%s】,执行的视图函数为【%s】,出错是【%s】'%(user_id,ip,path,str(view),str(exc)))
    response = drf_exception_handler(exc, context)
    if response:
        # drf 的异常已经处理了 ---》直接取detail 会又小问题 遇到再解决
        logger.warning('drf出了异常,异常是:%s' % str(exc))
        res = Response({'code': 999, 'msg': response.data.get('detail', '服务器异常,请联系系统管理员')})
    else:
        # django的异常,咱们要处理
        logger.error('用户【%s】,ip地址为【%s】,访问地址为【%s】,执行的视图函数为【%s】,出错是【%s】' % (user_id, ip, path, str(view), str(exc)))

        res = Response({'code': 888, 'msg': '服务器异常,请联系系统管理员'})

    return res

封装Response

本身drf有Response,但是公司规定,前端收到的格式是固定的
    {code:100,msg:提示,data:{}/[]}
    {code:100,msg:提示,token:asdfasd,user:lqz}

对Response进行封装,封装后,code,msg可以不传,不传就用默认的

使用步骤
    第一步:在utils下新建common_response.py
    第二步:封装APIResponse
    第三步:导入使用,视图函数的方法,返回时,都使用咱们自己写的格式
from rest_framework.response import Response


class APIResponse(Response):
    def __init__(self, code=100, msg='成功', status=None, headers=None, **kwargs):
        data = {'code': code, 'msg': msg}
        if kwargs:  # 有值 说明传了 ,除了code msg status,headers 以外的 咱们都要返回给前端
            data.update(kwargs)
        # Response(data=data,status=status,headers=headers)
        super().__init__(data=data, status=status, headers=headers)


        # 不要return 可以这样  self.data = data  self.status=status


视图代码
from utils.common_response import APIResponse


class TestAPIResponse(APIView):
    def get(self, request):
        # return APIResponse(token='dsds', username='lqz')  # {code:ok,msg:成功}
        # return APIResponse(code=101,msg='错误')  # {code:ok,msg:成功}
        return APIResponse(data=[{'name':'西游记','price':'66'},{'name':'西游记','price':'66'}])  # {code:ok,msg:成功}

路由代码
path('test_response/', views.TestAPIResponse.as_view()),

luffy数据库创建

创建用户创建库

创建luffy数据库
之前项目操作数据库,都是使用root用户,root用户权限太高了,在公司里,一般不会给你root用户权限

如果开发人员是root权限 数据安全性就很差

开发人员,专门创建一个用户,用户只对当前项目的库有操作权限

创建一个luffy库,创建luffy用户,luffy用户只最luffy有操作权限

面试题:utf8  utf8mb4 有什么区别

创建luffy数据库
"""
1.管理员连接数据库
>:mysql -uroot -p密码

2.创建数据库
create database luffy default charset=utf8;

3.查看用户
select user,host,password,from mysql.user;
只要root用户,要创建luffy用户
# 5.7往后的版本
select user,host authentication_string from mysql.user;
"""

创建路飞用户,授予luffy库所有权限

"""
设置权限账号密码
授权账号命令:grant权限(create,update) on 库.表 to '账号'@'host' identified by '密码'

1.配置任意ip 都可以连入数据库的账号
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';

2.由于数据库版本的问题,可能本地还连接不上,就给本地用单独配置
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';

3.刷新一下权限
flush privileges;

只能操作luffy数据库的账号
账号:luffy
密码:Luffy123?
"""

使用项目连接库

项目操作mysql 需要安装模块
   pymysql
   mysqlDB
   mysqlclient