首先完成省市区三级联动

新建areas应用

python ../../manage.py startapp 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

模型类代码说明:

parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subs', null=True, blank=True, verbose_name='上级行政区划')

self:自关联

on_delete=models.SET_NULL 在删除父级的时候,自己的parent_id设置为空,这里就不在级联删除了,避免误删除,采集数据不容易。

related_name=’subs’ 这个跟flask的backref很类似。 意思为如果想找自己的子级,就可以通过area.subs找到自己下级所有的area区域。

之后配置应用

然后迁移数据库

python manage.py makemigrations
python manage.py migrate

导入测试数据脚本

增加执行权限

返回省市区数据的后端视图集实现

定义视图最终如下

采用视图集

序列化器

定义路由

DRF缓存的实现

省市区的数据是经常被用户查询使用的,而且数据基本不变化,所以我们可以将省市区数据进行缓存处理,减少数据库的查询次数。

在Django REST framework中使用缓存,可以通过drf-extensions扩展来实现。

关于扩展使用缓存的文档,可参考链接http://chibisov.github.io/drf-extensions/docs/#caching

安装

pip install drf-extensions

使用方法

配置文件

禁止分页

前端代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>美多商城-用户中心</title>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="js/host.js"></script>
<script type="text/javascript" src="js/vue-2.5.16.js"></script>
<script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
<script>
var user_id = sessionStorage.user_id || localStorage.user_id;
var token = sessionStorage.token || localStorage.token;
if (!(user_id && token)) {
location.href = '/login.html?next=/user_center_site.html';
}
</script>
</head>
<body>
<div id="app" v-cloak>
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到美多商城!</div>
<div class="fr">
<div class="login_btn fl">
欢迎您:<em>{{ username }}</em>
<span>|</span>
<a @click="logout">退出</a>
</div>
<div class="user_link fl">
<span>|</span>
<a href="user_center_info.html">用户中心</a>
<span>|</span>
<a href="cart.html">我的购物车</a>
<span>|</span>
<a href="user_center_order.html">我的订单</a>
</div>
</div>
</div>
</div> <div class="search_bar clearfix">
<a href="index.html" class="logo fl"><img src="data:images/logo.png"></a>
<div class="sub_page_name fl">|&nbsp;&nbsp;&nbsp;&nbsp;用户中心</div>
<form method="get" action="/search.html" class="search_con fr mt40">
<input type="text" class="input_text fl" name="q" placeholder="搜索商品">
<input type="submit" class="input_btn fr" name="" value="搜索">
</form>
</div> <div class="main_con clearfix">
<div class="left_menu_con clearfix">
<h3>用户中心</h3>
<ul>
<li><a href="user_center_info.html">· 个人信息</a></li>
<li><a href="user_center_order.html">· 全部订单</a></li>
<li><a href="user_center_site.html" class="active">· 收货地址</a></li>
<li><a href="user_center_pass.html">· 修改密码</a></li>
</ul>
</div>
<div class="right_content clearfix">
<div class="site_top_con">
<a @click="show_add">新增收货地址</a>
<span>您已创建了<b>{{addresses.length}}</b>个收货地址,最多可创建<b>{{ limit }}</b>个</span>
</div>
<div class="site_con" v-for="(address, index) in addresses">
<div class="site_title">
<div v-if="is_set_title[index]">
<input v-model="input_title" type="text" name="">
<input @click="save_title(index)" type="button" name="" value="保 存">
<input @click="cancel_title(index)" type="reset" name="" value="取 消">
</div>
<div v-else>
<h3>{{ address.title }}</h3>
<a @click="show_edit_title(index)"></a>
</div>
<em v-if="address.id==default_address_id">默认地址</em>
<span @click="del_address(index)">×</span>
</div>
<ul class="site_list">
<li><span>收货人:</span><b>{{ address.receiver }}</b></li>
<li><span>所在地区:</span><b>{{ address.province }} {{address.city}} {{ address.district }}</b></li>
<li><span>地址:</span><b>{{ address.place }}</b></li>
<li><span>手机:</span><b>{{ address.mobile }}</b></li>
<li><span>固定电话:</span><b>{{ address.tel }}</b></li>
<li><span>电子邮箱:</span><b>{{ address.email }}</b></li>
</ul>
<div class="down_btn">
<a v-if="address.id!=default_address_id" @click="set_default(index)">设为默认</a>
<a @click="show_edit(index)">编辑</a>
</div>
</div>
</div>
</div>
<div class="footer">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京美多商业股份有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div> <div class="pop_con" v-show="is_show_edit">
<div class="site_con site_pop">
<div class="site_pop_title">
<h3 v-if="editing_address_index">编辑收货地址</h3>
<h3 v-else>新增收货地址</h3>
<a @click="is_show_edit=false">×</a>
</div>
<form>
<div class="form_group">
<label>*收货人:</label>
<input v-model="form_address.receiver" @blur="check_receiver" type="text" name="">
<span v-show="error_receiver" class="error_tip">请填写收件人</span>
</div>
<div class="form_group">
<label>*所在地区:</label>
<select v-model="form_address.province_id">
<option v-for="province in provinces" v-bind:value="province.id">{{ province.name }}</option>
</select>
<select v-model="form_address.city_id">
<option v-for="city in cities" v-bind:value="city.id">{{ city.name }}</option>
</select>
<select v-model="form_address.district_id">
<option v-for="district in districts" v-bind:value="district.id">{{ district.name }}</option>
</select>
</div>
<div class="form_group">
<label>*详细地址:</label>
<input v-model="form_address.place" @blur="check_place" type="text" name="">
<span v-show="error_place" class="error_tip">请填写地址信息</span>
</div>
<div class="form_group">
<label>*手机:</label>
<input v-model="form_address.mobile" @blur="check_mobile" type="text" name="">
<span v-show="error_mobile" class="error_tip">手机信息有误</span>
</div>
<div class="form_group">
<label>固定电话:</label>
<input v-model="form_address.tel" type="text" name="">
</div>
<div class="form_group">
<label>邮箱:</label>
<input v-model="form_address.email" @blur="check_email" type="text" name="">
<span v-show="error_email" class="error_tip">邮箱信息有误</span>
</div>
<input @click="save_address" type="button" name="" value="保 存" class="info_submit">
<input @click="is_show_edit=false" type="reset" name="" value="取 消" class="info_submit info_reset">
</form>
</div>
<div class="mask"></div>
</div>
</div>
<script type="text/javascript" src="js/user_center_site.js"></script>
</body>
</html>

