项目的配置都是十分基础的东西,在此就不再做过多的赘述,下边先用一张图片了解一下,登陆注册的具体流程
通过这张图我们可以基本了解,登陆注册需要的参数以及使用的一些方法,知识点,下边我们开始代码部分
我们先来定义一下模型类
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(max_length=11, verbose_name='手机号', unique=True, null=True)
last_login = models.DateTimeField(blank=True, null=True)
class Meta:
db_table = 'user'
def __str__(self):
return self.username
这里的模型类我使用了django里的AbstractUser,里边包括我们所需要的一些参数,AbstractUser中具体有哪些参数我们可以CTRL + B 进入他的这个方法里边看一下,然后根据需求在此基础上进行补充 例如在这里我用到了手机号和登陆时间,就需要自己定义一下这两个字段
我们在模型类里边定义的手机号,主要是用于发送短信验证码完成登录,可以在登陆的时候更加的严谨一些
class SendSMSCode(APIView):
def post(self, request):
phone = request.data.get('phone')
print(phone)
# 发送短信验证码
# delay触发异步任务
resp, sms_code = send_message(phone)
resp_data = json.loads(resp)
print(resp_data.get('statusCode'))
if resp_data['statusCode'] in ["000000", "112310"]:
# 1.发送成功的验证码写入redis
# 2.TODO 使用哪一种数据类型:zset,set,hash,list,string
# 3.用string最简单 string:k:phone v sms_code
client = redis.Redis()
# 设置有效期
client.setex('sms_{}'.format(phone), 120, sms_code)
return Response({'msg': '发送短信验证码成功', 'code': '200'})
else:
return Response({'msg': '发送短信验证码失败'})
因为这是在我自己电脑上测试的,所以短信验证码返回的状态码我就写了两种,方便测试
from celery import shared_task
from ronglian_sms_sdk import SmsSDK
import random
accId = ''
accToken = ''
appId = ''
@shared_task()
def send_message(phone):
sdk = SmsSDK(accId, accToken, appId)
tid = '1' # 容联云分配的一个测试短信验证码模版
# mobile = '18937774001' # 接收短信的手机号
data = '%06d' % random.randint(100000, 999999)
datas = (data,)
resp = sdk.sendMessage(tid, phone, datas)
print('>>>>>>>>>>>>>>>>>', resp)
print('>>>>>>>>>>>>>>>>>', data)
return resp, data
if __name__ == '__main__':
send_message()
上边三个参数可以自己去容联云申请账号然后把需要的参数复制到项目中即可
容联云_百度搜索https://www.baidu.com/s?wd=%E5%AE%B9%E8%81%94%E4%BA%91&rsv_spt=1&rsv_iqid=0xe89aacf0000003be&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=0&rsv_dl=tb&oq=AbstractUser&rsv_btype=t&inputT=2037&rsv_t=dc86tuh6Hw8LqjCZrjaj8pN5qs36c2cE5SEdiNQzL%2BYO6vYbiNo9rwvjI56LLEvGJm2A&rsv_pq=f3fd3ca90001a8c1&rsv_sug3=42&rsv_sug1=26&rsv_sug7=100&rsv_sug2=0&rsv_sug4=3357
class RegisterView(APIView):
def post(self, request):
# 注册
user_name = request.data.get("username")
print(user_name)
pwd = request.data.get("password")
phone = request.data.get("phone")
# 根据user_name 判断用户是否存在数据库中
res_user = User.objects.filter(username=user_name).count()
res_phone = User.objects.filter(phone=phone).count()
res_username = User.objects.filter(username=user_name).count()
if res_username != 0:
return Response({'code': 502, 'msg': '用户名重复'})
if res_phone != 0:
return Response({'code': 501, 'msg': '手机号重复'})
if res_user == 0:
user = User.objects.create_user(username=user_name, password=pwd, phone=phone,
last_login=time.strftime('%Y-%m-%d %H:%M:%S'))
print('>>>', user)
return Response({"code": '200', 'msg': 'register success'})
在注册时时候我们需要验证用户名和手机号是否已经存在了,如果已经存在则需要提示用户,用户名或者手机号重复,在这里我通过判断用户输入的用户名或者手机号在数据库里的数量是否为零来判断用户名和手机号是否重复,有的小伙伴可能会有疑问,在模型类中已经定义了手机号唯一,为什么还需要判断手机号。因为在模型类里便虽然已经定义过了,如果用户使用了重复的手机号,虽然不能注册成功,但是不会给用户返回错误的信息,因此为了避免不必要的麻烦,我们会再判断一下手机号的重复性
注册好了之后用户就可以进行登陆了
class LoginView(APIView):
def post(self, request):
user_name = request.data.get("username")
print(user_name)
pwd = request.data.get("password")
phone = request.data.get("phone")
code = request.data.get('code')
print(code)
# 校验短信验证码
client = redis.Redis()
# msmcode = 'code_%s' % phone
# msmcodes = client.get(msmcode)
msmcodes = client.get('sms_%s' % phone).decode()
print('>>>>>>>>>>>>>>>', msmcodes)
# 校验验证码是否过期
if not msmcodes:
return Response({'msg': '验证码过期请重新登陆', "code": '204'})
# 校验验证码是否正确
if msmcodes != code:
return Response({'msg': '验证码错误请重新输入', "code": '401'})
# 登录
user = User.objects.get(username=user_name)
user.last_login = time.strftime('%Y-%m-%d %H:%M:%S')
user.save()
# 密码效验
rest = check_password(pwd, user.password)
#
if not rest:
return Response({'msg': '密码错误', "code": '204'})
# 加密时生成第二部分的字符串
payload_dict = jwt_payload_handler(user)
# 生成token
token = jwt_encode_handler(payload_dict)
resource_list = get_resource_list(user)
return Response({'msg': 'login success', 'token': token, "code": '200', 'resource_list': resource_list})
因为我们将用户发送的验证码放在了redis数据库中,所以在用户登陆的时候我们需要去redis数据库中找到对应的值,千万要记得decode解码,不然不会匹配成功,因为我们在将验证码写入到redis里的时候设置了过期时间,所以我们要判断是否能取到这个数据,如果取不到就证明,已经到了过期时间即验证码已过期
在用户输入用户名和手机号的时候我们仍需判断,如果没有该条数据就证明,用户未注册,在输入密码的时候我们也要将其与数据库中的密码进行对比,需要注意的是,在数据库中存入的时候是密文存入的我们需要将其解密之后再与用户输入的密码进行对比,以此来判断是否一致
而且在登陆的时候我们需要生成一个token发送给前端,让前端接收传来的用户信息,这里生成token我直接使用的 jwt_payload_handler jwt_encode_handler 方法从rest_framework_jwt.utils导入进来python自带的方法来进行token的生成
以上方法即可使用django实现简单的登陆注册,如果有哪里写的不合理的地方,请及时告知