1.模型类
from django.db import models
from goods.models import SKU
from user.models import UserProfile
from utils.basemodel import BaseModel
STATUS_CHOICES = (
(1, "待付款"),
(2, "待发货"),
(3, "待收货"),
(4, "订单完成")
)
# Create your models here.
class OrderInfo(BaseModel):
"""
订单表
订单编号、总金额、支付方式、订单状态、运费
"""
# 外键-用户表:订单表=1:n
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
order_id = models.CharField("订单编号", max_length=64, primary_key=True)
# 总金额 商品总数 支付方式
total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="总金额")
total_count = models.IntegerField(verbose_name="商品总数")
pay_method = models.SmallIntegerField(default=1, verbose_name="支付方式")
# 运费
freight = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="运费")
# 订单状态
status = models.SmallIntegerField(verbose_name="订单状态", choices=STATUS_CHOICES)
# 冗余地址相关字段
receiver = models.CharField(verbose_name="收件人", max_length=10)
address = models.CharField(verbose_name="收件地址", max_length=100)
receiver_mobile = models.CharField(verbose_name="手机号", max_length=11)
tag = models.CharField(verbose_name="标签", max_length=11)
class Meta:
db_table = "orders_order_info"
class OrderGoods(BaseModel):
"""
订单商品表
名称、数量、价格、订单编号
"""
# 外键-订单表:订单商品表=1:n
order_info = models.ForeignKey(OrderInfo, on_delete=models.CASCADE)
# 外键-商品表:订单商品表=1:n
sku = models.ForeignKey(SKU, on_delete=models.CASCADE)
# 数量 单价
count = models.IntegerField(default=1, verbose_name="数量")
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="单价")
class Meta:
db_table = "orders_order_goods"
数据迁移
python manage.py makemigrations
python manage.py migrate
2.视图函数
class OrderInfoView(BaseView):
def post(self, request, username):
"""
生成订单视图逻辑
1.获取请求题数据[address_id]
2.订单表中插入数据[OrderInfo]
3.更新库存和销量[sku]
4.订单商品中插入数据[OrderGoods]
5.返回响应
"""
data = json.loads(request.body)
address_id = data.get("address_id")
user = request.user
order_id = time.strftime("%Y%m%d%H%M%S") + str(user.id)
total_amount = 0
total_count = 0
# 1.开启事物
with transaction.atomic():
# 2.创建存储点
sid = transaction.savepoint()
# 3.执行事物
try:
address = Address.objects.get(id=address_id, user_profile=user, is_active=True)
except Exception as e:
return JsonResponse({"code":50102, "error": "收获地址无效"})
# 订单表中插入数据
order = OrderInfo.objects.create(
user_profile=user,
order_id=order_id,
total_amount=total_amount,
total_count=total_count,
pay_method=1,
freight=1,
status=1,
receiver=address.receiver,
address=address.address,
receiver_mobile=address.receiver_mobile,
tag=address.tag
)
# 更新库存和销量
cache_key = f"carts_{user.id}"
carts_data = caches["carts"].get(cache_key)
if not carts_data:
carts_data = {}
skus_list = []
skus = SKU.objects.filter(id__in=carts_data.keys()) # 默认全是选中状态,全部结算
for sku in skus:
count = carts_data[str(sku.id)]
if count > sku.stock:
# 回滚
transaction.savepoint_rollback(sid)
return JsonResponse({"code": 10505, "error": "库存不足"})
SKU.objects.filter(id=sku.id).update(
stock=sku.stock - count,
sales=sku.sales + count
)
# 插入订单商品表
OrderGoods.objects.create(
order_info_id=order_id,
sku_id=sku.id,
price=sku.price,
count=count
)
total_amount += sku.price * count
total_count += count
# 更新订单表的总价和数量
order.total_amount = total_amount
order.total_count = total_count
order.save()
# 4.提交事物
transaction.savepoint_commit(sid)
# 清除购物车中已转化未有效订单商品数据
cache_key = f"carts_{user.id}"
carts_data = caches["carts"].get(cache_key)
if not carts_data:
carts_data = {}
carts_dict = {}
for k, v in carts_data.items():
carts_dict[k] = v # 未判断取消勾选
# 更新到redis
caches["carts"].set(cache_key, carts_dict)
carts_count = len(carts_dict)
# 组织数据返回
data = {
'saller': '达达商城',
'total_amount': total_amount,
'order_id': order_id,
'pay_url': '',
'carts_count': carts_count
}
result = {
"code": 200,
"data": data
}
return JsonResponse(result)
3.解决并发问题
SKU.objects.filter(id=sku.id).update(
stock=sku.stock - count,
sales=sku.sales + count
)
这一块代码可能存在同一时间很多人进行操作-提交购物车