1.异步用户登录\登出接口开发
1.设计公共响应数据类型
文件地址:utils/response404.py
from django.http import JsonResponse
class BadRequestJsonResponse(JsonResponse):
    status_code = 400
    def __init__(self, err_list, *args, **kwargs):
        data = {
            "error_code":"400000",
            "error_msg":"参数格式不正确",
            "error_list":err_list
        }
        super().__init__(data,*args, **kwargs)
class MethodNotAllJsonResponse(JsonResponse):
    status_code = 405
    def __init__(self, err_list, *args, **kwargs):
        data = {
            "error_code":"405000",
            "error_msg":"请求方式不被允许",
            "error_list":err_list
        }
        super().__init__(data,*args, **kwargs)2.设计accounts响应数据结构
新建文件:system/serializers.py
from utils.serializers import BaseSerializer
#返回用户基本信息
class UserSerializers(BaseSerializer):
    #重写父类to_dict函数
    def to_dict(self):
        user = self.obj
        return {
            'nickname': user.nickname,
            'avatar': user.avatar.url
        }
#返回用户详细信息
class UserProfileSerializers(BaseSerializer):
    #重写父类to_dict函数
    def to_dict(self):
        profile = self.obj
        return {
            'real_name': profile.real_name,
            'sex':profile.sex,
            'sex_display':profile.get_sex_display()
        }3.视图函数-服务端的处理过程
文件地址:accounts/views.py
def user_api_login(request):
    #确定请求方式
    if request.method == 'POST':
        #表单验证
        form = LoginForm(request.POST)
        #通过验证,则执行登录
        if form.is_valid():
            # 返回内容是登录用户的信息
            user = form.do_login(request)
            #获得用户详细信息
            profile = user.profile
            #合成返回数据
            data = {
                'user':serializers.UserSerializers(user).to_dict(),
                'profile':serializers.UserProfileSerializers(profile).to_dict()
            }
            return http.JsonResponse(data)
        else:
            #没有通过表单验证,返回错误信息
            err = json.load(form.errors.as_json())
            return BadRequestJsonResponse(err)
    else:
        #没有请求方式
        return MethodNotAllJsonResponse([{"detail": "Method not allowed. Only POST is allowed."}])
def user_api_logout(request):
    logout(request)
    return http.HttpResponse(status=201)4.配置路由地址
文件地址:accounts/urls.py
from django.urls import path
from accounts import views
urlpatterns = [
    #用户登录(异步提交)
    path('user/api/login/',views.user_api_login,name='user_api_login'),
    #用户登出(异步提交)
    path('user/api/logout/',views.user_api_logout,name='user_api_logout')
]2.用户详情接口开发
1.设计公共响应数据类型
文件地址:utils/response404.py
class UnauthorizedJsonResponse(JsonResponse):
    status_code = 401
    def __init__(self, *args, **kwargs):
        data = {
            "error_code":"401000",
            "error_msg":"请登录",
        }
        super().__init__(data,*args, **kwargs)2.视图函数-服务端的处理过程
文件地址:accounts/views.py
class UserDetailView(View):
    #用户详情接口
    def get(self, request):
        #获取用户信息
        user = request.user
        #判断用户状态是登录还是未登录
        if not user.is_authenticated:
            #未登录状态返回‘401’状态码
            return UnauthorizedJsonResponse()
        else:
            #返回详细信息
            profile = user.profile
            data = {
                'user':serializers.UserSerializers(user).to_dict(),
                'profile':serializers.UserProfileSerializers(profile).to_dict()
            }
            return http.JsonResponse(data)#向客户端浏览器中响应数据3.配置路由地址
文件地址:accounts/urls.py
from django.urls import path
from accounts import views
urlpatterns = [
    path('user/api/info/',views.UserDetailView.as_view(),name='user_api_info')
]3.短信验证接口开发
1.设计公共响应数据类型
文件地址:utils/response404.py
class ServerErrorJsonResponse(JsonResponse):
    status_code = 500
    def __init__(self, *args, **kwargs):
        data = {
            "error_code":"500000",
            "error_msg":"服务端正忙,请稍后再试",
        }
        super().__init__(data,*args, **kwargs)2.验证码表单发送
新建文件:system/forms.py
import random
import re
from django import forms
from django.core.cache import cache
from pymongo import timeout
class SendSmsCodeForm(forms.Form):
    #发送验证码
    phone_num = forms.CharField(label='手机号码',required=True,
                                error_messages={'required':'请输入手机号码'})
    def clean_phone_num(self):
        #验证是否为手机号码
        phone_num = self.cleaned_data['phone_num']
        pattern = r'^1[0-9]{10}$'
        if not re.search(pattern, phone_num):
            raise forms.ValidationError('手机号码%s输入不正确',code='invalid_phone',params=(phone_num,))
        return phone_num
    def send_sms_code(self):
        #生成验证码并发送
        sms_code = random.randint(100000,999999)
        phone_num = self.cleaned_data.get('phone_num',None)
        try:
            #将验证码存在radis中
            # key = 'sms_code_{}'.format(phone_num)
            time_out = 5*60
            # cache.set(key,sms_code,time_out)
            return {
                'phone_num': phone_num,
                'sms_code': sms_code,
                'time_out': time_out
            }
        except Exception as e:
            print(e)
            return None3.系统视图函数
