目录
一、使用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 logginglogger = 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.pyINSTALLED_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 Celeryos.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_asyncclass 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 settingsdef 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 logginglogger = 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过来的