开发|Django实现登录、注册、修改密码、重置密码

需求:
1.实现Django的登录
2.实现Django的注册,校验用户名、密码的长度为6-20,邮箱是否合法,序列化等
3.实现根据ID或者用户名修改密码,ID为数据库的用户表的id
4.实现重置密码功能,统一为123456,因为没有邮箱服务器所以简单实现

一、功能实现
1.根据Django自带的用户表序列化校验字段:

新建serializers.py文件

#!/usr/bin/env python # -*- coding:utf-8 _*- """ @author:壹拾壹 @Time: 2021/11/8 14:18 """ from django.contrib.auth.models import User from rest_framework.validators import UniqueValidator from rest_framework import serializers from rest_framework_jwt.utils import api_settingsclass RegisterSerializer(serializers.ModelSerializer): password_confirm = serializers.CharField(label='确认密码', help_text='确认密码', write_only=True, min_length=6, max_length=20, error_messages={ 'min_length': '仅允许6-20个字符的密码', 'max_length': '仅允许6-20个字符的密码', }) token = serializers.CharField(label='生成的token', help_text='生成的token', read_only=True)class Meta: model = User fields = ('id', 'username', 'password', 'email', 'token', 'password_confirm') # model指定的模型中没有的字段, 不能在extra_kwargs中来定义 extra_kwargs = { 'username': { 'label': '用户名', 'help_text': '用户名', 'min_length': 6, 'max_length': 20, 'error_messages': { 'min_length': '仅允许6-20个字符的用户名', 'max_length': '仅允许6-20个字符的用户名', } }, 'email': { 'label': '邮箱', 'help_text': '邮箱', 'write_only': True, 'required': True, # 添加邮箱重复校验 'validators': [UniqueValidator(queryset=User.objects.all(), message='此邮箱已注册')], }, 'password': { 'label': '密码', 'help_text': '密码', 'write_only': True, 'min_length': 6, 'max_length': 20, 'error_messages': { 'min_length': '仅允许6-20个字符的密码', 'max_length': '仅允许6-20个字符的密码', } }, }def validate(self, attrs): password = attrs.get('password') password_confirm = attrs.get('password_confirm') if password != password_confirm: raise serializers.ValidationError("两次输入的密码不一致!")return attrsdef create(self, validated_data): validated_data.pop('password_confirm') # 可以使用create_user方法来创建用户, 会对密码进行加密 user = User.objects.create_user(**validated_data)# 生成token ? jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) user.token = token return user

2. 在view.py视图里配置
from django.contrib.auth.models import User from rest_framework.generics import CreateAPIView from rest_framework.views import APIView from rest_framework.response import Responsefrom . import serializersclass RegisterView(CreateAPIView): """注册接口 """ serializer_class = serializers.RegisterSerializer # 如果某个视图中, 没有获取信息的接口, 那么可以不用指定queryset类属性class UsernameValidateView(APIView): """校验用户名 """def get(self, request, username): data_dict = { "username": username, "count": User.objects.filter(username=username).count() } return Response(data_dict)class EmailValidateView(APIView): """ 校验邮箱 """def get(self, request, email): data_dict = { "email": email, "count": User.objects.filter(email=email).count() } return Response(data_dict)class UpdatePasswordView(APIView): """修改密码 """ def put(self, request): """ 根据传的用户名修改密码 :param request: :return: """ data = https://www.it610.com/article/request.data try: user = User.objects.get(username=data['username']) except: return Response({'message': '账号不存在'}) if not user.check_password(data['old_password']): return Response({'message': '原密码输入有误'}) if data['password'] != data['password2']: return Response({'message': '两次密码不一样,请重新输入'}) user.set_password(data['password']) user.save() return Response({'message': 'ok'}) # def put(self, request, pk): #""" #根据传的用户ID修改密码 #:param request: #:param pk: #:return: #""" #data = https://www.it610.com/article/request.data #user = User.objects.get(id=pk) #print(user) #if not user.check_password(data['old_password']): #raise Exception('原密码输入有误') #if data['password'] != data['password2']: #raise Exception('两次密码不一样,请重新输入') #user.set_password(data['password']) #user.save() #return Response({'message': 'ok'})class ResetPasswordView(APIView): """重置密码 """ def post(self, request): data = https://www.it610.com/article/request.data try: user = User.objects.get(username=data['username']) except: return Response({'message': '账号不存在'}) # 所有的密码都重置为123456 user.set_password('123456') user.save() return Response({'message': 'ok'})class LogoutView(APIView): """退出视图 """def get(self, request): logout(request) return Response({"message": 'ok'})

3.配置路由信息:urls.py
from django.conf.urls import url from django.urls import path, re_path from rest_framework_jwt.views import obtain_jwt_token from . import viewsurlpatterns = [ path('login/', obtain_jwt_token), path('register/', views.RegisterView.as_view()),re_path(r'^(?P\w{6,20})/count/$', views.UsernameValidateView.as_view(), name='check_username'), re_path(r'^(?P[A-Za-z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9_-]+)/count/$', views.EmailValidateView.as_view(), name='check_email'), # 根据传的ID重置密码 # url(r"^users/(?P\d+)/password/$", views.UpdatePasswdView.as_view()) # 根据用户名重置密码 path('password/', views.UpdatePasswordView.as_view()), # 直接重置密码为123456 path('reset_password/', views.ResetPasswordView.as_view()) # 退出接口 path('logout/', views.LogoutView.as_view(), name='logout') ]

二、启动项目成功调试:
1.登录
开发|Django实现登录、注册、修改密码、重置密码
文章图片

2.注册
开发|Django实现登录、注册、修改密码、重置密码
文章图片

3.修改密码(只写用户名的,根据ID的已经注释了代码,想调试可以直接取消注释)
开发|Django实现登录、注册、修改密码、重置密码
文章图片

4.重置密码:重置的密码统一为123456,可以在代码里修改
开发|Django实现登录、注册、修改密码、重置密码
文章图片

三、痛点
1.目前只针对注册进行序列化,没有对修改密码,重置密码等序列化,导致修改密码的时候会绕过验证
2.目前没有免密登录
3.目前没有注销账号接口
【开发|Django实现登录、注册、修改密码、重置密码】

    推荐阅读