文件地址:system/views.py
class SmsCodeView(FormView):
    form_class = SendSmsCodeForm
    def form_valid(self, form):
        #表单通过验证,生成并获得验证码
        data = form.send_sms_code()
        if data is not None:
            return http.JsonResponse(data,status=201)
        return ServerErrorJsonResponse()
    def form_invalid(self, form):
        #表单未通过验证
        err_list = json.loads(form.errors.as_json())
        return BadRequestJsonResponse(err_list)4.配置路由
文件地址:system/urls.py
from django.urls import path
from system import views
urlpatterns= [
    path('send/sms/',views.SmsCodeView.as_view(),name='send_sms')
]5.效果图示
向指定的手机号发送随机验证码

4.注册用户
1.登录日志&装饰器
文件地址:accounts/models.py
class User(AbstractUser):
    avatar = models.ImageField("头像", null=True, upload_to="avatar/%Y%m")
    nickname = models.CharField("昵称", max_length=32, unique=True)
    class Meta:
        db_table = "account_user"
    👇
    def add_login_record(self, **kwargs):
        #写入日志,保存登入历史【把传入的参数kwargs,创建在日志中】。
        self.login_records.create(**kwargs)
    @property
    def avatar_url(self):
        return self.avatar.url if self.avatar else ''
    👆文件地址:accounts/serializers.py

2.注册表单
文件地址:accounts/forms.py
这段代码定义了一个 Django 注册表单类:
用于验证用户输入的手机号码、密码、昵称和验证码,
并在验证通过后执行用户注册流程,包括创建用户、登录和记录登录信息。
class RegisterForm(forms.Form):
    #用户名
    username = forms.CharField(label='手机号码',max_length=16,required=True,error_messages={
        'required':'请输入手机号码'
    })
    # 密码
    password = forms.CharField(label='密码',max_length=128,required=True,error_messages={
        'required':'请输入密码'
    })
    # 昵称
    nickname = forms.CharField(label='昵称',max_length=16,required=True,error_messages={
        'required':'请输入昵称'
    })
    # 验证码
    sms_code = forms.CharField(label='验证码',max_length=6,required=True,error_messages={
        'required':'请输入验证码'
    })
    def clean_username(self):
        #验证用户名
        username = self.cleaned_data['username']
        pattern = r'^1[0-9]{10}$'
        if not re.search(pattern,username):
            raise forms.ValidationError('手机号码%s输入不正确',code='invalid_phone',params=(username,))
        #利用数据模型对用户内容进行验证
        if User.objects.filter(username=username).exists():
            raise forms.ValidationError('手机号码已被使用')
        return username
    def clean_nickname(self):
        #验证昵称
        nickname = self.cleaned_data['nickname']
        if User.objects.filter(nickname=nickname).exists():
            raise forms.ValidationError('昵称已被使用')
        return nickname
    #【数据获取】
    def clean(self):
        data = super().clean()
        if self.errors:
            return
        phone_num = self.cleaned_data.get('username',None)
        sms_code = self.cleaned_data.get('sms_code', None)
        #注册验证码存入redis中
        return data
    def do_register(self,request):
        #执行注册
        data = self.cleaned_data
        version = request.headers.get('version','')
        source = request.headers.get('source','')
        try:
            #1.写入基础信息
            user = User.objects.create_user(
                username=data.get('username', None),
                password=data.get('password', None),
                nickname=data.get('nickname', None)
            )
            #2.写入详细信息
            profile = Profile.objects.create(
                user = user,
                username = user.username,
                version = version,
                source = source,
            )
            #3.登录
            login(request, user)
            #4.获取最后登录时间
            user.last_login = now()
            # 保存数据
            user.save()
            #获得IP地址
            ip = request.META.get('REMOTE_ADDR', '')
            # 4.写入日志
            user.add_login_record(username=user.username,ip=ip,source=source,version=version)
            return user,profile
        except Exception as e:
            print(e)
            return None3.视图函数
文件地址:accounts/views.py
class UserRegisterView(FormView):
    #用户注册接口
    form_class = RegisterForm #表单验证类
    http_method_names = ['post'] #请求方式
    def form_valid(self, form):
        #验证通过
        result = form.do_register(request=self.request)
        #调用注册函数,完成注册步骤
        if result is not None:
            #合成响应数据
            user,profile = result
            data = {
                'user':serializers.UserSerializers(user).to_dict(),
                'profile':serializers.UserProfileSerializers(profile).to_dict()
            }
            #响应数据数据
            return http.JsonResponse(data, status=201)
        return ServerErrorJsonResponse()
    def form_invalid(self, form):
        #验证失败
        err_list = json.loads(form.errors.as_json())
        return BadRequestJsonResponse(err_list)4.配置路由
文件地址:accounts/urls.py
from django.urls import path
from system import views
urlpatterns= [
    path('user/api/register/',views.UserRegisterView.as_view(),name='user_api_register')
]

















