当前位置: 首页 > article >正文

Vue全栈开发旅游网项目(10)-用户管理后端接口开发

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 None

3.系统视图函数

文件地址: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 None

3.视图函数

文件地址: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')
]

http://www.kler.cn/a/393963.html

相关文章:

  • [Linux] Linux信号捕捉
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • 速盾:高防 CDN 和 CDN 的缓存机制都一样吗?
  • 【MySQL】约束
  • 搭建Python2和Python3虚拟环境
  • Spring框架之观察者模式 (Observer Pattern)
  • selenium 控制内嵌table滚动条的方法
  • RabbitMQ-死信队列(golang)
  • CouchdbH2database未授权
  • CSS回顾-长度单位汇总详解
  • 基于大语言模型意图识别和实体提取功能;具体ZK数值例子:加密货币交易验证;
  • Unity学习---IL2CPP打包时可能遇到的问题
  • 视图【MySQL】
  • 深入探究 Linux 系统的快照备份与恢复:TimeShift 实践与原理解析
  • Android 无签名系统 debug 版本APK push到设备引起的开机异常问题分析(zygote进程)
  • 【青牛科技】14W 高保真音频放大电路——D2030
  • 大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)
  • Linux入门:环境变量与进程地址空间
  • [Linux] Linux信号捕捉
  • PostgreSQL加密连接SSL配置
  • linux安装ansible
  • 微信小程序家政项目小程序
  • sqoop Oracle 导入到hive 日期时间消失
  • unity 玩家和炸弹切线计算方式
  • python 爱心邮件代码
  • 二叉树的遍历(手动)