19-Django实战项目[order]-生成订单

发布于:2025-08-20 ⋅ 阅读:(28) ⋅ 点赞:(0)

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
)

这一块代码可能存在同一时间很多人进行操作-提交购物车


网站公告

今日签到

点亮在社区的每一天
去签到