当前位置: 首页 > news >正文

第12次09:展示收货地址和新增地址

第1步:定义地址模型,考虑到地址模型中的创建时间与更新时间在后续其它模型中也会用到,所以先定义一个包含创建时间和更新时间的基础模型BaseModel.py,其它模型通过继承它来获取创建时间和更新时间属性。

在utils包中创建models.py,并定义BaseModel模型

from django.db import modelsclass BaseModel(models.Model):"""本项目中地址、商品后续涉及到创建时间和更新时间的模型的基类"""create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)update_time = models.DateTimeField(verbose_name='更新时间', auto_now=True)class Meta:abstract = True  # 不能实例化表

第2步:在users应用的下的models.py创建地址模型,此模型继承BaseModel,注意Address模型在放在User模型的下面,否则无法正确使用Use的模型作为外键

from xiaoyu_mall.utils.models import BaseModelclass Address(BaseModel):"""收货地址"""user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name='用户')title = models.CharField(verbose_name='地址名称', max_length=20)receiver = models.CharField(verbose_name='收货人', max_length=20)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(verbose_name='地址', max_length=50)mobile = models.CharField(verbose_name='手机号', max_length=11)tel = models.CharField(verbose_name='固定电话', max_length=20, null=True, blank=True, default='')email = models.CharField(verbose_name='电子邮箱', max_length=30, null=True, blank=True, default='')is_deleted = models.BooleanField(default=False, verbose_name='逻辑删除')class Meta:db_table = 'tb_address'verbose_name = '用户地址'verbose_name_plural = verbose_nameordering = ['-update_time']  # 按更新时间倒序排列

第3步:在User模型中添加默认收货地址的字段default_address

class User(AbstractUser):...# 新增字段default_address = models.ForeignKey('Address', on_delete=models.SET_NULL, null=True, blank=True,related_name='users', verbose_name='默认地址')

第4步:生成并执行迁移文件

python .\manage.py makemigrations

python .\manage.py makemigrations
python .\manage.py migrate

第5步:在users应用下定义展示地址的视图

class AddressView(LoginRequiredMixin, View):"""展示地址"""def get(self, request):"""提供收货地址界面"""login_user = request.user  # 获取当前登录用户对象addresses = Address.objects.filter(user=login_user, is_deleted=False)address_list = []  # 将用户地址模型列表转字典列表for address in addresses:address_dict = {"id": address.id, "title": address.title,"receiver": address.receiver, "city": address.city.name,"province": address.province.name, "place": address.place,"district": address.district.name, "tel": address.tel,"mobile": address.mobile, "email": address.email}address_list.append(address_dict)context = {'default_address_id': login_user.default_address_id or '0','addresses': address_list,'address_num': constants.USER_ADDRESS_COUNTS_LIMIT}return render(request, 'user_center_site.html', context)

第6步:配置路由,users/urls.py

path('addresses/', views.AddressView.as_view(), name='address'),

第7步:导入模板user_center_site.html

