之前使用django 4配合celery 5.26的时候还好好的,今天新增了一个任务就突然不行了,一直报AttributeError,调了差不多24小时终于发现问题了。
对比任务端和worker端的代码可以发现,如果想要worker端的celery正常运行,就必须要把导入类的语句放到配置好环境变量之后,不然worker端的celery会找不到别的包,导致AttributeError。我由于在新增的任务中使用了工程中其他的类,又把导入类的语句放错了位置,所以导致了这个问题,如果你出现类似的问题,你也可以参考我的修改过程,少走弯路。一些编辑器的自动格式化会自动把导入语句放最前面,最好在关闭之后用记事本打开看看语句的顺序有没有错,不然会在保存的一瞬间自动格式化了。
worker端正确代码如下,仅供参考:
# __init__.py
# celery worker端初始化代码,可以不放tasks.py里面,这里也可以读取
import os
import django
# worker端的环境变量配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'daily_fresh.settings')
django.setup()
# worker端启动代码(先切换目录)
# celery --app=celery_tasks.tasks worker -l INFO
# tasks.py
import os
from celery import Celery # 使用celery
from daily_fresh import settings
from django.template import loader
from django.core.mail import send_mail
from goods.models import * # worker端这一句放在环境变量之后,不然celery会报错
# 创建一个Celery类的实例对象,链接redis,用1号数据库
app = Celery('celery_tasks.tasks', broker='redis://127.0.0.1:6379/1')
@app.task # 使用task修饰器创建被celery调用的任务
def send_register_avtive_email(to_email, username, token): # 定义任务函数
"""发送激活邮件"""
subject = "天天生鲜欢迎信息" # 邮件标题
message = '邮件正文' # 邮件正文(用了html-message就不会显示了)
html_message = '<h1>%s,欢迎您成为天天生鲜注册会员</h1>'\
'请点击下面链接激活您的账户,半小时内有效:<br>' \
'<a href="http://127.0.0.1:8000/user/active/%s">'\
'http://127.0.0.1:8000/user/active/%s<a/>' \
% (username, token, token)
sender = settings.EMAIL_FROM # 发件人
receiver = [to_email] # 收件人
send_mail(subject, message, sender, receiver,
html_message=html_message)
@app.task
def generate_static_index_html():
"""产生首页静态页面"""
# 查询商品的种类信息
types = GoodsType.objects.all()
# 获取首页轮播的商品的信息
index_banner = IndexGoodsBanner.objects.all().order_by('index')
# 获取首页促销的活动信息
promotion_banner = IndexPromotionBanner.objects.all().order_by('index')
# 获取首页分类商品信息展示
for type in types:
# 查询首页显示的type类型的文字商品信息
title_banner = IndexTypeGoodsBanner.objects.filter(
type=type, display_type=0).order_by('index')
# 查询首页显示的图片商品信息
image_banner = IndexTypeGoodsBanner.objects.filter(
type=type, display_type=1).order_by('index')
# 动态给type对象添加两个属性保存数据
type.title_banner = title_banner
type.image_banner = image_banner
# 组织模板上下文
context = {
'types': types,
'index_banner': index_banner,
'promotion_banner': promotion_banner,
}
# 加载模板文件,返回模板对象
temp = loader.get_template('static_index.html')
# 渲染模板
static_index_html = temp.render(context)
# 生成首页对应静态文件
save_path = os.path.join(settings.BASE_DIR, 'static/index.html')
with open(save_path, 'w') as f:
f.write(static_index_html)