前言:

  登陆和注册功能是一个功能比较完善的网站必备的功能,其中涉及的业务逻辑实用性较强,所以我将Django的注册功能进行了总结,希望可以帮助大家。我们这次使用的第三方短息平台是云通信,当然你可以用其他的第三方平台,我使用这个平台的主要原因是 云通信有免费的试用。云通信的官方文档链接:http://www.yuntongxun.com/doc/ready/demo/1_4_1_2.html,图片验证码是使用的captcha包,这个包可以在git开源社区直接下载 ,如果你有其他更加高大上的验证码模块的可以使用也可以使用,基本的业务逻辑是不变的。

1.准备工作:(1)下载官方API文件,由于这些东西官方已经帮你编写完成了,因此可以直接拿来用,节省了开发时间。将下载的官方的文件复制到你的项目中

     

你可以向我一样在apps(项目子应用目录)的同级目录下创建一个libs的模块包用来存放第三方的包,这样可以让项目的目录更加的清晰,维护起来也比较方便,做到这里基本的准备工作就完成了

(2)在apps模块中创建usrs子应用和verifications子应用,创建方法:在终端执行 python manage.py startapp users/verifications(注意必须在manage.py的目录下执行),这是你创建的子应用并不在apps目录下而是和apps同级目录,你需要手动将users子应用移动到apps中。做完这些你的准备工作就完成了

2.注册路由 :

   (1)在主工程的urls文件添加以下信息

  

  (2)在子应用中创建urls.py文件(用来作为路由的二次引导),这里我就以users为例,verifications的做法一样

  

3.判断用户名是否重复:

  通常的开发环境下,我们认为用户名是不能重复的,因此我们需要写一个api接口验证用户民给是否存在。

  在users子模块views中编写用户名验重代码

# 验证用户名接口

class RegisterUsernameCountAPIView(APIView):
    #  /users/usernames/(?P<username>\w{5,20})/count/

    def get(self,request,username):

        # 查询数据
        count = User.objects.filter(username=username).count()
        context = {
          
 #count=0没有,count=1有
"count":count, "username":username, } return Response(context)

  将api的url注册到urls中 

    url(r'^usernames/(?P<username>\w{5,20})/count/$',views.RegisterUsernameCountAPIView.as_view()),

4.校验手机号码或邮箱

  手机号码或者与邮箱必须是唯一的,将他们设置成唯一的在用户更改信息时对用户身份尽心验证,这样会更加的安全,由于这两个api基本一样,我们在这里以手机号码为例:

  在users子模块views中编写代码