js代码

var vm = new Vue({
el: '#app',
data: {
host: host,
user_id: sessionStorage.user_id || localStorage.user_id,
token: sessionStorage.token || localStorage.token,
username: sessionStorage.username || localStorage.username,
is_show_edit: false,
provinces: [],
cities: [],
districts: [],
addresses: [],
limit: '',
default_address_id: '',
form_address: {
receiver: '',
province_id: '',
city_id: '',
district_id: '',
place: '',
mobile: '',
tel: '',
email: '',
},
error_receiver: false,
error_place: false,
error_mobile: false,
error_email: false,
editing_address_index: '', // 正在编辑的地址在addresses中的下标,''表示新增地址
is_set_title: [],
input_title: ''
},
mounted: function(){
axios.get(this.host + '/areas/', {
responseType: 'json'
})
.then(response => {
this.provinces = response.data;
})
.catch(error => {
alert(error.response.data);
});
},
watch: {
'form_address.province_id': function(){
if (this.form_address.province_id) {
axios.get(this.host + '/areas/'+ this.form_address.province_id + '/', {
responseType: 'json'
})
.then(response => {
this.cities = response.data.subs;
})
.catch(error => {
console.log(error.response.data);
this.cities = [];
});
}
},
'form_address.city_id': function(){
if (this.form_address.city_id){
axios.get(this.host + '/areas/'+ this.form_address.city_id + '/', {
responseType: 'json'
})
.then(response => {
this.districts = response.data.subs;
})
.catch(error => {
console.log(error.response.data);
this.districts = [];
});
}
}
},
methods: {
// 退出
logout: function(){
sessionStorage.clear();
localStorage.clear();
location.href = '/login.html';
},
clear_all_errors: function(){
this.error_receiver = false;
this.error_mobile = false;
this.error_place = false;
this.error_email = false;
},
// 展示新增地址界面
show_add: function(){
this.clear_all_errors();
this.editing_address_index = '';
this.form_address.receiver = '';
this.form_address.province_id = '';
this.form_address.city_id = '';
this.form_address.district_id = '';
this.form_address.place = '';
this.form_address.mobile = '';
this.form_address.tel = '';
this.form_address.email = '';
this.is_show_edit = true;
},
// 展示编辑地址界面
show_edit: function(index){
this.clear_all_errors();
this.editing_address_index = index;
// 只获取数据,防止修改form_address影响到addresses数据
this.form_address = JSON.parse(JSON.stringify(this.addresses[index]));
this.is_show_edit = true;
},
check_receiver: function(){
if (!this.form_address.receiver) {
this.error_receiver = true;
} else {
this.error_receiver = false;
}
},
check_place: function(){
if (!this.form_address.place) {
this.error_place = true;
} else {
this.error_place = false;
}
},
check_mobile: function(){
var re = /^1[345789]\d{9}$/;
if(re.test(this.form_address.mobile)) {
this.error_mobile = false;
} else {
this.error_mobile = true;
}
},
check_email: function(){
if (this.form_address.email) {
var re = /^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$/;
if(re.test(this.form_address.email)) {
this.error_email = false;
} else {
this.error_email = true;
}
}
},
// 保存地址
save_address: function(){ },
// 删除地址
del_address: function(index){ },
// 设置默认地址
set_default: function(index){ },
// 展示编辑标题
show_edit_title: function(index){ } ,
// 保存地址标题
save_title: function(index){ },
// 取消保存地址
cancel_title: function(index){ }
}
})

