【Django开发】前后端分离django美多商城项目第9篇:收货地址,1. 展示收货地址界面【附代码文档】
【摘要】 本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后端接口设计: 用户部分 JWT 什么是JWT 起源 传统的session认
本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后端接口设计: 用户部分 JWT 什么是JWT 起源 传统的session认证 用户部分 登录 1. 业务说明 2. 后端接口设计 3. 后端实现 登录 使用登录的流程 创建模型类 urllib使用说明 登录回调处理 登录 使用登录的流程 创建模型类 urllib使用说明 绑定用户身份接口 邮件与验证 学习目标: 业务说明: 技术说明: 保存邮箱并发送验证邮件 省市区地址查询 数据库建表 说明 页面静态化 注意 定时任务 安装 部分 详情页 异步任务的触发 。 后端接口设计 收货地址 使用缓存 安装 使用方法 为省市区视图添加缓存 数据库表设计 表结构 数据表结构 首页数据表结构 Docker使用 Docker简介 用户浏览历史记录 1. 保存 后端接口设计 后端实现 搜索 1. 需求分析 2. 搜索引擎原理 3. Elasticsearch 部分 业务需求分析 技术实现 数据存储设计 1. Redis保存已登录用户 商品部分 业务需求分析 技术实现 查询数据 1. 后端接口设计 部分 业务需求分析 技术实现 登录合并 修改登录视图 部分 保存 1. 后端接口设计 2. 后端实现 保存的思路 创建数据库模型类 接入 开发平台登录 沙箱环境 Xadmin 1. 安装 2. 使用 站点的全局配置 站点Model管理。 在Ubuntu中安装 2. 启动与停止 3. 镜像操作 端与自定义文件存储系统 1. 的Python客户端 安装 使用。
完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Django/前后端分离django美多商城项目/note.md
感兴趣的小伙伴可以自取哦~
全套教程部分目录:
部分文件图片:
收货地址
用户地址的主要业务逻辑有:
- 展示省市区数据
- 用户地址的增删改查处理
- 设置默认地址
- 设置地址标题
省市区三级联动
1. 展示收货地址界面
提示:
- 省市区数据是在收货地址界面展示的,所以我们先渲染出收货地址界面。
- 收货地址界面中基础的交互已经提前实现。
class AddressView(LoginRequiredMixin, View):
"""用户收货地址"""
def get(self, request):
"""提供收货地址界面"""
return render(request, 'user_center_site.html')
2. 准备省市区模型和数据
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
模型说明:
- 自关联字段的外键指向自身,所以
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
3. 查询省市区数据
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /areas/ |
> | |
2.请求参数:查询参数 |
- 如果前端没有传入
area_id
,表示用户需要省份数据 - 如果前端传入了
area_id
,表示用户需要市或区数据
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
area_id | string | 否 | 地区ID |
> | |||
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.查询省市区数据后端逻辑实现
- 如果前端没有传入
area_id
,表示用户需要省份数据 - 如果前端传入了
area_id
,表示用户需要市或区数据
class AreasView(View):
"""省市区数据"""
def get(self, request):
"""提供省市区数据"""
area_id = request.GET.get('area_id')
if not area_id:
# 提供省份数据
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': RETCODE.DBERR, 'errmsg': '省份数据错误'})
# 响应省份数据
return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'province_list': province_list})
else:
# 提供市或区数据
try:
parent_model = Area.objects.get(id=area_id) # 查询市或区的父级
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': RETCODE.DBERR, 'errmsg': '城市或区数据错误'})
# 响应市或区数据
return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'sub_data': sub_data})
4. Vue渲染省市区数据
1.
user_center_site.js
中
mounted() {
// 获取省份数据
this.get_provinces();
},
// 获取省份数据
get_provinces(){
let url = '/areas/';
axios.get(url, {
responseType: 'json'
})
.then(response => {
if (response.data.code == '0') {
this.provinces = response.data.province_list;
} else {
console.log(response.data);
this.provinces = [];
}
})
.catch(error => {
console.log(error.response);
this.provinces = [];
})
},
watch: {
// 监听到省份id变化
'form_address.province_id': function(){
if (this.form_address.province_id) {
let url = '/areas/?area_id=' + this.form_address.province_id;
axios.get(url, {
responseType: 'json'
})
.then(response => {
if (response.data.code == '0') {
this.cities = response.data.sub_data.subs;
} else {
console.log(response.data);
this.cities = [];
}
})
.catch(error => {
console.log(error.response);
this.cities = [];
})
}
},
// 监听到城市id变化
'form_address.city_id': function(){
if (this.form_address.city_id){
let url = '/areas/?area_id='+ this.form_address.city_id;
axios.get(url, {
responseType: 'json'
})
.then(response => {
if (response.data.code == '0') {
this.districts = response.data.sub_data.subs;
} else {
console.log(response.data);
this.districts = [];
}
})
.catch(error => {
console.log(error.response);
this.districts = [];
})
}
}
},
2.
user_center_site.html
中
<div class="form_group">
<label>*所在地区:</label>
<select v-model="form_address.province_id">
<option v-for="province in provinces" :value="province.id">[[ province.name ]]</option>
</select>
<select v-model="form_address.city_id">
<option v-for="city in cities" :value="city.id">[[ city.name ]]</option>
</select>
<select v-model="form_address.district_id">
<option v-for="district in districts" :value="district.id">[[ district.name ]]</option>
</select>
</div>
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)
```python class AreasView(View): """省市区数据"""def get(self, request): """提供省市区数据""" area_id = request.GET.get('area_id')
if not area_id: # 读取省份缓存数据 province_list = cache.get('province_list') if not province_list: # 提供省份数据 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': RETCODE.DBERR, 'errmsg': '省份数据错误'}) # 存储省份缓存数据 cache.set('province_list', province_list, 3600) # 响应省份数据 return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'province_list': province_list}) else: # 读取市或区缓存数据 sub_data = cache.get('sub_area_' + area_id) if n
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)