三、收货地址

用户地址的主要业务逻辑有:

  1. 展示省市区数据
  2. 用户地址的增删改查处理
  3. 设置默认地址
  4. 设置地址标题

3.1 省市区三级联动

1. 展示收货地址界面

提示:

  • 省市区数据是在收货地址界面展示的,所以我们先渲染出收货地址界面。
  • 收货地址界面中基础的交互已经提前实现。
class AddressView(LoginRequiredMixin, View):"""用户收货地址"""def get(self, request):"""提供收货地址界面"""return render(request, 'user_center_site.html')

把.html和.js文件复制到响应的位置。

urls.py

    #  展示用户收货地址url(r'^addresses/$', views.AddressView.as_view(), name='address'),

2. 准备省市区模型和数据

新建子应用areas专门管理省市区三级联动

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

将areas.sql文件导入到数据库中

3. 查询省市区数据

1.请求方式

选项 方案
请求方法 GET
请求地址 /areas/

总路由:

    #  areasurl(r'^', include('areas.urls')),

子路由:

from django.conf.urls import url
from . import viewsurlpatterns = [#  省市区三级联动url(r'^areas/$', views.AreasView.as_view()),
]

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,表示用户需要市或区数据
from django.shortcuts import render
from django.views import View
from .models import Area
from django import http
from meiduo_mall.utils.response_code import RETCODE
import logging#  创建日志输出器
logger = logging.getLogger('django')# Create your views here.
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 http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '省份数据错误'})# 响应省份数据return http.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})#  构造子集json数据sub_data = {'id': parent_model.id,  # 父级pk'name': parent_model.name,  # 父级name'subs': sub_list  # 父级的子集}except Exception as e:logger.error(e)return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '城市或区数据错误'})# 响应市或区数据return http.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)

from django.shortcuts import render
from django.views import View
from .models import Area
from django import http
from meiduo_mall.utils.response_code import RETCODE
from django.core.cache import cache
import logging#  创建日志输出器
logger = logging.getLogger('django')# Create your views here.
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 http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '省份数据错误'})#  存储省份缓存数据cache.set('province_list', province_list, 3600)# 响应省份数据return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'province_list': province_list})else:#  读取市或区缓存数据sub_data = cache.get('sub_area_' + area_id)if not sub_data:# 提供市或区数据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})#  构造子集json数据sub_data = {'id': parent_model.id,  # 父级pk'name': parent_model.name,  # 父级name'subs': sub_list  # 父级的子集}except Exception as e:logger.error(e)return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '城市或区数据错误'})#  存储市或区缓存数据cache.set('sub_area_' + area_id, sub_data, 3600)# 响应市或区数据return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'sub_data': sub_data})

美多商城之用户中心(收货地址1)相关推荐

  1. 美多商城之用户中心(收货地址3)

    三.收货地址 3.4 修改地址前后端逻辑 1. 修改地址接口设计和定义 1.请求方式 选项 方案 请求方法 PUT 请求地址 /addresses/(?P<address_id>\d+)/ ...

  2. 美多商城之用户中心(收货地址2)

    三.收货地址 3.2 新增地址前后端逻辑 1. 定义用户地址模型类 1.用户地址模型类 from meiduo_mall.utils.models import BaseModelclass Addr ...

  3. Python_美多商城(用户中心)_5

    用户基本信息 用户基本信息逻辑分析 1. 用户基本信息逻辑分析 以下是要实现的后端逻辑 用户模型补充email_active字段 查询并渲染用户基本信息 添加邮箱 发送邮箱验证邮件 验证邮箱 提示: ...

  4. dj鲜生-32-用户中心-收货地址

    用户中心,收货地址 本页主要有两方面需要处理 >收货地址的显示,get请求 >表单的提交,可用post请求 表单的模板页处理 >先让模板页的界面变继承一下 参考 user_cente ...

  5. 微信小程序开发之——个人中心-收货地址(9)

    一 概述 个人详情页对应的页面为:pages/address/address 页面搭建 页面逻辑 二 页面搭建 2.1 布局文件(address.wml) <view class="l ...

  6. 微信公众号获取微信用户共享收货地址

    wx.openAddress({ success: function (res) { var userName = res.userName; // 收货人姓名 var postalCode = re ...

  7. 美多商城之用户中心(添加和验证邮箱)

    二.添加和验证邮箱 2.1 添加邮箱后端逻辑 1. 添加邮箱接口设计和定义 1.请求方式 选项 方案 请求方法 PUT 请求地址 /emails/ # 添加邮箱url(r'^emails/$', vi ...

  8. 美多商城之用户中心(用户基本信息)

    一.用户基本信息 1.1用户基本信息逻辑分析 1. 用户基本信息逻辑分析 以下是要实现的后端逻辑 用户模型补充email_active字段 查询并渲染用户基本信息 添加邮箱 发送邮箱验证邮件 验证邮箱 ...

  9. 美多商城之用户中心(修改密码)

    修改密码 1. 修改密码后端逻辑 提示: 修改密码前需要校验原始密码是否正确,以校验修改密码的用户身份. 如果原始密码正确,再将新的密码赋值给用户. class ChangePasswordView( ...

最新文章

  1. PCL滤波介绍(2)
  2. iOS 关于第三方键盘
  3. html input选择框样式修改,关于type=file的input框样式修改小结
  4. visual tree view在工具箱力没有_Visual-Inertial Odometry
  5. 【Linux】一步一步学Linux——dir命令(了解)(25)
  6. java之Arrays工具类的使用
  7. 我很喜欢玩游戏,那么我就适合做游戏程序员吗?
  8. java 虚拟内存不够,java虚拟内存不足
  9. leetcode题解98-验证二叉搜索树
  10. web前端入门指南:来看看这位大佬的学习之路吧!
  11. Java-计算器(简易版)
  12. Java实现带发音的简易电子词典
  13. ram与flash你知道多少?
  14. 2019双十一自动领喵币
  15. jeecgboot 查询_124.JSuperQuery高级查询组件 - JeecgBoot 开发文档
  16. 怎么安装aptdaemon模块_dlt-daemon安装教程
  17. 安装k8s - 阿里云镜像
  18. 唐澳华的亚索有错吗?
  19. 三国杀:智能电视迎来对垒时代
  20. 压缩文件如何设置密码?/ 如何破解压缩文件密码?

热门文章

  1. 遏制企业数据泄露之殇,大咖切磋云安全的攻防之道
  2. 程序员感叹一年只能存下15万太少了……网友:潸然泪下
  3. “机器学习还是很难用!”
  4. 实战:手把手教你实现用语音智能控制电脑 | 附完整代码
  5. 卷积神经网络中十大拍案叫绝的操作
  6. 阿里最新论文解读:考虑时空域影响的点击率预估模型DSTN
  7. 那位13岁就当上老板的开发者是如何炼成的?
  8. 美团确定进军自动驾驶,滴滴如何应对?
  9. 9月热文精选,为你的假期加点料
  10. 进程、线程、进程池、进程三态、同步、异步、并发、并行、串行