美多商城项目之用户中心:基本信息邮箱验证收货地址
Posted 黑马程序员官方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了美多商城项目之用户中心:基本信息邮箱验证收货地址相关的知识,希望对你有一定的参考价值。
一、用户基本信息
1.1 用户基本信息逻辑分析
1. 用户基本信息逻辑分析
以下是要实现的后端逻辑
- 用户模型补充
email_active
字段 - 查询用户基本信息
- 添加邮箱
- 发送邮箱验证邮件
- 验证邮箱
1.2 查询用户基本信息
1. 接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /info/ |
2.请求参数
无
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 用户模型补充email_active字段
由于在渲染用户基本信息时,需要渲染用户邮箱验证的状态,所以需要给用户模型补充email_active字段
补充完字段后,需要进行迁移。
python manage.py makemigrations python manage.py migrate
class User(AbstractUser):
"""自定义用户模型类"""
mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
email_active = models.BooleanField(default=False, verbose_name='邮箱验证状态')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
3. 查询用户基本信息
from utils.views import LoginRequiredJSONMixin
class UserInfoView(LoginRequiredJSONMixin, View):
"""用户中心"""
def get(self, request):
"""提供个人信息界面"""
# 获取界面需要的数据,进行拼接
info_data =
'username': request.user.username,
'mobile': request.user.mobile,
'email': request.user.email,
'email_active': request.user.email_active
# 返回响应
return JsonResponse('code':0,
'errmsg':'ok',
'info_data':info_data)
二、添加和验证邮箱
2.1 添加邮箱后端逻辑
1. 添加邮箱接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /emails/ |
2.请求参数
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
string | 是 | 邮箱 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 添加邮箱后端逻辑实现
import json
import re
from django import http
class EmailView(View):
"""添加邮箱"""
def put(self, request):
"""实现添加邮箱逻辑"""
# 接收参数
json_dict = json.loads(request.body.decode())
email = json_dict.get('email')
# 校验参数
if not email:
return http.JsonResponse('code': 400,
'errmsg': '缺少email参数')
if not re.match(r'^[a-z0-9][\\w\\.\\-]*@[a-z0-9\\-]+(\\.[a-z]2,5)1,2$', email):
return http.JsonResponse('code': 400,
'errmsg': '参数email有误')
# 赋值email字段
try:
request.user.email = email
request.user.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 400, 'errmsg': '添加邮箱失败')
# 响应添加邮箱结果
return http.JsonResponse('code':0, 'errmsg': '添加邮箱成功')
2.2 Django发送邮件的配置
1. Django发送邮件流程分析
send_mall()
方法介绍
- 位置:
- 在
django.core.mail
模块提供了send_mail()
来发送邮件。- 方法参数:
send_mail(subject, message, from_email, recipient_list, html_message=None)
subject 邮件标题
message 普通邮件正文,普通字符串
from_email 发件人
recipient_list 收件人列表
html_message 多媒体邮件正文,可以是html字符串
2. 准备发邮件服务器
1.点击进入《设置》界面
2.点击进入《客户端授权密码》界面
3.开启《授权码》,并完成验证短信
4.填写《授权码》
5.完成《授权码》设置
6.配置邮件服务器
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = 'qi_rui_hua@163.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = '123456abc'
#收件人看到的发件人
EMAIL_FROM = '美多商城<qi_rui_hua@163.com>'
2.3 发送邮箱验证邮件
重要提示:
- 发送邮箱验证邮件是耗时的操作,不能阻塞美多商城的响应,所以需要异步发送邮件。
- 我们继续使用Celery实现异步任务。
1. 定义和调用发送邮件异步任务
1.定义发送邮件任务
import logging
from django.conf import settings
from django.core.mail import send_mail
from celery_tasks.main import celery_app
logger = logging.getLogger('django')
@celery_app.task( name='send_verify_email')
def send_verify_email(to_email, verify_url):
"""
发送验证邮箱邮件
:param to_email: 收件人邮箱
:param verify_url: 验证链接
:return: None
"""
subject = "美多商城邮箱验证"
html_message = '<p>尊敬的用户您好!</p>' \\
'<p>感谢您使用美多商城。</p>' \\
'<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \\
'<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
try:
send_mail(subject, "", settings.EMAIL_FROM, [to_email], html_message=html_message)
except Exception as e:
logger.error(e)
2.注册发邮件的任务:main.py
- 在发送邮件的异步任务中,我们用到了Django的配置文件。
- 所以我们需要修改celery的启动文件main.py。
- 在其中指明celery可以读取的Django配置文件。
- 最后记得注册新添加的email的任务
# celery启动文件
from celery import Celery
# 为celery使用django配置文件进行设置
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings")
# 创建celery实例
celery_app = Celery('celery_tasks')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')
# 自动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.email'])
3.调用发送邮件异步任务
# 赋值email字段
try:
request.user.email = email
request.user.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 0, 'errmsg': '添加邮箱失败')
# 异步发送验证邮件
from celery_tasks.email.tasks import send_verify_email
verify_url = '邮件验证链接'
send_verify_email.delay(email, verify_url)
# 响应添加邮箱结果
return http.JsonResponse('code': 0, 'errmsg': '添加邮箱成功')
4.启动Celery
$ celery -A celery_tasks.main worker -l info
2. 生成邮箱验证链接
1.定义生成邮箱验证链接方法
在users.utils.py中添加生成认证的url方法
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings
def generate_verify_email_url(user):
"""
生成邮箱验证链接
:param user: 当前登录用户
:return: verify_url
"""
serializer = Serializer(settings.SECRET_KEY, expires_in=3600)
data = 'user_id': user.id, 'email': user.email
token = serializer.dumps(data).decode()
verify_url = settings.EMAIL_VERIFY_URL + '?token=' + token
return verify_url
2.配置相关参数
# 邮箱验证链接
EMAIL_VERIFY_URL = 'http://www.meiduo.site:8080/success_verify_email.html'
3.使用邮箱验证链接
verify_url = generate_verify_email_url(request.user)
send_verify_email.delay(email, verify_url)
2.4 验证邮箱后端逻辑
1. 验证邮箱接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /emails/verification/ |
2.请求参数:查询参数
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
token | string | 是 | 邮箱激活链接 |
3.响应结果:HTML
字段 | 说明 |
---|---|
邮箱验证失败 | 响应错误提示 |
邮箱验证成功 | 重定向到用户中心 |
2. 验证链接提取用户信息
在users.utils.py中添加生成认证的url方法
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer,BadData
from django.conf import settings
from apps.users.models import User
def check_verify_email_token(token):
"""
验证token并提取user
:param token: 用户信息签名后的结果
:return: user, None
"""
serializer = Serializer(settings.SECRET_KEY, expires_in=3600)
try:
data = serializer.loads(token)
except BadData:
return None
else:
user_id = data.get('user_id')
email = data.get('email')
try:
user = User.objects.get(id=user_id, email=email)
except User.DoesNotExist:
return None
else:
return user
3. 验证邮箱后端逻辑实现
验证邮箱的核心:就是将用户的
email_active
字段设置为True
class VerifyEmailView(View):
def put(self, request):
# - 1.接收 token
token = request.GET.get('token')
if not token:
return JsonResponse('code': 400, 'errmsg': 'token缺少')
# - 2.解密
data_dict = check_verify_email_token(token)
# - 4.去数据库对比 user_id,email
try:
user = User.objects.get(pk=data_dict.get('user_id'), email=data_dict.get('email'))
except Exception as e:
print(e)
return JsonResponse('code': 400, 'errmsg': '参数有误!')
# - 5.修改激活状态
try:
user.email_active = True
user.save()
except Exception as e:
return JsonResponse('code': 0, 'errmsg': '激活失败!')
三、收获地址
省市区三级联动
1. 准备省市区模型和数据
创建areas子应用
from django.db import models
class Area(models.Model):
"""省市区"""
name = models.CharField(max_length=20, verbose_name='名称')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subs', null=True, blank=True, verbose_name='上级行政区划')
class Meta:
db_table = 'tb_areas'
verbose_name = '省市区'
verbose_name_plural = '省市区'
def __str__(self):
return self.name
模型说明:
-
安装子应用之后,需要迁移
python manage.py makemigrations python manage.py migrate
-
自关联字段的外键指向自身,所以
models.ForeignKey('self')
-
使用
related_name
指明父级查询子级数据的语法- 默认
Area模型类对象.area_set
语法
- 默认
-
related_name='subs'
- 现在
Area模型类对象.subs
语法
- 现在
导入省市区数据
mysql -h数据库ip地址 -u数据库用户名 -p数据库密码 数据库 < areas.sql
mysql -h127.0.0.1 -uroot -pmysql meiduo_mall < areas.sql
总路由
# areas
path('', include('apps.areas.urls')),
子路由
from django.conf.urls import url
from . import views
urlpatterns = [
]
3. 查询省数据
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /areas/ |
2.请求参数:查询参数
- 无
3.响应结果:JSON
-
省份数据
"code":"0", "errmsg":"OK", "province_list":[ "id":110000, "name":"北京市" , "id":120000, "name":"天津市" , "id":130000, "name":"河北省" , ...... ]
-
市或区数据
"code":"0", "errmsg":"OK", "sub_data": "id":130000, "name":"河北省", "subs":[ "id":130100, "name":"石家庄市" , ...... ]
4.查询省数据后端逻辑实现
from django.http import JsonResponse
from django.views import View
from apps.areas.models import Area
import logging
logger = logging.getLogger('django')
class AreasView(View):
"""省市区数据"""
def get(self, request):
"""提供省市区数据"""
# 提供省份数据
try:
# 查询省份数据
province_model_list = Area.objects.filter(parent__isnull=True)
# 序列化省级数据
province_list = []
for province_model in province_model_list:
province_list.append('id': province_model.id, 'name': province_model.name)
except Exception as e:
logger.error(e)
return JsonResponse('code': 400, 'errmsg': '省份数据错误')
# 响应省份数据
return JsonResponse('code': 0, 'errmsg': 'OK', 'province_list': province_list)
4. 查询市区县数据
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /areas/(?P<pk>[1-9]\\d+)/ |
2.请求参数:查询参数
- 无
3.响应结果:JSON
-
市或区数据
"code":"0", "errmsg":"OK", "sub_data": "id":130000, "name":"河北省", "subs":[ "id":130100, "name":"石家庄市" , ...... ]
4.查询市区数据后端逻辑实现
class SubAreasView(View):
"""省市区数据"""
def get(self, request,pk):
"""提供省市区数据"""
# 提供市或区数据
try:
parent_model = Area.objects.get(id=pk) # 查询市或区的父级
sub_model_list = parent_model.subs.all()
# 序列化市或区数据
sub_list = []
for sub_model in sub_model_list:
sub_list.append('id': sub_model.id, 'name': sub_model.name)
sub_data =
'id': parent_model.id, # 父级pk
'name': parent_model.name, # 父级name
'subs': sub_list # 父级的子集
except Exception as e:
logger.error(e)
return JsonResponse('code': 400, 'errmsg': '城市或区数据错误')
# 响应市或区数据
return JsonResponse('code': 0, 'errmsg': 'OK', 'sub_data': sub_data)
5. 缓存省市区数据
提示:
- 省市区数据是我们动态查询的结果。
- 但是省市区数据不是频繁变化的数据,所以没有必要每次都重新查询。
- 所以我们可以选择对省市区数据进行缓存处理。
1.缓存工具
from django.core.cache import cache
- 存储缓存数据:
cache.set('key', 内容, 有效期)
- 读取缓存数据:
cache.get('key')
- 删除缓存数据:
cache.delete('key')
- 注意:存储进去和读取出来的数据类型相同,所以读取出来后可以直接使用。
2.缓存逻辑
3.缓存逻辑实现
- 省份缓存数据
cache.set('province_list', province_list, 3600)
- 市或区缓存数据
cache.set('sub_area_' + area_id, sub_data, 3600)
3.2 新增地址前后端逻辑
1. 定义用户地址模型类
1.用户地址模型类
from utils.models import BaseModel
class Address(BaseModel):
"""用户地址"""
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name='用户')
title = models.CharField(max_length=20, verbose_name='地址名称')
receiver = models.CharField(max_length=20, verbose_name='收货人')
province = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='province_addresses', verbose_name='省')
city = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='city_addresses', verbose_name='市')
district = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='district_addresses', verbose_name='区')
place = models.CharField(max_length=50, verbose_name='地址')
mobile = models.CharField(max_length=11, verbose_name='手机')
tel = models.CharField(max_length=20, null=True, blank=True, default='', verbose_name='固定电话')
email = models.CharField(max_length=30, null=True, blank=True, default='', verbose_name='电子邮箱')
is_deleted = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'tb_address'
verbose_name = '用户地址'
verbose_name_plural = verbose_name
ordering = ['-update_time']
2.
Address
模型类说明
Address
模型类中的外键指向areas/models
里面的Area
。指明外键时,可以使用应用名.模型类名
来定义。ordering
表示在进行Address
查询时,默认使用的排序方式。ordering = ['-update_time']
: 根据更新的时间倒叙。
3.补充用户模型默认地址字段
class User(AbstractUser):
"""自定义用户模型类"""
mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
email_active = models.BooleanField(default=False, verbose_name='邮箱验证状态')
default_address = models.ForeignKey('Address', related_name='users', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='默认地址')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
需要进行迁移。
python manage.py makemigrations python manage.py migrate
2. 新增地址接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | POST |
请求地址 | /addresses/create/ |
2.请求参数:JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
receiver | string | 是 | 收货人 |
province_id | string | 是 | 省份ID |
city_id | string | 是 | 城市ID |
district_id | string | 是 | 区县ID |
place | string | 是 | 收货地址 |
mobile | string | 是 | 手机号 |
tel | string | 否 | 固定电话 |
string | 否 | 邮箱 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
id | 地址ID |
receiver | 收货人 |
province | 省份名称 |
city | 城市名称 |
district | 区县名称 |
place | 收货地址 |
mobile | 手机号 |
tel | 固定电话 |
邮箱 |
3. 新增地址后端逻辑实现
提示:
- 用户地址数量有上限,最多20个,超过地址数量上限就返回错误信息
class CreateAddressView(LoginRequiredJSONMixin, View):
"""新增地址"""
def post(self, request):
"""实现新增地址逻辑"""
# 判断是否超过地址上限:最多20个
# Address.objects.filter(user=request.user).count()
count = request.user.addresses.count()
if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
return http.JsonResponse('code': RETCODE.THROTTLINGERR, 'errmsg': '超过地址数量上限')
# 接收参数
json_dict = json.loads(request.body.decode())
receiver = json_dict.get('receiver')
province_id = json_dict.get('province_id')
city_id = json_dict.get('city_id')
district_id = json_dict.get('district_id')
place = json_dict.get('place')
mobile = json_dict.get('mobile')
tel = json_dict.get('tel')
email = json_dict.get('email')
# 校验参数
if not all([receiver, province_id, city_id, district_id, place, mobile]):
return http.HttpResponseBadRequest('缺少必传参数')
if not re.match(r'^1[3-9]\\d9$', mobile):
return http.HttpResponseBadRequest('参数mobile有误')
if tel:
if not re.match(r'^(0[0-9]2,3-)?([2-9][0-9]6,7)+(-[0-9]1,4)?$', tel):
return http.HttpResponseBadRequest('参数tel有误')
if email:
if not re.match(r'^[a-z0-9][\\w\\.\\-]*@[a-z0-9\\-]+(\\.[a-z]2,5)1,2$', email):
return http.HttpResponseBadRequest('参数email有误')
# 保存地址信息
try:
address = Address.objects.create(
user=request.user,
title = receiver,
receiver = receiver,
province_id = province_id,
city_id = city_id,
district_id = district_id,
place = place,
mobile = mobile,
tel = tel,
email = email
)
# 设置默认地址
if not request.user.default_address:
request.user.default_address = address
request.user.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': RETCODE.DBERR, 'errmsg': '新增地址失败')
# 新增地址成功,将新增的地址响应给前端实现局部刷新
address_dict =
"id": address.id,
"title": address.title,
"receiver": address.receiver,
"province": address.province.name,
"city": address.city.name,
"district": address.district.name,
"place": address.place,
"mobile": address.mobile,
"tel": address.tel,
"email": address.email
# 响应保存结果
return JsonResponse('code': 0, 'errmsg': '新增地址成功', 'address':address_dict)
3.3 展示地址逻辑
1. 展示地址接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /addresses/ |
2.请求参数
无
2. 展示地址后端逻辑实现
class AddressView(View):
"""用户收货地址"""
def get(self, request):
"""提供地址管理界面
"""
# 获取所有的地址:
addresses = Address.objects.filter(user=request.user,
is_deleted=False)
# 创建空的列表
address_dict_list = []
# 遍历
for address in addresses:
address_dict =
"id": address.id,
"title": address.title,
"receiver": address.receiver,
"province": address.province.name,
"city": address.city.name,
"district": address.district.name,
"place": address.place,
"mobile": address.mobile,
"tel": address.tel,
"email": address.email
# 将默认地址移动到最前面
default_address = request.user.default_address
if default_address.id == address.id:
# 查询集 addresses 没有 insert 方法
address_dict_list.insert(0, address_dict)
else:
address_dict_list.append(address_dict)
default_id = request.user.default_address_id
return JsonResponse('code': 0,
'errmsg': 'ok',
'addresses': address_dict_list,
'default_address_id': default_id)
3.4 修改地址前后端逻辑
1. 修改地址接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /addresses/(?P<address_id>\\d+)/ |
2.请求参数:路径参数 和 JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
address_id | string | 是 | 要修改的地址ID(路径参数) |
receiver | string | 是 | 收货人 |
province_id | string | 是 | 省份ID |
city_id | string | 是 | 城市ID |
district_id | string | 是 | 区县ID |
place | string | 是 | 收货地址 |
mobile | string | 是 | 手机号 |
tel | string | 否 | 固定电话 |
string | 否 | 邮箱 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
id | 地址ID |
receiver | 收货人 |
province | 省份名称 |
city | 城市名称 |
district | 区县名称 |
place | 收货地址 |
mobile | 手机号 |
tel | 固定电话 |
邮箱 |
2. 修改地址后端逻辑实现
提示
- 删除地址后端逻辑和新增地址后端逻辑非常的相似。
- 都是更新用户地址模型类,需要保存用户地址信息。
class UpdateDestroyAddressView(LoginRequiredJSONMixin, View):
"""修改和删除地址"""
def put(self, request, address_id):
"""修改地址"""
# 接收参数
json_dict = json.loads(request.body.decode())
receiver = json_dict.get('receiver')
province_id = json_dict.get('province_id')
city_id = json_dict.get('city_id')
district_id = json_dict.get('district_id')
place = json_dict.get('place')
mobile = json_dict.get('mobile')
tel = json_dict.get('tel')
email = json_dict.get('email')
# 校验参数
if not all([receiver, province_id, city_id, district_id, place, mobile]):
return http.JsonResponse('code': 400,
'errmsg': '缺少必传参数')
if not re.match(r'^1[3-9]\\d9$', mobile):
return http.JsonResponse('code': 400,
'errmsg': '参数mobile有误')
if tel:
if not re.match(r'^(0[0-9]2,3-)?([2-9][0-9]6,7)+(-[0-9]1,4)?$', tel):
return http.JsonResponse('code': 400,
'errmsg': '参数tel有误')
if email:
if not re.match(r'^[a-z0-9][\\w\\.\\-]*@[a-z0-9\\-]+(\\.[a-z]2,5)1,2$', email):
return http.JsonResponse('code': 400,
'errmsg': '参数email有误')
# 判断地址是否存在,并更新地址信息
try:
Address.objects.filter(id=address_id).update(
user = request.user,
title = receiver,
receiver = receiver,
province_id = province_id,
city_id = city_id,
district_id = district_id,
place = place,
mobile = mobile,
tel = tel,
email = email
)
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 400, 'errmsg': '更新地址失败')
# 构造响应数据
address = Address.objects.get(id=address_id)
address_dict =
"id": address.id,
"title": address.title,
"receiver": address.receiver,
"province": address.province.name,
"city": address.city.name,
"district": address.district.name,
"place": address.place,
"mobile": address.mobile,
"tel": address.tel,
"email": address.email
# 响应更新地址结果
return JsonResponse('code': 0, 'errmsg': '更新地址成功', 'address': address_dict)
3.5 删除地址前逻辑
1. 删除地址接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | DELETE |
请求地址 | /addresses/(?P<address_id>\\d+)/ |
2.请求参数:路径参数
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
address_id | string | 是 | 要修改的地址ID(路径参数) |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 删除地址后端逻辑实现
提示:
- 删除地址不是物理删除,是逻辑删除。
class UpdateDestroyAddressView(LoginRequiredJSONMixin, View):
"""修改和删除地址"""
def put(self, request, address_id):
"""修改地址"""
......
def delete(self, request, address_id):
"""删除地址"""
try:
# 查询要删除的地址
address = Address.objects.get(id=address_id)
# 将地址逻辑删除设置为True
address.is_deleted = True
address.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 400, 'errmsg': '删除地址失败')
# 响应删除地址结果
return http.JsonResponse('code': 0, 'errmsg': '删除地址成功')
3.6 设置默认地址
1. 设置默认地址接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /addresses/(?P<address_id>\\d+)/default/ |
2.请求参数:路径参数
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
address_id | string | 是 | 要修改的地址ID(路径参数) |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 设置默认地址后端逻辑实现
class DefaultAddressView(LoginRequiredJSONMixin, View):
"""设置默认地址"""
def put(self, request, address_id):
"""设置默认地址"""
try:
# 接收参数,查询地址
address = Address.objects.get(id=address_id)
# 设置地址为默认地址
request.user.default_address = address
request.user.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 400, 'errmsg': '设置默认地址失败')
# 响应设置默认地址结果
return JsonResponse('code': 0, 'errmsg': '设置默认地址成功')
3.7 修改地址标题
1. 修改地址标题接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /addresses/(?P<address_id>\\d+)/title/ |
2.请求参数:路径参数
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
address_id | string | 是 | 要修改的地址ID(路径参数) |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 修改地址标题后端逻辑实现
class UpdateTitleAddressView(LoginRequiredJSONMixin, View):
"""设置地址标题"""
def put(self, request, address_id):
"""设置地址标题"""
# 接收参数:地址标题
json_dict = json.loads(request.body.decode())
title = json_dict.get('title')
try:
# 查询地址
address = Address.objects.get(id=address_id)
# 设置新的地址标题
address.title = title
address.save()
except Exception as e:
logger.error(e)
return http.JsonResponse('code': 400, 'errmsg': '设置地址标题失败')
# 4.响应删除地址结果
return JsonResponse('code': 0, 'errmsg': '设置地址标题成功')
四、修改密码
修改密码接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /password/ |
2.请求参数:JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
old_password | string | 是 | 老密码 |
new_password | string | 是 | 新密码 |
new_password2 | string | 是 | 确认的新密码 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
1. 修改密码后端逻辑
提示:
- 修改密码前需要校验原始密码是否正确,以校验修改密码的用户身份。
- 如果原始密码正确,再将新的密码赋值给用户。
- 我们在 users.views.py 文件中添加如下代码:
class ChangePasswordView(LoginRequiredMixin, View):
"""修改密码"""
def put(self, request):
"""实现修改密码逻辑"""
# 接收参数
dict = json.loads(request.body.decode())
old_password = dict.get('old_password')
new_password = dict.get('new_password')
new_password2 = dict.get('new_password2')
# 校验参数
if not all([old_password, new_password, new_password2]):
return http.JsonResponse('code':400,
'errmsg':'缺少必传参数')
result = request.user.check_password(old_password)
if not result:
return http.JsonResponse('code':400,
'errmsg':'原始密码不正确')
if not re.match(r'^[0-9A-Za-z]8,20$', new_password):
return http.JsonResponse('code':400,
'errmsg':'密码最少8位,最长20位')
if new_password != new_password2:
return http.JsonResponse('code':400,
'errmsg':'两次输入密码不一致')
# 修改密码
try:
request.user.set_password(new_password)
request.user.save()
except Exception as e:
return http.JsonResponse('code':400,
'errmsg':'修改密码失败')
# 清理状态保持信息
logout(request)
response = http.JsonResponse('code':0,
'errmsg':'ok')
response.delete_cookie('username')
# # 响应密码修改结果:重定向到登录界面
return response
以上是关于美多商城项目之用户中心:基本信息邮箱验证收货地址的主要内容,如果未能解决你的问题,请参考以下文章