需求:
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_settings
class 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 attrs
def 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 Response
from . import serializers
class 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 = 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 = 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 = 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 views
urlpatterns = [
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.登录
2.注册
3.修改密码(只写用户名的,根据ID的已经注释了代码,想调试可以直接取消注释)
4.重置密码:重置的密码统一为123456,可以在代码里修改
三、痛点
1.目前只针对注册进行序列化,没有对修改密码,重置密码等序列化,导致修改密码的时候会绕过验证
2.目前没有免密登录
3.目前没有注销账号接口