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_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.登录

Django实现登录、注册、修改密码、重置密码_第1张图片

2.注册 

Django实现登录、注册、修改密码、重置密码_第2张图片

 3.修改密码(只写用户名的,根据ID的已经注释了代码,想调试可以直接取消注释)

Django实现登录、注册、修改密码、重置密码_第3张图片

 4.重置密码:重置的密码统一为123456,可以在代码里修改

Django实现登录、注册、修改密码、重置密码_第4张图片

三、痛点

1.目前只针对注册进行序列化,没有对修改密码,重置密码等序列化,导致修改密码的时候会绕过验证

2.目前没有免密登录

3.目前没有注销账号接口

你可能感兴趣的:(开发,django,python,后端)