目录
一、使用AdminEmailHandler实现发送日志通知邮件
1,配置日志项
2,配置邮件项
3,在视图里使用日志
二、继承AdminEmailHandler使用celery实现异步发送邮件
1,安装配置celery
2,继承AdminEmailHandler类,重写方法
3,编写异步任务
4,配置日志项
5,在视图里使用日志
6,启动celery并测试
在django的项目配置日志功能后,响应发送日志邮件到邮箱进行通知
一、使用AdminEmailHandler实现发送日志通知邮件
1,配置日志项
# settings.py
# 日志配置
LOGGING = {
"version": 1,
"formatters": {
"simple": {
"format": '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
},
"standard": {
"format": '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s'
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple"
},
"file": {
"class": "logging.FileHandler",
"formatter": "simple",
"filename": "monitoring.log", # 将日志信息写入本地文件中
"encoding": "utf-8"
},
'mail_admins': { # 新增mail_admins的handler,class为AdminEmailHandler
'level': 'INFO', # 发送邮件的级别,INFO及以上的级别会发送邮件
'class': 'django.utils.log.AdminEmailHandler', #
'formatter': "simple"
}
},
"loggers": {
"simple": {
"level": "DEBUG",
"handlers": ["file", "mail_admins"], # 添加mail_admins项
"propagate": True
},
"standard": {
"level": "ERROR",
"handlers": ["console", "file"],
"propagate": True
}
}
}
2,配置邮件项
# 邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com' # 如果是 163 改成 smtp.163.com
EMAIL_PORT = 587
EMAIL_HOST_USER = 'xxxx@qq.com' # 登录邮箱的账号
EMAIL_HOST_PASSWORD = 'yxamfessnijaie' # 授权码,各邮箱的设置中启用smtp服务时获取
SERVER_EMAIL = 'xxxx@qq.com' # 日志邮件的发送方
ADMINS = [('admin', 'xxxxx@qq.com')] # 日志邮件的接收方
3,在视图里使用日志
import logging
logger = logging.getLogger('simple') # 使用配置的simple项
logging.basicConfig(level=logging.INFO) # 配置级别
class MessageView(View):
def get(self, request):
# 查询的逻辑
logger.info("查询成功")
return JsonResponse({"status": 200})
为MessageView视图配置url后使用postman请求测试
可以看到视图请求成功返回了,邮件也收到了
但是存在一个问题:如此配置的发送日志邮件的功能是同步的,也就是说是阻塞的,需要邮件发送成功后视图才能返回结果,所以下面使用celery自定义一个异步的
二、继承AdminEmailHandler使用celery实现异步发送邮件
在项目根目录下创建celery_tasks文件夹,以下是目录结构:
1,安装配置celery
pip install celery django-redis
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'celery', # 添加celery
]
在celery_tasks目录 下创建celery.py文件,定入下面的内容:
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MediaManager.settings')
app = Celery('MediaManager') # 项目的名
app.config_from_object('celery_tasks.config', namespace='CELERY') # 配置文件
app.autodiscover_tasks() # 任务
在celery_tasks目录 下创建config.py文件,写入下面的内容:
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/4' # 存储celery任务队列的数据库
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/5' # 存储结果的数据库
CELERY_TASK_SERIALIZER = 'json'
# celery时区
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = False
在与settings.py同级的__init__.py文件里写入以下内容:
from celery_tasks.celery import app as celery_app
__all__ = ['celery_app']
2,继承AdminEmailHandler类,重写方法
在celery_tasks目录下创建handlers.py,写入下面的内容:
from django.utils.log import AdminEmailHandler
from celery_tasks.sms.tasks import send_email_async
class CeleryAdminEmailHandler(AdminEmailHandler):
def emit(self, record):
message = self.format(record) # 邮件正文内容
subject = super(CeleryAdminEmailHandler, self).format_subject(message) # 邮件标题
send_email_async.delay(subject, message)
重写AdminEmailHandler类里的emit方法
CeleryAdminEmailHandler的emit方法调用send_mail_async.delay()方法异步执行任务
3,编写异步任务
在在celery_tasks/sms目录下创建tasks.py,写入下面的内容:
from celery import shared_task
from django.core import mail
from django.core.mail import get_connection
from django.conf import settings
def connection():
return get_connection(backend=settings.EMAIL_BACKEND, fail_silently=True)
@shared_task
def send_email_async(subject, message, *args, **kwargs):
try:
mail.mail_admins(
subject, message, *args, connection=connection(), **kwargs
)
return "success"
except Exception as e:
print("发生错误:" + str(e))
return "fail"
4,配置日志项
将日志配置中的mail_admins的class项替换为handlers.py里写的CeleryAdminEmailHandler类
# settings.py
# 日志配置
LOGGING = {
"version": 1,
"formatters": {
"simple": {
"format": '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
},
"standard": {
"format": '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s'
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple"
},
"file": {
"class": "logging.FileHandler",
"formatter": "simple",
"filename": "monitoring.log", # 将日志信息写入本地文件中
"encoding": "utf-8"
},
'mail_admins': { # 新增mail_admins的handler,class为AdminEmailHandler
'level': 'INFO', # 发送邮件的级别,INFO及以上的级别会发送邮件
'class': 'celery_tasks.handlers.CeleryAdminEmailHandler', # 替换为自己写的类
'formatter': "simple"
}
},
"loggers": {
"simple": {
"level": "DEBUG",
"handlers": ["file", "mail_admins"], # 添加mail_admins项
"propagate": True
},
"standard": {
"level": "ERROR",
"handlers": ["console", "file"],
"propagate": True
}
}
}
5,在视图里使用日志
import logging
logger = logging.getLogger('simple') # 使用配置的simple项
logging.basicConfig(level=logging.INFO) # 配置级别
class MessageView(View):
def get(self, request):
# 查询的逻辑
logger.info("查询成功")
return JsonResponse({"status": 200})
6,启动celery并测试
先启动django项目,然后在项目根目录下启动celery
celery -A MediaManager worker -l INFO -P eventlet
为MessageView视图配置url后使用postman请求测试
可以发现postman返回的很快,因为这时发送邮件的耗时任务交由celery执行了,邮件也异步收到了
redis查看任务返回的结果,result参数为success也提示成功了,这个success是在tasks.py里return过来的