• 商品分类-商品详情-数据库脏读-不可重复读-幻读-订单生成


    商品详情的无限极分类

      --北京
    
        --朝阳区
      ---上海
    
        --松江
          --大学城
    def get_level(data):
        data_list=[]
        for item in data:
            if item['parent_id']==0:
                item['level']=0
            else:
                item['level']=1
            data_list.append(item)
        return data_list
    
    data=[
        {"cat_id":1,"name":"北京","parent_id":0},
        {"cat_id":2,"name":"上海","parent_id":0},
        {"cat_id":3,"name":"沙河","parent_id":1},
        {"cat_id":4,"name":"sb镇","parent_id":3},
        {"cat_id":5,"name":"昌平","parent_id":1},
        {"cat_id":6,"name":"青浦","parent_id":2},
    ]
    def get_tree(data):
        lists=[]
        tree={}
        for i in data:
            tree[i['cat_id']]=i
        for item in data:
            if not item['parent_id']:
                lists.append(tree[item['cat_id']])
            else:
                if "children" not in tree[item['parent_id']]:
                    tree[item['parent_id']]['children']=[]
                tree[item['parent_id']]['children'].append(tree[item['cat_id']])
        return lists
    # print(get_tree(data))
    res=[]
    def get_son(data,level=0,parent_id=0,is_clear=True):
        if is_clear:
            res.clear()
        for item in data:
            if item['parent_id']==parent_id:
                item['level']=level
                res.append(item)
                get_son(data,level=level+1,parent_id=item['cat_id'],is_clear=False)
        return res
    # son=get_son(data)
    # for i in son:
    #     print("-"*i['level']+i['name'])
    # 1北京 0
    #     2-海淀1
    #         4--sb镇2
    #     -昌平
    # 3 上海 0
    #     -青浦
    #     --徐泾镇
    #     -闵行
    res_id=[]
    def get_son_id(data,parent_id=0,is_clear=True):
        if is_clear:
            res_id.clear()
            if parent_id :
                res_id.append(parent_id)
    
        for item in data:
            if item['parent_id']==parent_id:
                res_id.append(item['cat_id'])
                get_son(data,parent_id=item['cat_id'],is_clear=False)
        return res_id
    
    import time ,random
    def get_order_id():
        st="012345679qwertyui"
        order_id=str(time.strftime("%Y%m%d%h%M%S"))+"".join(random.sample(st,5))
        return order_id

     商品分类列表

    前端部分

    后端

    class List(APIView):
        def post(self,request):
            param=request.data
            if param.get('category_id'):
                data=models.Category.objects.filter(is_show=True)
                data=Category_ser.Category_ser(instance=data,many=True,context={"request":request}).data
                all_id=func.get_son_id(data,param['category_id'])
                data=models.Product.objects.filter(disabled=True,cat_id__in=all_id).order_by("-w_order")
                data = Goods_ser.Goods_ser(instance=data, many=True, context={"request": request}).data
                return Response({"code": 200, "msg": "ok", "data": data})
            else:
                return Response({"code": 201, "msg":"缺少参数" })

    商品详情

    class Detail(APIView):
        def post(self,request):
            param=request.data
            if param.get("id"):
                data = models.Product.objects.filter(disabled=True,product_id=param.get("id")).first()
                if data:
                    data = Goods_ser.Goods_ser(instance=data, many=False, context={"request": request}).data
                    print(data)
                    return Response({"code": 200, "msg": "ok", "data": data})
                else:
                    return Response({"code": 201, "msg": "没有该商品"})

    前端

    <import src="../../wxParse/wxParse.wxml" />
    <navigation id='Navigation' show-icon="{{true}}" title="商品详情" show-title="{{true}}" class=""></navigation>
    <view class="container">
      
      <view class="swiper-container">
      
              <image src="{{goodsDetail.image_url}}" class="slide-image" lazy-load="true" />
      </view>
      <view class="goods-info">
        <view class="goods-left">
          <view class="goods-title">{{goodsDetail.name}}</view>
          <view class="goods-characteristic">{{goodsDetail.intor}}</view>    
            <view class="goods-price">Ұ {{goodsDetail.price}}</view>       
            <view class="piangjia">
              已售 {{goodsDetail.buy_count}}
            </view>     
        </view>
      </view> 
      <view class="tab-header" bindtap="tabFun">
        <view class="{{tabArr.curHdIndex=='0'? 'active' : ''}}" id="tab-hd01" data-id="0">商品介绍</view>
        <view class="{{tabArr.curHdIndex=='1'? 'active' : ''}}" id="tab-hd02" data-id="1">商品评价</view>
    
      </view>
      <view class="tab-container">
        <view class="tab-item {{tabArr.curBdIndex=='0'? 'active' : ''}}">
          <view class="goods-text">
            <template is="wxParse" data="{{wxParseData:article.nodes}}" />
          </view>
        </view>
        <view class="tab-item {{tabArr.curBdIndex=='1'? 'active' : ''}}">
          <view class="reputation-none" wx:if="{{!reputation}}">
            <image src="../../images/empty_comment.png" /> 还没有人评价
          </view>
          <view class="goods-reputa-list" wx:for="{{reputation}}" wx:key="id">
            <view class="goods-reputa-avatar">
              <image class="goods-avatar" src="{{item.user.avatarUrl}}"></image>
            </view>
            <view class="goods-reputa-mark">
              <view class="goods-reputa-user">
                {{item.user.nick}}
                <text>{{item.goods.goodReputationStr}}</text>
              </view>
              <view class="goods-mark">{{item.goods.goodReputationRemark}}</view>
              <view class="goods-mark-day">
                {{item.goods.dateReputation}}
                <text>{{item.goods.property}}</text>
              </view>
            </view>
          </view>
        </view>
      </view>
    
        <view class="footer-box">
          <view class="box-list">
            <image src="../../images/goods_service.png"></image>
            <button open-type="contact" session-from="weapp"></button>
          </view>
          <view class="box-list" bindtap="goShopCar">
            <image src="../../images/shopping_cart.png"></image>
            <view class="shop-num">{{shopNum}}</view>
          </view>
          <view class="box-list" >
         
          </view>
          <view class="box-title">
            <view class="box-shop-cart npx" bindtap="tobuy">立即购买</view>
          </view>
          <view class="box-title buy-now">
            <view class="box-now-buy npx" bindtap="toAddShopCar">加入购物车1</view>
          </view>
        </view>
     
      <view class="show-popup" hidden="{{hideShopPopup}}">
        <view class="popup-mask" bindtap="closePopupTap"></view>
        <view class="popup-contents">
          <view class="pop-goods-info">
            <view class="pop-img-box">
              <image src="{{goodsDetail.image_url}}" class="goods-thumbnail" />
            </view>
            <view class="pop-goods-des">
              <view class="pop-goods-title">{{goodsDetail.name}}</view>
              <view class="pop-goods-price" >¥ {{goodsDetail.price}}</view>
              
            </view>
            <view class="pop-goods-close" bindtap="closePopupTap"></view>
          </view>
         
          <view class="buy-num-box">
            <view class="num-label">购买数量</view>
            <view class="num-box">
              <view class="num-jian {{buyNumber == buyNumMin ? 'hui': ''}}" bindtap="numJianTap">-</view>
              <view class="num-input">
                <input type="number" value="{{buyNumber}}" disabled/>
              </view>
              <view class="num-jia {{buyNumber== buyNumMax ? 'hui': ''}}" bindtap="numJiaTap">+</view>
            </view>
          </view>
          <view class="popup-join-btn" wx:if="{{shopType =='addShopCar'}}" bindtap="addShopCar">加入购物车</view>
          <view class="popup-join-btn" wx:if="{{shopType =='tobuy'}}" bindtap="buyNow"> 立即购买</view>
         
        </view>
      </view>
    </view>
    View Code

    事务的隔离级别

      事务的四大特性分别是:原子性、一致性、隔离性、持久性

    解释

    """
    原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
    一致性: 执行事务前后,数据保持一致;
    隔离性: 并发访问数据库时,一个用户的事物不被其他事物所干扰,各并发事务之间数据库是独立的;
    持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
    """

    并发事务带来的问题

      在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。

    并发虽然是必须的,但可能会导致一下的问题。

    脏读(Dirty read):

       事务T1正在操作一条数据,此时事务T2获取该条数据纪录,如果T1异常,事务回滚,T2读取到的数据就是脏数据,这种现象称为脏读。

    不可重复读(Unrepeatableread): 

       事务T1多次读取某条记录,在读取间隔中,事务T2更新了该技术的数据,当T1再次读取该记录时,获取到的数据不一致,这种现象称为不可重复读。产生的原因主要是数据的更新。

    幻读(Phantom read): 

      幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,

    第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

    可重复读(Repeatable read):

       ①定义:就是一个事务对同一份数据读取到的相同,不在乎其他事务对数据的修改。MySQL默认的隔离级别。

       ②缺点:会产生幻读。

    序列化(Serializable)

      ①定义:事务串行化执行,隔离级别最高,牺牲了系统的并发性。

       ②缺点:可以解决并发事务的所有问题。但是效率地下,消耗数据库性能,一般不使用。

     乐观锁和悲观锁

    概念

    #悲观锁:总是假设最坏的情况,认为竞争总是存在,每次拿数据的时候都认为会被修改,因此每次都会先上锁。其他线程阻塞等待释放锁。
    
    #乐观锁:总是假设最好的情况,认为竞争总是不存在,每次拿数据的时候都认为不会被修改,因此不会先上锁,在最后更新的时候比较数据有无更新,可通过版本号或CAS实现。

    两种锁的使用场景

    悲观锁:用于写比较多的情况,避免了乐观锁不断重试从而降低性能。
    乐观锁:用于读比较多的情况,避免了不必要的加锁的开销。

    加入购物车订单分析

    前端

     订单表的设计

    # 订单表
    class Order(models.Model):
        order_id = models.CharField(max_length=50, unique=True, primary_key=True)
        status_choices = (("active", '活动订单'), ("dead", '作废订单'), ("finish", '已完成订单'))
        status = models.CharField(choices=status_choices, default="active", max_length=50)
        pay_status_choices = ((0, '未付款'), (1, '已付款'))
        pay_status = models.SmallIntegerField(choices=pay_status_choices, default=0)
        payed = models.DecimalField(max_digits=10, decimal_places=2,default=0)
        order_total = models.DecimalField(max_digits=10, decimal_places=2,default=0)
        ship_status_choices = ((0, '未发货'), (1, '已发货'))
        pay_app = models.CharField(max_length=100)
        wxuser = models.ForeignKey(to="Wxuser", to_field="id", related_name="Order", db_constraint=False,on_delete=models.CASCADE)
        quantity = models.IntegerField(default=0)
        memo = models.CharField(max_length=200, default=0)
        consignee_name = models.CharField(max_length=200, default=0)
        consignee_area = models.CharField(max_length=200, default=0)
        consignee_address = models.CharField(max_length=200, default=0)
        consignee_zip = models.CharField(max_length=200, default=0)
        consignee_mobile = models.CharField(max_length=200,default=0)
        creat_time = models.DateTimeField(auto_now_add=True)
        update_time = models.DateTimeField(auto_now=True)
        def __str__(self):
            return self.order_id

    商品订单的实现

    from rest_framework.views import APIView
    from rest_framework.response import  Response
    from django.core.cache import cache
    from  app01 import models
    from app01.comment import func
    import hashlib,time
    from django.db import transaction
    
    
    from django import forms
    class OrderForm(forms.Form):
        phone = forms.CharField(
            error_messages={
                "required": "手机号不能为空"
            },
            # 调用Form组件中的验证器来校验手机号
           # validators=[RegexValidator(r'1[1-9][0-9]{9}', '手机号格式不正确')],
        )
        token = forms.CharField( error_messages={
                "required": "token不能为空"
            })
        province=forms.CharField( error_messages={
                "required": "省份不能为空"
            })
        city = forms.CharField(error_messages={
            "required": "城市不能为空"
        })
        county = forms.CharField(error_messages={
            "required": "县/区不能为空"
        })
        address = forms.CharField(error_messages={
            "required": "详细地址不能为空"
        })
        name = forms.CharField(error_messages={
            "required": "姓名不能为空"
        })
    
    class Creat(APIView):
        @transaction.atomic
        def post(self,request):
            param=request.data
            form_obj=OrderForm(param)
            if form_obj.is_valid() and param['buy_list']:
                user_cache=cache.get(param['token'])
                if user_cache:
                    openid=user_cache.split("&")[0]
                    user_data=models.Wxuser.objects.filter(openid=openid).first()
                    order_data = {"consignee_mobile": param['phone'],
                                  'consignee_name': param['name'],
                                  'wxuser_id': user_data.id,
                                  "memo": param['remark'],
                                  "consignee_area":f"{param['province']},{param['city']},{param['county']}",
                                  "consignee_address":param['address'] ,
                                  }
    
                    buy_list=param['buy_list']
                    goods_key=list(buy_list.keys())
                    all_product=models.Product.objects.filter(product_id__in=goods_key)
                    order_data['order_id']=func.get_order_id()
                    order_data['order_total']=0
                    order_data['quantity']=0
                    sid=transaction.savepoint()
                    for product in all_product:
                        product.product_id=str(product.product_id)
                        order_data['order_total']+=product.price*buy_list[product.product_id]
                        order_data['quantity']+=buy_list[product.product_id]
    
                        #创建子订单
                        for i in range(3):
                            stock=product.stock.quantity
                            new_stock=stock-buy_list[product.product_id]
                            if new_stock<0:
                                transaction.rollback(sid)
                                return Response({"code":203,"msg":f"{product.name}库存不足"})
                            res=models.Stock.objects.filter(quantity=stock,stock_id=product.stock.stock_id).update(quantity=new_stock)
                            if not  res:
                                if i==2:
                                    transaction.rollback(sid)
                                    return Response({"code": 203, "msg": f"创建订单失败"})
                                else:
                                    continue
                            else:
                                break
                        new_buy_count = product.buy_count + buy_list[product.product_id]
                        models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
                        order_item_data={'order_id': order_data['order_id'], 'product_id': product.product_id, 
                                       "name": product.name, "image": product.image, "price": product.price, 
                                       "nums": buy_list[product.product_id], "brief": product.brief}
                        models.Order_items.objects.create(**order_item_data)
    
                        #models.Order_items.objects.create(**order_item_data)
                    models.Order.objects.create(**order_data)
    
                else:
                    return Response({"code":202,"msg":"token已过期"})
            else:
                return Response({"code":201,"msg":"缺少参数"})

     

     

      

      

      

  • 相关阅读:
    JavaScript获取后台C#变量以及后台方法
    无刷新二级联动dropdownlist
    如何使用验证控件对DropDownList进行验证
    对某项目中Vuex用法的分析
    JavaScript中的深拷贝和浅拷贝
    Vue开发中的中央事件总线
    Vue项目中使用Vuex + axios发送请求
    html文件引用本地js文件出现跨域问题的解决方案
    数组的一些与遍历相关的方法总结
    《EMCAScript6入门》读书笔记——16.Generator函数的语法
  • 原文地址:https://www.cnblogs.com/Gaimo/p/11827857.html
Copyright © 2020-2023  润新知