Celery是一个功能完备即插即用的任务队列。它使得我们不需要考虑复杂的问题,使用非常简单。celery看起来似乎很庞大,本章节我们先对其进行简单的了解,然后再去学习其他一些高级特性。 celery适用异步处理问题,当发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用户体验。 celery的特点是:
- 简单,易于使用和维护,有丰富的文档。
- 高效,单个celery进程每分钟可以处理数百万个任务。
- 灵活,celery中几乎每个部分都可以自定义扩展
任务队列是一种跨线程、跨机器工作的一种机制.
任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理.
celery通过消息进行通信,通常使用一个叫Broker(中间人)来协client(任务的发出者客户端)和worker(任务的处理者). clients发出消息到队列中,broker将队列中的信息派发给worker来处理。
一个celery系统可以包含很多的worker和broker,可增强横向扩展性和高可用性能。
Broker(中间人):RabbitMQ和Redis
models.py
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): '''用户模型类''' class Meta: db_table = 'fm_user' verbose_name = '用户' verbose_name_plural = verbose_name
setting.py
#认证模型类 AUTH_USER_MODEL = "app01.User" #发送邮件配置 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.qq.com' EMAIL_PORT = 25 #发送邮件的邮箱 EMAIL_HOST_USER = 'chvv1016@qq.com' #在邮箱中设置的客户端授权密码 EMAIL_HOST_PASSWORD = 'xxxxxxxxx' #收件人看到的发件人 EMAIL_FROM = '天猫商城<chvv1016@qq.com>'
创建一个celery_tasks的python包文件,然后创建一个tasks.py文件
from celery import Celery from django.conf import settings from django.core.mail import send_mail import time #django环境初始化 #下面四句加到任务处理者一段,即ubuntu里面的任务处理者,ubuntu作为处理者,要把全部代码复制过去 #ubuntu中启动命令 celery -A celery_tasks.tasks worker -l info import os import django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "celery_demo.settings") django.setup() # 创建一个celery的实例对象 app = Celery("celery_tasks.tasks",broker='redis://:chenchen@192.168.170.141:6379/8') #定义任务函数 @app.task def send_register_active_email(to_email,username,token): #发送激活邮件 subject = "天猫商城欢迎你" message = '' sender = settings.EMAIL_FROM receiver = [to_email] html_message = "<h1>%s欢迎成为会员</h1>请点击以下链接激活账户</br><a href='http://127.0.0.1:8000/active/%s'>http://127.0.0.1:8000/active/%s</a>" % ( username, token, token) send_mail(subject, message, sender, receiver, html_message=html_message) time.sleep(3)
views.py
from django.shortcuts import render,redirect,HttpResponse from django.core.urlresolvers import reverse from django.views.generic import View from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from itsdangerous import SignatureExpired from django.conf import settings from celery_tasks.tasks import send_register_active_email from app01.models import User from django.contrib.auth import authenticate,login,logout import re # Create your views here. ##########注册第一种FBV模式######### #注册和注册处理合一起 def register1(request): if request.method == "GET": return render(request,'register.html') else: username = request.POST.get("user_name") password = request.POST.get("pwd") re_password = request.POST.get("cpwd") email = request.POST.get("email") allow = request.POST.get("allow") if not all([username, password, re_password, email]): return render(request, 'register.html', {"errmsg": '数据不完整'}) # 第一种校验用户名 # name_exist= models.User.objects.filter(username=username) # if name_exist: # return render(request, 'register.html', {"error": '用户名已存在'}) # 第二种校验用户名 try: user = User.objects.get(username=username) except User.DoesNotExist: # 用户名不存在 user = None if user: return render(request, 'register.html', {"errmsg": '用户名已存在'}) if not re.match(r'^[a-z0-9][w.-]*@[a-z0-9-]+(.[a-z]{2,5}){1,2}$', email): return render(request, 'register.html', {"error": '邮箱格式不正确'}) if allow != "on": return render(request, 'register.html', {"errmsg": '请同意协议'}) user = User.objects.create_user(username=username, password=password, email=email) # django内置的user中有一个is_active,注册成功默认激活,这里不认他激活 user.is_active = 0 user.save() return redirect(reverse('goods:index')) #注册和注册处理分开写 # def register_handle(request): # username = request.POST.get("user_name") # password = request.POST.get("pwd") # re_password = request.POST.get("cpwd") # email = request.POST.get("email") # allow = request.POST.get("allow") # # if not all([username,password,re_password,email]): # return render(request,'register.html',{"error":'数据不完整'}) # #第一种校验用户名 # # name_exist= models.User.objects.filter(username=username) # # if name_exist: # # return render(request, 'register.html', {"error": '用户名已存在'}) # #第二种校验用户名 # try: # user = models.User.objects.get(username=username) # except models.User.DoesNotExist: # #用户名不存在 # user=None # if user: # return render(request, 'register.html', {"error": '用户名已存在'}) # # if not re.match(r'^[a-z0-9][w.-]*@[a-z0-9-]+(.[a-z]{2,5}){1,2}$',email): # return render(request, 'register.html', {"error": '邮箱格式不正确'}) # if allow != "on" : # return render(request, 'register.html', {"error": '请同意协议'}) # # user = models.User.objects.create_user(username=username,password=password,email=email) # #django内置的user中有一个is_active,注册成功默认激活,这里不认他激活 # user.is_active = 0 # user.save() # return redirect(reverse('goods:index')) ##########注册第二种CBV模式##### class RegisterView(View): def get(self,request): return render(request, 'register.html') def post(self,request): print("=========") username = request.POST.get("user_name") password = request.POST.get("pwd") re_password = request.POST.get("cpwd") email = request.POST.get("email") allow = request.POST.get("allow") print(username,password,re_password,email) if not all([username, password, re_password, email]): return render(request, 'register.html', {"errmsg": '数据不完整'}) # 第一种校验用户名 # name_exist= models.User.objects.filter(username=username) # if name_exist: # return render(request, 'register.html', {"error": '用户名已存在'}) # 第二种校验用户名 try: user = User.objects.get(username=username) except User.DoesNotExist: # 用户名不存在 user = None if user: return render(request, 'register.html', {"errmsg": '用户名已存在'}) if not re.match(r'^[a-z0-9][w.-]*@[a-z0-9-]+(.[a-z]{2,5}){1,2}$', email): return render(request, 'register.html', {"errmsg": '邮箱格式不正确'}) if allow != "on": return render(request, 'register.html', {"errmsg": '请同意协议'}) user = User.objects.create_user(username=username, password=password, email=email) # django内置的user中有一个is_active,注册成功默认激活,这里不认他激活 user.is_active = 0 user.save() #发送激活邮件,激活连接地址http://127.0.0.1:8000/user/active/2 #激活连接中要有用户的身份信息,为了防止恶意激活,要对用户信息加密 #加密用户信息,生成激活token serialize = Serializer(settings.SECRET_KEY,3600) info = {"confirm":user.id} token = serialize.dumps(info) #byte类型 token = token.decode() #转成utf8 #发送邮件 send_register_active_email.delay(email,username,token) return redirect('/index') #激活视图 class ActiveView(View): def get(self,request,token): serialize = Serializer(settings.SECRET_KEY, 3600) try: info = serialize.loads(token) #解密 #获取待激活的用户id user_id = info['confirm'] user = User.objects.get(id=user_id) user.is_active = 1 user.save() #激活成功,返回登录页面 return redirect('/login') except SignatureExpired as e: return HttpResponse("激活链接已过期") class LoginView(View): def get(self,request): '''显示登录页面''' # 判断是否记住了用户名 if 'username' in request.COOKIES: username = request.COOKIES.get("username") checked = 'checked' #勾选记住用户名 else: username = '' checked = '' return render(request,'login.html',{'username':username,'checked':checked}) def post(self,request): #登录校验 username = request.POST.get("username") password = request.POST.get("pwd") if not all([username,password]): return render(request,'login.html',{'errmsg':"数据不完整"}) user = authenticate(username=username,password=password) if user is not None: #判断用户是否激活 if user.is_active: login(request, user) #login()使用Django的session框架来将用户的ID保存在session中 #默认跳转到主页,即如果用户直接在login登录则默认跳转主页,如果其他页面转到,则跳转之前页面 next_url = request.GET.get("next",reverse('index')) response = redirect(next_url)#跳转到首页 remember = request.POST.get("remember") if remember == "on": #记住用户名 response.set_cookie('username',username,max_age=7*24*3600) else: response.delete_cookie('username') return response else: return render(request, 'login.html', {'errmsg': "用户未激活"}) else: return render(request, 'login.html', {'errmsg': "用户名或密码错误"}) # /user/logout class LogoutView(View): '''退出登录''' def get(self, request): '''退出登录''' # 清除用户的session信息 logout(request) # 跳转到首页 return redirect(reverse('index')) class IndexView(View): def get(self, request): '''退出登录''' # 清除用户的session信息 # 跳转到首页 return render(request,'index.html')
url.py
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register$',views.RegisterView.as_view(),name='register'),#第一种FBV url(r'^active/(?P<token>.*)$',views.ActiveView.as_view(),name='active'), url(r'^login$',views.LoginView.as_view(),name='login'), url(r'^logout$', views.LogoutView.as_view(), name='logout'), # 注销登录 url(r'^index$', views.IndexView.as_view(), name='index'), # 注销登录 ]