开源web框架django知识总结(二十)
阿尔法商城(订单)
订单
提示:
- 订单入口 在《购物车》页面的《去结算》。
- 《去结算》后进入到《结算订单》页面,展示出要结算的商品信息。
结算订单
新建apps->orders,同步数据,注册app,新建子路由urls.py,添加项目主路由
1. 结算订单逻辑分析
结算订单是从Redis购物车中查询出被勾选的商品信息进行结算并展示。
2. 结算订单接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /orders/settlement/ |
**2.请求参数:**无
3.响应结果:HTML place_order.html
4.后端接口定义
class OrderSettlementView(LoginRequiredMixin, View):
"""结算订单"""
def get(self, request):
"""提供订单结算页面"""
pass
- 结算订单后端逻辑实现
from django.views import View
from django_redis import get_redis_connection
from goods.models import SKU
from users.models import Address
from django.http import JsonResponse
# Paginator:分页器
from decimal import Decimal # 数据精确处理
from aerf_mall.utils.views import login_required
from django.utils.decorators import method_decorator
class OrderSettlementView(View):
@method_decorator(login_required)
def get(self, request):
user = request.user
# 1、读取用户购物商品(必须是选中的!)
conn = get_redis_connection('carts')
# {b'1': b'4'} hgetall,返回所有的字段和值。
cart_redis = conn.hgetall('carts_%s'%user.id)
# [b'1'] smembers返回所有集合
cart_selected = conn.smembers('selected_%s'%user.id)
# 构造商品返回数据
sku_list = []
for k,v in cart_redis.items():
# k:b'1'; v:b'4'
if k in cart_selected:
sku = SKU.objects.get(pk=k)
sku_list.append({
'id': sku.id,
'name': sku.name,
'default_image_url': sku.default_image_url.url,
'price': sku.price,
'count': int(v)
})
# 2、读取用户的收货地址数据
addresss_list = []
addresses = Address.objects.filter(user=user)
for address in addresses:
if not address.is_deleted:
addresss_list.append({
"id": address.id,
"province": address.province.name,
"city": address.city.name,
"district": address.district.name,
"place": address.place,
"mobile": address.mobile,
"receiver": address.receiver,
})
# 3、构建响应数据
# freight = 10.0
# 结论:使用Decimal类型来保存十进制数,目的是为了保证计算的精确度,Decimal(10,5)10位数,其中小数占5位
freight = Decimal('10.5')
return JsonResponse({
'code': 0,
'errmsg': 'ok',
'context': {
'addresses': addresss_list,
'skus': sku_list,
'freight': freight
}
})
=======================================
提交订单
提示:
- 确认了要结算的商品信息后,就可以去提交订单了。
创建订单数据库表
生成的订单数据要做持久化处理,而且需要在《我的订单》页面展示出来。
1. 订单数据库表分析
注意:
- 订单号不再采用数据库自增主键,而是由后端生成。
- 一个订单中可以有多个商品信息,订单基本信息和订单商品信息是一对多的关系。
2. 订单模型类、迁移、建表
orders.models.py
from django.db import models
from aerf_mall.utils.BaseModel import BaseModel
from users.models import User,Address
from goods.models import SKU
# Create your models here.
#
class OrderInfo(BaseModel):
"""订单信息"""
PAY_METHODS_ENUM = {
"CASH": 1,
"ALIPAY": 2
}
PAY_METHOD_CHOICES = (
(1, "货到付款"),
(2, "支付宝"),
)
ORDER_STATUS_ENUM = {
"UNPAID": 1,
"UNSEND": 2,
"UNRECEIVED": 3,
"UNCOMMENT": 4,
"FINISHED": 5
}
ORDER_STATUS_CHOICES = (
(1, "待支付"),
(2, "待发货"),
(3, "待收货"),
(4, "待评价"),
(5, "已完成"),
(6, "已取消"),
)
# primary_key=True表明当前字段作为主键——自定义主键
order_id = models.CharField(max_length=64, primary_key=True, verbose_name="订单号")
user = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name="下单用户")
address = models.ForeignKey(Address, on_delete=models.PROTECT, verbose_name="收货地址")
total_count = models.IntegerField(default=1, verbose_name="商品总数")
# DecimalField类型字段:十进制的数(高精度)
total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="商品总金额")
freight = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="运费")
pay_method = models.SmallIntegerField(choices=PAY_METHOD_CHOICES, default=1, verbose_name="支付方式")
status = models.SmallIntegerField(choices=ORDER_STATUS_CHOICES, default=1, verbose_name="订单状态")
class Meta:
db_table = "tb_order_info"
verbose_name = '订单基本信息'
verbose_name_plural = verbose_name
def __str__(self):
return self.order_id
#
class OrderGoods(BaseModel):
"""订单商品"""
SCORE_CHOICES = (
(0, '0分'),
(1, '20分'),
(2, '40分'),
(3, '60分'),
(4, '80分'),
(5, '100分'),
)
order = models.ForeignKey(OrderInfo, related_name='skus', on_delete=models.CASCADE, verbose_name="订单")
sku = models.ForeignKey(SKU, on_delete=models.PROTECT, verbose_name="订单商品")
count = models.IntegerField(default=1, verbose_name="数量")
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="单价")
comment = models.TextField(default="", verbose_name="评价信息")
score