{#<!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="{{ static('css/reset.css') }}"><link rel="stylesheet" type="text/css" href="{{ static('css/main.css') }}"><script type="text/javascript" src="{{ static('js/vue-2.5.16.js') }}"></script><script type="text/javascript" src="{{ static('js/axios-0.18.0.min.js') }}"></script>
</head>
<body><div id="app"><div class="header_con"><div class="header" v-cloak><div class="welcome fl">欢迎来到小鱼商城!</div><div class="fr"><div v-if="username" class="login_btn fl">欢迎您:<em>[[ username ]]</em><span>|</span><a href="{{ url('users:logout') }}">退出</a></div><div v-else class="login_btn fl"><a href="{{ url('users:login') }}">登录</a><span>|</span><a href="{{ url('users:register') }}">注册</a></div><div class="user_link fl"><span>|</span><a href="{{ url('users:info') }}">用户中心</a><span>|</span>
{#					<a href="{{ url('carts:info') }}">我的购物车</a>#}<span>|</span>
{#					<a href="{{ url('users:myorderinfo',args=(1,)) }}">我的订单</a>#}</div></div></div></div><div class="search_bar clearfix"><a href="{{ url('contents:index') }}" class="logo fl"><img src="{{ static('images/logo.png') }}"></a><div class="search_wrap fl"><form method="get" action="/search/" class="search_con"><input type="text" class="input_text fl" name="q" placeholder="搜索商品"><input type="submit" class="input_btn fr" name="" value="搜索"></form><ul class="search_suggest fl"><li><a href="#">索尼微单</a></li><li><a href="#">优惠15元</a></li><li><a href="#">美妆个护</a></li><li><a href="#">买2免1</a></li></ul></div></div><div class="main_con clearfix"><div class="left_menu_con clearfix"><h3>用户中心</h3><ul><li><a href="{{ url('users:info') }}">· 个人信息</a></li><li><a href="{{ url('users:address') }}" class="active">· 收货地址</a></li>
{#                <li><a href="{{ url('users:myorderinfo',args=(1,)) }}">· 全部订单</a></li>#}
{#				<li><a href="{{ url('users:resetpwd') }}">· 修改密码</a></li>#}</ul></div><div class="right_content clearfix" v-cloak><div class="site_top_con"><a @click="show_add_site">新增收货地址</a><span>你已创建了<b>[[ addresses.length ]]</b>个收货地址,最多可创建<b>{{ address_num }}</b></span></div><div class="site_con" v-for="(address, index) in addresses"><div class="site_title"><div v-if="edit_title_index===index"><input v-model="new_title" type="text" name=""><input @click="save_title(index)" type="button" name="" value="保 存"><input @click="cancel_title(index)" type="reset" name="" value="取 消"></div><div><h3>[[ address.title ]]</h3><a @click="show_edit_title(index)" class="edit_title"></a></div><em v-if="address.id==default_address_id">默认地址</em><span @click="delete_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_site(index)" class="edit_icon">编辑</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 © 2024 北京小鱼商业股份有限公司 All Rights Reserved</p><p>电话:010-****888    京ICP备*******8号</p></div><div class="pop_con" v-show="is_show_edit" v-cloak><div class="site_con site_pop"><div class="site_pop_title"><h3>新增收货地址</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" class="receiver"><span v-show="error_receiver" class="receiver_error">请填写收件人</span></div><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><div class="form_group"><label>*详细地址:</label><input v-model="form_address.place" @blur="check_place" type="text" class="place"><span v-show="error_place" class="place_error">请填写地址信息</span></div><div class="form_group"><label>*手机:</label><input v-model="form_address.mobile" @blur="check_mobile" type="text" class="mobile"><span v-show="error_mobile" class="mobile_error">手机信息有误</span></div><div class="form_group"><label>固定电话:</label><input v-model="form_address.tel" @blur="check_tel" type="text" class="tel"><span v-show="error_tel" class="tel_error">固定电话有误</span></div><div class="form_group"><label>邮箱:</label><input v-model="form_address.email" @blur="check_email" type="text" class="email"><span v-show="error_email" class="email_error">邮箱信息有误</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">let addresses = {{ addresses | safe }};let default_address_id = "{{ default_address_id }}";</script><script type="text/javascript" src="{{ static('js/common.js') }}"></script><script type="text/javascript" src="{{ static('js/user_center_site.js') }}"></script>
</body>
</html>

第8步:在users应用下定义AddressCreateView,用于实现新增地址的功能。

class AddressCreateView(LoginRequiredJSONMixin, View):"""展示地址"""def get(self, request):"""提供收货地址界面"""login_user = request.user  # 获取当前登录用户对象addresses = Address.objects.filter(user=login_user,is_deleted=False)address_list = []  # 将用户地址模型列表转字典列表for address in addresses:address_dict = {"id": address.id, "title": address.title,"receiver": address.receiver, "city": address.city.name,"province": address.province.name, "place": address.place,"district": address.district.name, "tel": address.tel,"mobile": address.mobile, "email": address.email}address_list.append(address_dict)context = {'default_address_id': login_user.default_address_id or '0','addresses': address_list}return render(request, 'user_center_site.html', context)def post(self, request):"""新增收货地址"""# 校验用户收货地址数量count = request.user.addresses.filter(is_deleted__exact=False).count()if count >= constants.USER_ADDRESS_COUNTS_LIMIT:return 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 HttpResponseForbidden('缺少必传参数')if not re.match(r'^1[3-9]\d{9}$', mobile):return HttpResponseForbidden('参数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 HttpResponseForbidden('参数tel有误')if email:if not re.match(r'^[a-z0-9][\w\\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):return HttpResponseForbidden('参数email有误')# 保存收货地址try:address = Address.objects.create(user=request.user, title=receiver, receiver=receiver,province_id=province_id, place=place, tel=tel,city_id=city_id, district_id=district_id,mobile=mobile, email=email)# 设置默认收货地址if not request.user.default_address:request.user.default_address = addressrequest.user.save()except Exception as e:logger.error(e)return 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': RETCODE.OK,'errmsg': '新增地址成功', 'address': address_dict})

第9步:在users应用下配置路由

path('addresses/create/', views.AddressCreateView.as_view()),
http://www.xdnf.cn/news/774019.html

相关文章:

  • 基于vue3-elemenyui的动态列案例
  • 【C语言入门级教学】assert断⾔和指针的使用
  • linux学习第18天(fork函数)
  • 代码随想录算法训练营第六天| 242.有效的字母异位词 、 349. 两个数组的交集 、 202. 快乐数 、1. 两数之和
  • Cesium使用primitive添加点线面(贴地)
  • 【文献阅读】Learning Transferable Visual Models From Natural Language Supervision
  • 【网络信息安全体系结构】知识点总结
  • 每日算法-250602
  • 复变函数 $w = z^2$ 的映射图像演示
  • 电商 API 开发实战:唯品会商品详情页实时数据接口接入与调试
  • 【Python 进阶2】抽象方法和实例调用方法
  • 激光雷达的强度像和距离像误差与噪声分析(2)2025.6.2
  • ps反相调整
  • 西红柿番茄成熟度目标检测数据集介绍
  • RSCUcaller
  • C语言进阶知识:深入探索编程的奥秘
  • 免费的硬盘工具
  • c++ 赋值函数和拷贝构造函数的调用时机
  • 【Pytorch学习笔记】模型模块06——hook函数
  • ps色彩平衡调整
  • java反序列化: Transformer链技术剖析
  • DAX权威指南6:DAX 高级概念(扩展表)、DAX 计算常见优化
  • 集成测试的流程总结
  • 【Kubernetes-1.30】--containerd部署
  • 工作日记之权限校验-token的实战案例
  • 基于Android的医院陪诊预约系统
  • 九(2).参数类型为引用结构体类型
  • css呼吸灯
  • 详细解析2MHz和3MHz压电陶瓷片的区别
  • 数据库-数据查询