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'), # 注销登录
- ]
来源: http://www.bubuko.com/infodetail-2963608.html