# 验证用户名电话
class RegisterModileCountAPIView(APIView):
    #  /users/mobile/(?P<mobile>1[345789]\d{9})/count/

    def get(self,request,mobile):

        # 查询数据
        count = User.objects.filter(mobile=mobile).count()
        context = {
          #count=0没有,count=1有 "count":count, "mobile":mobile, } return Response(context)

  将api注册到urls中

    url(r'^mobile/(?P<mobile>1[345789]\d{9})/count/',views.RegisterMobileCountAPIView.as_view()),

 好了我们已经进行了一些简单的验证,接下来我们将会通过图片验证与短信验证来进一步完善我们的代码

5.图形验证码

  一个安全可靠的注册界面一些必要的验证手段是必不可少的,我们写的注册模块利用了图形验证码与短信验证码,首先我们需要先获取图形验证码,,在 veriifications子应用中的views中编写获取验证码代码:

from rest_framework.views import APIView
from django.http import HttpResponse
from libs.captcha.captcha import captcha
from django_redis import get_redis_connection

class VerificationAPIView(APIView):
    # /verifications/imagecodes/(?P<image_code_id>.+)/

    def get(self,request,image_code_id):

        #  获取验证码
        text,image_code = captcha.generate_captcha()

        # 将验证码存储到redis中
        redis = get_redis_connection('code')

        redis.setex('img_%s'%image_code_id,200,text)

        return HttpResponse(content_type='image/png',content=image_code)

  这里我们是使用redis数据库存储每次获取的验证码,在使用redis之前我们在settings中添加对验证的redis支持:

#Redis
CACHES = {
    ... ,
    "code": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

  除了setting配置之外我们还需要注意我们在给前端发出响应的时候需要在HttpResponse(content_type='image/png',content=image_code)设置数据类型content-type,不然浏览器会普通的json格式的数据解析,会出现乱码。setting设置完成后将图片验证码的url注册到verifications中

# /verifications/imagecodes/(?P<image_code_id>.+)/ 验证码
url(r'^imagecodes/(?P<image_code_id>.+)/$',views.VerificationAPIView.as_view()),

  

接下来测试下我们的代码:

现在图形验证码就做好了,我们只需要将前端的img标签的src属性的值改为对应的url地址就行了,放在表单里的效果图(随便找的一个注册表单)

6. 短信验证码

  拥有图形验证验证码后我们的注册就有了第一层的保障,但这些还是完全不够的,我们还需要短信验证码进一步验证,首先我们需要在在veriifications子应用中的views中编写获取验证码代码:

class SmscodesAPIView(APIView):

    # /verifications/smscodes/(?P<mobile>1[345789]\d{9})/?text=xxxx & image_code_id=xxxx

    def get(self,request,mobile):

        # 获取验证码
        print(1)

        data= request.query_params
        print(data)

        # 创建并调用序列化器
        value = SmscodesSerializer(data=data)

        value .is_valid(raise_exception=True)

        # 生成短信验证码

        smscode = '%06d'%randint(100000,999999)

        # 将验证码存入redis
        sms_redis = get_redis_connection('smscode')

        sms_redis.setex('sms_%s'%mobile,5*60,smscode)

        # 利用celery实现异步发送短信验证码
        from celery_tasks.sms.tasks import send_sms_code
        # 注意不能直接调用,必须先调用delay()方法
        send_sms_code.delay(mobile, smscode)

        return Response({'message': 'ok'})

这里我们利用了celery 实现短信的异步发布,详情请参考:https://www.cnblogs.com/xuchuankun/p/9787786.html

然后在veriifications子应用中创建serializer文件,这个文件就是我们的序列化器,这是django对数据处理的一整个十分重要的途径,也充分的体现了面向对象的编程思想

from rest_framework import serializers
from django_redis import get_redis_connection


class SmscodesSerializer(serializers.Serializer):
    # 需要验证的字段 text(输入的验证码),image_code_id
    text = serializers.CharField(max_length=4,min_length=4,required=True,label="验证码")
    image_code_id = serializers.UUIDField(label="uuid")

    def validate(self,attrs):

        text = attrs.get("text")
        image_code_id = attrs.get("image_code_id")

        # 链接redis
        redis = get_redis_connection('code')

        redis_text = redis.get('img_%s'%image_code_id)

        #判断验证码是否过期
        if redis_text is None:

            raise serializers.ValidationError('验证码已过期')

        # 判断验证码与保存在redis的是否一直

        if redis_text.decode().lower() != text.lower():

            raise serializers.ValidationError('验证码不一致')


        return attrs

  我们创建的序列化器直接让我们的序列化器继承了serializers.Serializer类,这样为我们省去了许多的时间,但这种方法必须在models类已经创建的情况下才能使用,虽然方便但也由一定的

 限制。如果你没有创建models类,我们可以让序列化器继承serializers.ModelSerializer,虽然比较麻烦但没有限制,我们这次采用第一种方法,另外附上models文件

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.

class User(AbstractUser):

    mobile = models.CharField(max_length=11,unique=True,verbose_name="手机")

    class Meta:

        db_table = 'md_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

这中方法也采用了继承Django内置的AbstractUser的方法,然后在此基础上进行修改。最后我们要把api注册到veriifications路由中

    url(r'^smscodes/(?P<mobile>1[345789]\d{9})/$',views.SmscodesAPIView.as_view()),

  

做到这里我们基本的一些准备工作已经完成了,接下来就要实现注册功能了,详情请看我下一篇博客,。谢谢大家

 

 

 

  

    

  

 

posted on 2018-10-11 10:02  落水猫  阅读(299)  评论(0编辑  收藏  举报