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')
]