![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/505b43b279cdeba1e998476a747b29d6.jpeg)
(根据居然老师直播课内容整理)
一、页面功能简介
- 在“用户中心”的任一界面,点击左边“收货地址”后,显示下面界面
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e403a8d62a29ab8c9f164fea16fc5175.png)
- 此界面包括以下4个功能:
- 新增收货地址
- 删除当前收货地址
- 编辑(当前记录收货地址)
- 设为默认
- 以4个功能中,“新增收货地址”和“编辑” 需要弹出表单,进行编辑
二、显示收货地址信息页面
1、实现分析
- 在“用户中心”的任一界面,点击左边“收货地址”
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/dd79863f3781814c786b59c6211e03ab.png)
- 前端向后端发起 user/addresses路由发起 get请求
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/42681a75ed8981e7540b78bc1178b670.png)
- 后端接收请求,判断用户是否登录
- 如果已登录,返回页面
- 如果未登录,跳转到登录页面
2、后端veiw实现
# /apps/users/views.py
class AddressView(LoginRequiredMixin, View):
"""用户收货地址"""
def get(self, request):
"""提供收货地址界面"""
return render(request, 'user_center_site.html')
3、路由注册
# /apps/users/urls.py
# 展示用户地址
path('addresses/', views.AddressView.as_view(),name="addresses"),
三、收货地址数据模型
- 用户地址模型类定在users应用的models.py中
1、收货地址模型类
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、收货地址模型类说明
- 收货地址模型类中省、市、县的外键指向areas/models里面的Area。
- 指明外键时,可以使用应用名.模型类名来定义,也可以使用模型类
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/87984bd39de50d078b6cd312692d7adc.png)
- ordering表示在进行收货地址模型查询时,默认使用的排序方式。
- ordering = [’-update_time’] : 根据更新的时间倒叙。
3、补充用户模型默认地址字段
- 默认地址字段应保存到user表中,与用户绑定,需要修改User模型
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/32e4206bd6ff4adc772c8db239c8edef.png)
4、数据库迁移
python manage.py makemigrations
python manage.py migrate
四、新增用户收货地址
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f48d7d9125410636814c257392e7005b.png)
1、接口设计和定义
1.1 请求方式:
选项 |
方案 |
请求方法 |
POST |
请求地址 |
/users/addresses/create/ |
1.2 请求参数 :
参数名 |
类型 |
是否必传 |
说明 |
eceiver |
string |
是 |
收货人 |
province_id |
string |
是 |
省份ID |
city_id |
string |
是 |
城市ID |
district_id |
string |
是 |
区县ID |
place |
string |
是 |
收货地址 |
mobile |
string |
是 |
手机号 |
tel |
string |
否 |
固定电话 |
email |
string |
否 |
邮箱 |
1.3 响应结果 : json
响应结果 |
响应内容 |
code |
状态码 |
errmsg |
错误信息 |
id |
地址ID |
receiver |
收货人 |
province |
省份名称 |
city |
城市名称 |
district |
区县名称 |
place |
收货地址 |
mobile |
手机号 |
tel |
固定电话 |
email |
邮箱 |
2、后端view实现
- 判断用户是否登录
- 接收参数
- 校验参数
- 必传参数量否传递
- 手机号校验
- 如果填有固定电话,固定电话需要校验
- 如果填了邮箱,邮箱需校验
- 保存到数据库
- 根据前端需要,返回详细数据
class AddressCreateView(LoginRequiredJSONMixin, View):
"""新增地址"""
def post(self,request):
# 接收参数
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.HttpResponseForbidden('缺少必传参数')
if not re.match(r"^1[3-9]\d{9}$", mobile):
return http.HttpResponseForbidden('参数mobile有误')
if tel and not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
return http.HttpResponseForbidden('参数固定电话有误')
if not email and not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
return http.HttpResponseForbidden('参数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,
)
except Exception as e:
logging.error(e)
return http.HttpResponseServerError({"code": RETCODE.DBERR, "errmsg": "新增收获地址失败"})
# 响应
address_dict = {
"id": address.id,
"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 http.JsonResponse({"code": RETCODE.OK, "errmsg": "新增收货地址成功", "address": address_dict})
3、定义路由
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/bc3b28e2fe42497bd545a2638dea1a26.png)
4、前端实现
4.1 新增地址JS
// 新增地址
save_address(){
if (this.error_receiver || this.error_place || this.error_mobile || this.error_email || !this.form_address.province_id || !this.form_address.city_id || !this.form_address.district_id ) {
alert('信息填写有误!');
} else {
// 新增地址
let url = '/users/addresses/create/';
axios.post(url, this.form_address, {
headers: {
'X-CSRFToken':getCookie('csrftoken')