测试

Django商城项目笔记No.16用户部分-用户中心收货地址的更多相关文章

  1. Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid

    Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...

  2. Django商城项目笔记No.10用户部分-登录接口

    Django商城项目笔记No.10用户部分-登录接口 添加url路由 接下来第二步,增加返回内容: 增加结果如下: 配置:上边的方法定义了返回的内容都有哪些,那这个方法jwt还不知道,需要配置: 修改 ...

  3. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  4. Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址

    Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...

  5. Django商城项目笔记No.9用户部分-注册接口签发JWTtoken

    Django商城项目笔记No.9用户部分-注册接口签发JWTtoken 我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT. 关于签 ...

  6. Django商城项目笔记No.8用户部分-注册接口实现

    Django商城项目笔记No.8用户部分-注册接口实现 users的view.py中增加如下代码 class RegisterUserView(CreateAPIView): "" ...

  7. Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在

    Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在 判断用户名是否存在 后端视图代码实现,在users/view.py里编写如下代码 class UsernameCount ...

  8. Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步

    Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...

  9. Django商城项目笔记No.4用户部分-注册接口-图片验证码

    Django商城项目笔记No.4用户部分-注册接口-图片验证码 1.首先分析注册业务接口 1.1.分析可得,至少这么几个接口 图片验证码 短信验证码 用户名是否存在 手机号是否存在 整体注册接口 图片 ...

随机推荐

  1. 基于GoogLeNet的不同花分类微调训练案例

    import tensorflow as tf from tensorflow.contrib.slim import nets slim = tf.contrib.slim import numpy ...

  2. Infopath 2010 接收SQL Server数据

    Infopath2010为我们提供了多种接收数据的方式,今天我来讲讲里面其中的一种直接读取SQL Server数据库表数据方法(高阶者的下面可以略省,只针对入门者). 1.选择数据库(SQL) 2.选 ...

  3. t3用户-角色-权限hibernate经典配置

    用户-角色-权限hibernate经典配置. 既然有人问起,我就写下说明吧.在文章中间的配置文件那里.权当回忆一下,也帮助更多人.这是以前学校时写的,没有注释.都是贴的代码笔记.看到的莫要见怪.欢迎学 ...

  4. 【4】 .net MVC使用Session验证用户登录

    用最简单的Session方式记录用户登录状态 1.添加DefaultController控制器,重写OnActionExecuting方法,每次访问控制器前触发 public class Defaul ...

  5. vb.net連接ACCESS数据库

    '導入命名空間Imports System.Data.OleDb '定義變量 Dim Sql As String 'OleDb連線 Dim SqlAC As OleDbConnection Dim C ...

  6. 算法时间复杂度、空间复杂度(大O表示法)

    什么是算法? 计算机是人的大脑的延伸,它的存在主要是为了帮助我们解决问题. 而算法在计算机领域中就是为了解决问题而指定的一系列简单的指令集合.不同的算法需要不同的资源,例如:执行时间或消耗内存. 如果 ...

  7. elasticsearch6.7 04.API规范

    API Conventions elasticsearch的REST的API是使用HTTP的JSON格式暴露的. 除非另有说明,本章中列出的约定可以在整个REST API中应用. 多索引 索引名称支持 ...

  8. python生成器简单了解

    1.什么是生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素, ...

  9. 微信公众号获取acess_token并存储(php)

    <?php define("appid", "你的appid"); define("appsecret", "你的appse ...

  10. Tornado入门

    一.概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像是一个py文件,不过为了能有效利用非阻塞式服务器环境,这 ...