一。事务的隔离级别。

  mysql的默认数据库级别是可重复读,一般的应用使用的是读已提交

  http://www.zsythink.net/archives/1233/

  1. Read UnCommitted(读未提交)

  最低的隔离级别。一个事务可以读取另一个事务并未提交的更新结果。

  2. Read Committed(读提交)

  大部分数据库采用的默认隔离级别。一个事务的更新操作结果只有在该事务提交之后,另一个事务才可以的读取到同一笔数据更新后的结果。

  3. Repeatable Read(重复读)

  mysql的默认级别。整个事务过程中,对同一笔数据的读取结果是相同的,不管其他事务是否在对共享数据进行更新,也不管更新提交与否。

  4. Serializable(序列化)

  最高隔离级别。所有事务操作依次顺序执行。注意这会导致并发度下降,性能最差。通常会用其他并发级别加上相应的并发锁机制来取代它。

  1.脏读。

  当两个事务对数据进行操作时,事务A读取了一些数据之后,对其进行修改,但是还未提交,事务b对该数据进行读取的时候读取的是事务a修改后的数据,这个数据就是一个脏数据,如果数据a对该数据进行回滚,就会报错。

  2.不可重复读

  当事务A对一些数据进行读取的时候,事务B也对该数据进行了读取,并修改,当事务A再次对其进行读取的时候,就会发现数据不对,就是不可重复读。即数据不重复。

  3。幻读。

  在重复读的隔离级别下,数据是不能被修改的,但是可以被提交,所以当事务A对影响行数据进行读取的时候,事务b添加了一项数据,事务A再次读取的时候就会发现多了一条数据,就像出现幻觉一样。

  处理方法:

  1.悲观锁。

  当事务处理数据的时候。默认所有的数据会被其他数据操作,所以加上锁,不开放任何权限(包括查的权限),保证所有数据都处理完再开放锁。

  2。乐观锁,

  当处理事务的时候,默认所有的数据不会被其他数据,再提交数据之前再进行判断库中的数据是否和一开始读的数据相同(需要再可重复读的级别下,再事务过程中,保证识别到其他操作的提交数据)。

  在处理数据时,后提交的操作会时最终的数据。

二。celery

  当订单提交完毕之后,用户不会马上支付,就会调用celery分配异步任务,将该任务延时一定时间,将其回滚到一开始的状态。

项目详情。

comment

  1. def get_level(data):
  2. data_list=[]
  3. for item in data:
  4. if item['parent_id']==0:
  5. item['level']=0
  6. else:
  7. item['level']=1
  8. data_list.append(item)
  9. return data_list
  10.  
  11. data=[
  12. {"cat_id":1,"name":"北京","parent_id":0},
  13. {"cat_id":2,"name":"上海","parent_id":0},
  14. {"cat_id":3,"name":"沙河","parent_id":1},
  15. {"cat_id":4,"name":"sb镇","parent_id":3},
  16. {"cat_id":5,"name":"昌平","parent_id":1},
  17. {"cat_id":6,"name":"青浦","parent_id":2},
  18. ]
  19.  
  20. def get_tree(data):
  21. lists=[]
  22. tree={}
  23. for i in data:
  24. tree[i['cat_id']]=i
  25. for item in data:
  26. if not item['parent_id']:
  27. lists.append(tree[item['cat_id']])
  28. else:
  29. if "children" not in tree[item['parent_id']]:
  30. tree[item['parent_id']]['children']=[]
  31. tree[item['parent_id']]['children'].append(tree[item['cat_id']])
  32. return lists
  33.  
  34. print(get_tree(data))
  35.  
  36. res=[]
  37. def get_son(data,level=0,parent_id=0,is_clear=True):
  38. if is_clear:
  39. res.clear()
  40. for item in data:
  41. if item['parent_id']==parent_id:
  42. item['level']=level
  43. res.append(item)
  44. get_son(data,level=level+1,parent_id=item['cat_id'],is_clear=False)
  45. return res
  46.  
  47. # print(get_son(data))
  48. # son=get_son(data)
  49. # for i in son:
  50. # print("-"*i['level']+i['name'])
  51. # 1北京 0
  52. # 2-海淀1
  53. # 4--sb镇2
  54. # -昌平
  55. # 3 上海 0
  56. # -青浦
  57. # --徐泾镇
  58. # -闵行
  59. res_id=[]
  60. def get_son_id(data,parent_id=0,is_clear=True):
  61. if is_clear:
  62. res_id.clear()
  63. if parent_id :
  64. res_id.append(parent_id)
  65.  
  66. for item in data:
  67. if item['parent_id']==parent_id:
  68. res_id.append(item['cat_id'])
  69. get_son_id(data,parent_id=item['cat_id'],is_clear=False)
  70. return res_id
  71.  
  72. # print(get_son_id(data,1))
  73.  
  74. import time ,random
  75. def get_order_id():
  76. st="012345679qwertyui"
  77. order_id=str(time.strftime("%Y%m%d%h%M%S"))+"".join(random.sample(st,5))
  78. return order_id
  79.  
  80. from datetime import datetime
  81.  
  82. def add_task(order_id,seconds=5):
  83. from pro_celery.celery import del_order
  84. ctime = datetime.now()
  85. utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
  86. from datetime import timedelta
  87. time_delay = timedelta(seconds=seconds)
  88. task_time = utc_ctime + time_delay
  89. result = del_order.apply_async(args=[order_id, ], eta=task_time)

func.py

my_ser

  1. from rest_framework import serializers
  2. from app01 import models
  3. class Banner_ser(serializers.ModelSerializer):
  4. image_url=serializers.ImageField(source="image.image_url")
  5. product_id=serializers.IntegerField(source="product.product_id")
  6. class Meta:
  7. model=models.Banner
  8. fields="__all__"

Banner_ser

  1. from rest_framework import serializers
  2. from app01 import models
  3. class Category_ser(serializers.ModelSerializer):
  4. image_url=serializers.ImageField(source="image.image_url")
  5. parent_id=serializers.SerializerMethodField()
  6. def get_parent_id(self,obj):
  7. if obj.parent_id is None:
  8. return 0
  9. else:
  10. return obj.parent_id
  11.  
  12. class Meta:
  13. model=models.Category
  14. fields="__all__"

Category_ser

  1. from rest_framework import serializers
  2. from app01 import models
  3. class Goods_ser(serializers.ModelSerializer):
  4. image_url=serializers.ImageField(source="image.image_url")
  5. stock=serializers.IntegerField(source="stock.quantity")
  6. class Meta:
  7. model=models.Product
  8. fields="__all__"

Goods_ser

Pay

  1. import time
  2. from app01.wx import settings
  3. class Wxpay:
  4. def pay(self,order_data):
  5. self.order_id = order_data["order_id"]
  6. self.open_id = order_data['open_id']
  7. self.ip = order_data['ip']
  8. data_body = self.get_body_data()
  9. import requests
  10. url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
  11. response = requests.post(url, data_body.encode("utf-8"), headers={'content-type': "application/xml"})
  12. res_dict = self.xml_to_dic(response.content)
  13. timeStamp = str(int(time.time()))
  14. paySign = self.get_pay_sign(res_dict, timeStamp)
  15.  
  16. data_dic = {
  17. 'timeStamp': timeStamp,
  18. 'nonceStr': res_dict['nonce_str'],
  19. 'package': f"prepay_id={res_dict['prepay_id']}",
  20. 'signType': 'MD5',
  21. "paySign": paySign,
  22. }
  23.  
  24. return data_dic
  25.  
  26. def get_pay_sign(self, res_dict, timeStamp):
  27. data_dic = {
  28. 'appId': res_dict['appid'],
  29. 'timeStamp': timeStamp,
  30. 'nonceStr': res_dict['nonce_str'],
  31. 'package': f"prepay_id={res_dict['prepay_id']}",
  32. "signType": "MD5"
  33. }
  34. sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
  35. sign_str = f"{sign_str}&key={settings.pay_apikey}"
  36. import hashlib
  37. md5 = hashlib.md5()
  38. md5.update(sign_str.encode("utf-8"))
  39. sign = md5.hexdigest()
  40. return sign.upper()
  41.  
  42. def xml_to_dic(self, xml_data):
  43. import xml.etree.ElementTree as ET
  44. '''
  45. xml to dict
  46. :param xml_data:
  47. :return:
  48. '''
  49. xml_dict = {}
  50. root = ET.fromstring(xml_data)
  51. for child in root:
  52. xml_dict[child.tag] = child.text
  53. return xml_dict
  54.  
  55. def get_random(self):
  56. import random
  57. data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
  58. nonce_str = "".join(random.sample(data, 30))
  59. return nonce_str
  60.  
  61. def get_sign(self):
  62. data_dic = {
  63. "nonce_str": self.nonce_str,
  64. "out_trade_no": self.out_trade_no,
  65. "spbill_create_ip": self.spbill_create_ip,
  66. "notify_url": self.notify_url,
  67. "openid": self.open_id,
  68. "body": self.body,
  69. "trade_type": "JSAPI",
  70. "appid": self.appid,
  71. "total_fee": "",
  72. "mch_id": self.mch_id
  73. }
  74.  
  75. sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
  76. sign_str = f"{sign_str}&key={settings.pay_apikey}"
  77. import hashlib
  78. md5 = hashlib.md5()
  79. md5.update(sign_str.encode("utf-8"))
  80. sign = md5.hexdigest()
  81. return sign.upper()
  82.  
  83. def get_body_data(self):
  84. self.appid = settings.AppId
  85. # openid=self.open_id
  86. self.mch_id = str(settings.pay_mchid)
  87. self.nonce_str = self.get_random()
  88. self.out_trade_no = self.order_id
  89. self.spbill_create_ip = self.ip
  90. self.notify_url = "https://www.test.com"
  91. self.body = "lzx"
  92. self.sign = self.get_sign()
  93. body_data = f"""
  94. <xml>
  95. <appid>{self.appid}</appid>
  96. <mch_id>{self.mch_id}</mch_id>
  97. <nonce_str>{self.nonce_str}</nonce_str>
  98. <sign>{self.sign}</sign>
  99. <body>{self.body}</body>
  100. <out_trade_no>{self.out_trade_no}</out_trade_no>
  101. <total_fee>1</total_fee>
  102. <spbill_create_ip>{ self.spbill_create_ip}</spbill_create_ip>
  103. <notify_url>{self.notify_url}</notify_url>
  104. <openid>{self.open_id}</openid>
  105. <trade_type>JSAPI</trade_type>
  106. </xml>"""
  107. return body_data

Wxpay

views

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from app01 import models
  4. from app01.my_ser import Banner_ser
  5.  
  6. class List(APIView):
  7. def post(self,request):
  8. data = models.Banner.objects.filter(is_show=True).order_by("-w_order")
  9. data = Banner_ser.Banner_ser(instance=data,many=True,context={"request":request}).data
  10. return Response({
  11. "code":200,
  12. "msg":"ok",
  13. "data":data
  14. })

Banner

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from app01 import models
  4. from app01.my_ser import Category_ser
  5. from app01.comment import func
  6. class All(APIView):
  7. def post(self,request):
  8. data=models.Category.objects.filter(is_show=True)
  9. data=Category_ser.Category_ser(instance=data,many=True,context={"request":request}).data
  10. data=func.get_son(data)
  11. return Response({
  12. "code":200,
  13. "msg":"ok",
  14. "data":data
  15. })

Category

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from app01.my_ser import Goods_ser
  4. from app01 import models
  5. from app01.my_ser import Category_ser,Goods_ser
  6. from app01.comment import func
  7. class HotGoods(APIView):
  8. def post(self,request):
  9. data=models.Product.objects.filter(disabled=True).order_by("-buy_count","-w_order")
  10. data=Goods_ser.Goods_ser(instance=data,many=True,context={"request":request}).data
  11. return Response({"code":200,"msg":"ok","data":data})
  12.  
  13. class List(APIView):
  14. def post(self,request):
  15. param=request.data
  16. if param.get('category_id'):
  17. data=models.Category.objects.filter(is_show=True)
  18. data=Category_ser.Category_ser(instance=data,many=True,context={"request":request}).data
  19. all_id=func.get_son_id(data,param['category_id'])
  20. data=models.Product.objects.filter(disabled=True,cat_id__in=all_id).order_by("-w_order")
  21. data = Goods_ser.Goods_ser(instance=data, many=True, context={"request": request}).data
  22. return Response({"code": 200, "msg": "ok", "data": data})
  23. else:
  24. return Response({"code": 201, "msg":"缺少参数" })
  25.  
  26. class Detail(APIView):
  27. def post(self,request):
  28. param=request.data
  29. if param.get("id"):
  30. data = models.Product.objects.filter(disabled=True,product_id=param.get("id")).first()
  31. if data:
  32. data = Goods_ser.Goods_ser(instance=data, many=False, context={"request": request}).data
  33. print(data)
  34. return Response({"code": 200, "msg": "ok", "data": data})
  35. else:
  36. return Response({"code": 201, "msg": "没有该商品"})

Goods

  1. import importlib
  2.  
  3. from rest_framework.views import APIView
  4. from rest_framework.response import Response
  5. from django.core.cache import cache
  6. from app01 import models
  7. from app01.comment import func
  8. import hashlib, time
  9. from django.db import transaction
  10.  
  11. from django import forms
  12.  
  13. class OrderForm(forms.Form):
  14. phone = forms.CharField(
  15. error_messages={
  16. "required": "手机号不能为空"
  17. },
  18. # 调用Form组件中的验证器来校验手机号
  19. # validators=[RegexValidator(r'1[1-9][0-9]{9}', '手机号格式不正确')],
  20. )
  21. token = forms.CharField(error_messages={
  22. "required": "token不能为空"
  23. })
  24. province = forms.CharField(error_messages={
  25. "required": "省份不能为空"
  26. })
  27. city = forms.CharField(error_messages={
  28. "required": "城市不能为空"
  29. })
  30. county = forms.CharField(error_messages={
  31. "required": "县/区不能为空"
  32. })
  33. address = forms.CharField(error_messages={
  34. "required": "详细地址不能为空"
  35. })
  36. name = forms.CharField(error_messages={
  37. "required": "姓名不能为空"
  38. })
  39.  
  40. class Creat(APIView):
  41. @transaction.atomic
  42. def post(self, request):
  43. param = request.data
  44. form_obj = OrderForm(param)
  45. if form_obj.is_valid() and param['buy_list']:
  46. if request.META.get("HTTP_X_FORWARDED_FOR"):
  47. host_ip = request.META["HTTP_X_FROWARDED_FOR"]
  48. else:
  49. host_ip = request.META["REMOTE_ADDR"]
  50. user_cache = cache.get(param['token'])
  51. if user_cache:
  52. openid = user_cache.split("&")[0]
  53. user_data = models.Wxuser.objects.filter(openid=openid).first()
  54. order_data = {"consignee_mobile": param['phone'],
  55. 'consignee_name': param['name'],
  56. 'wxuser_id': user_data.id,
  57. "memo": param['remark'],
  58. "consignee_area": f"{param['province']},{param['city']},{param['county']}",
  59. "consignee_address": param['address'],
  60. }
  61. buy_list = param['buy_list']
  62. goods_key = list(buy_list.keys())
  63. all_product = models.Product.objects.filter(product_id__in=goods_key)
  64. order_data['order_id'] = func.get_order_id()
  65. order_data['order_total'] = 0
  66. order_data['quantity'] = 0
  67. sid = transaction.savepoint()
  68. for product in all_product:
  69. product.product_id = str(product.product_id)
  70. order_data['order_total'] += product.price * buy_list[product.product_id]
  71. order_data['quantity'] += buy_list[product.product_id]
  72. # 创建子订单
  73. for i in range(3):
  74. stock = product.stock.quantity
  75. new_stock = stock - buy_list[product.product_id]
  76. if new_stock < 0:
  77. transaction.rollback(sid)
  78. return Response({"code": 203, "msg": f"{product.name}库存不足"})
  79. res = models.Stock.objects.filter(quantity=stock, stock_id=product.stock.stock_id).update(
  80. quantity=new_stock)
  81. if not res:
  82. if i == 2:
  83. transaction.rollback(sid)
  84. return Response({"code": 203, "msg": f"创建订单失败"})
  85. else:
  86. continue
  87. else:
  88. break
  89. new_buy_count = product.buy_count + buy_list[product.product_id]
  90. models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
  91. order_item_data = {'order_id': order_data['order_id'], 'product_id': product.product_id, \
  92. "name": product.name, "image": product.image, "price": product.price, \
  93. "nums": buy_list[product.product_id], "brief": product.brief}
  94. models.Order_items.objects.create(**order_item_data)
  95.  
  96. # models.Order_items.objects.create(**order_item_data)
  97. models.Order.objects.create(**order_data)
  98. pay_methon = "Wxpay"
  99. try:
  100. pay_file = importlib.import_module(f"app01.Pay.{pay_methon}")
  101. pay_class = getattr(pay_file,pay_methon)
  102. order_data['open_id'] = openid
  103. order_data['ip'] = host_ip
  104. data = pay_class().pay(order_data)
  105. except:
  106. transaction.savepoint_rollback(sid)
  107. return Response({"code": 202, "msg": "未知的支付方式"})
  108. transaction.savepoint_commit(sid)
  109. func.add_task(order_data['order_id'])
  110. return Response({"code": 200, "msg":"ok","data":data})
  111. else:
  112. return Response({"code": 202, "msg": "token已过期"})
  113. else:
  114. return Response({"code": 201, "msg": "缺少参数"})
  115.  
  116. class Notity(APIView):
  117. def post(self,request,paymethon):
  118. pay_file = importlib.import_module(f"app01.Pay.{paymethon}")
  119. pay_class = getattr(pay_file, paymethon)
  120. data=pay_class().notity(request.data)
  121. if data['status']=="success":
  122. models.Order.objects.filter(order_id=data['order']).updata(pay_status=1)

Order

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from django.core.cache import cache
  4. from app01 import models
  5. import hashlib,time
  6. from app01.wx import wx_Login
  7. class Login(APIView):
  8. def post(self,request):
  9. param=request.data
  10. if param.get("code"):
  11. data=wx_Login.login(param.get("code"))
  12. if data:
  13. val=data['openid']+"&"+data["session_key"]
  14. key=str(int(time.time()))+data['openid']
  15. md5=hashlib.md5()
  16. md5.update(key.encode("utf-8"))
  17. key=md5.hexdigest()
  18. cache.set(key,val)
  19. has_user=models.Wxuser.objects.filter(openid=data['openid']).first()
  20. if not has_user:
  21. models.Wxuser.objects.create(openid=data['openid'])
  22. return Response({"code":200,"msg":"ok",'data':{"login_key":key}})
  23.  
  24. else:
  25. return Response({"code":200,"msg":"code错误"})
  26. else:
  27. return Response({"code": 200, "msg": "缺少参数"})

User

wx

  1. import xadmin
  2. from xadmin import views
  3. from app01 import models
  4.  
  5. class BaseSetting(object):
  6. """xadmin的基本配置"""
  7. enable_themes = True # 开启主题切换功能
  8. use_bootswatch = True
  9.  
  10. xadmin.site.register(views.BaseAdminView, BaseSetting)
  11.  
  12. class GlobalSettings(object):
  13. """xadmin的全局配置"""
  14. site_title = "商城后台" # 设置站点标题
  15. site_footer = "饼哥有限公司" # 设置站点的页脚
  16. menu_style = "accordion" # 设置菜单折叠
  17.  
  18. xadmin.site.register(views.CommAdminView, GlobalSettings)
  19.  
  20. xadmin.site.register(models.Order_items)
  21. xadmin.site.register(models.Product)
  22. xadmin.site.register(models.Order)
  23. xadmin.site.register(models.Category)
  24. xadmin.site.register(models.Stock)
  25. xadmin.site.register(models.Images)
  26. xadmin.site.register(models.Wxuser)
  27.  
  28. xadmin.site.register(models.Banner)

adminx

  1. from django.db import models
  2.  
  3. # Create your models here.
  4. '''
  5. #banner
  6. id
  7. image_url
  8. product_id
  9. is_show
  10. w_order
  11. create_time
  12. update_time
  13.  
  14. #销量最高的排前面,销量一样,权重大的在前面
  15. #product_id
  16. id
  17. name
  18. price
  19. intor
  20. buy_count
  21. w_order (越大越前)
  22. detail
  23. image_url
  24. scort #库存
  25. is_show
  26. catory_id
  27. create_time
  28. update_time
  29.  
  30. #scort库存
  31. id
  32. name
  33. num
  34. create_time
  35. update_time
  36.  
  37. #category_id
  38. id
  39. cate_name
  40. image_url
  41. parent_id
  42. create_time
  43. update_time
  44.  
  45. #imgae
  46. id
  47. imgae_url
  48. name
  49. create_time
  50. update_time
  51.  
  52. #订单
  53. order_id
  54. 商品总数量
  55. 总价格
  56. 收货地址
  57. 用户id
  58. 订单状态(是否取消)
  59. 收货人电话
  60. 收人姓名
  61. 支付
  62. create_time
  63. update_time
  64.  
  65. order_item
  66. id
  67. order_id
  68. 商品id
  69. 商品价格
  70. num
  71. image_url
  72. create_time
  73. update_time
  74.  
  75. '''
  76.  
  77. # Create your models here.
  78. class Wxuser(models.Model):
  79. id = models.AutoField(primary_key=True)
  80. openid=models.CharField(max_length=255)
  81. name = models.CharField(max_length=50)
  82. avatar = models.CharField(max_length=200)
  83. language = models.CharField(max_length=50)
  84. province = models.CharField(max_length=50)
  85. city = models.CharField(max_length=50)
  86. country = models.CharField(max_length=50)
  87. gender = models.CharField(max_length=50),
  88. creat_time = models.DateTimeField(auto_now_add=True)
  89. update_time = models.DateTimeField(auto_now=True)
  90. def __str__(self):
  91. return self.openid
  92.  
  93. class Category(models.Model):
  94. cat_id=models.AutoField(primary_key=True)
  95. category_name=models.CharField(max_length=50)
  96. parent=models.ForeignKey(to='Category', to_field='cat_id', related_name="Category", on_delete=models.CASCADE, db_constraint=False,blank=True,null=True)
  97. p_order=models.IntegerField(default=0)
  98. is_show =models.BooleanField(default=1)
  99. image = models.OneToOneField(to='Images', to_field='image_id', on_delete=models.CASCADE, db_constraint=False,null=True)
  100. creat_time = models.DateTimeField(auto_now_add=True)
  101. update_time = models.DateTimeField(auto_now=True)
  102. def __str__(self):
  103. return self.category_name
  104.  
  105. class Images(models.Model):
  106. image_id=models.AutoField(primary_key=True)
  107. name=models.CharField(max_length=30,default="")
  108. image_url=models.ImageField(upload_to="")
  109. creat_time = models.DateTimeField(auto_now_add=True)
  110. update_time = models.DateTimeField(auto_now=True)
  111. def __str__(self):
  112. return self.name
  113.  
  114. class Product(models.Model):
  115. product_id=models.AutoField(primary_key=True)
  116. name=models.CharField(max_length=200)
  117. price=models.DecimalField(max_digits=10, decimal_places=2)
  118. weight=models.IntegerField(default=0)
  119. cat = models.ForeignKey(to="Category", to_field="cat_id", related_name="Product", db_constraint=False, on_delete=models.CASCADE)
  120. intor = models.TextField(max_length=250)#详细介绍
  121. brief = models.TextField(max_length=250)#商品简介
  122. image=models.OneToOneField(to='Images',to_field='image_id',on_delete=models.CASCADE,db_constraint=False)
  123. stock = models.OneToOneField(to="Stock", to_field="stock_id", db_constraint=False, on_delete=models.CASCADE)
  124. buy_count=models.IntegerField(default=0)#购买量
  125. disabled = models.BooleanField(default=1)#是否显示
  126. w_order=models.IntegerField(default=0)#权重
  127. creat_time = models.DateTimeField(auto_now_add=True)
  128. update_time = models.DateTimeField(auto_now=True)
  129. def __str__(self):
  130. return self.name
  131.  
  132. class Order(models.Model):
  133. order_id = models.CharField(max_length=50, unique=True, primary_key=True)
  134. status_choices = (("active", '活动订单'), ("dead", '作废订单'), ("finish", '已完成订单'))
  135. status = models.CharField(choices=status_choices, default="active", max_length=50)
  136. pay_status_choices = ((0, '未付款'), (1, '已付款'))
  137. pay_status = models.SmallIntegerField(choices=pay_status_choices, default=0)
  138. payed = models.DecimalField(max_digits=10, decimal_places=2,default=0)
  139. order_total = models.DecimalField(max_digits=10, decimal_places=2,default=0)
  140. ship_status_choices = ((0, '未发货'), (1, '已发货'))
  141. pay_app = models.CharField(max_length=100)
  142. wxuser = models.ForeignKey(to="Wxuser", to_field="id", related_name="Order", db_constraint=False,on_delete=models.CASCADE)
  143. quantity = models.IntegerField(default=0)
  144. memo = models.CharField(max_length=200, default=0)
  145. consignee_name = models.CharField(max_length=200, default=0)
  146. consignee_area = models.CharField(max_length=200, default=0)
  147. consignee_address = models.CharField(max_length=200, default=0)
  148. consignee_zip = models.CharField(max_length=200, default=0)
  149. consignee_mobile = models.CharField(max_length=200,default=0)
  150. creat_time = models.DateTimeField(auto_now_add=True)
  151. update_time = models.DateTimeField(auto_now=True)
  152. def __str__(self):
  153. return self.order_id
  154.  
  155. class Order_items(models.Model):
  156. item_id = models.AutoField(primary_key=True)
  157. order= models.ForeignKey(to="Order", to_field="order_id", related_name="Order_items", db_constraint=False,on_delete=models.CASCADE)
  158. product=models.ForeignKey(to="Product", to_field="product_id", related_name="Order_items", db_constraint=False,on_delete=models.CASCADE,null=True)
  159. name = models.CharField(max_length=200)
  160. image = models.ForeignKey(to='Images', to_field='image_id',related_name="Order_items", on_delete=models.CASCADE,db_constraint=False)
  161. price = models.DecimalField(max_digits=10, decimal_places=2,default=0)
  162. amount=models.DecimalField(max_digits=10, decimal_places=2,default=0)
  163. nums=models.IntegerField()
  164. send_nums=models.IntegerField(null=True)
  165. brief=models.CharField(max_length=200)
  166. creat_time = models.DateTimeField(auto_now_add=True)
  167. update_time = models.DateTimeField(auto_now=True)
  168.  
  169. class Stock(models.Model):
  170. stock_id=models.AutoField(primary_key=True)
  171. name=models.CharField(max_length=100)
  172. quantity=models.IntegerField(default=0)#库存量
  173. creat_time = models.DateTimeField(auto_now_add=True)
  174. update_time = models.DateTimeField(auto_now=True)
  175. def __str__(self):
  176. return self.name
  177.  
  178. class Banner(models.Model):
  179. product = models.OneToOneField(to="Product", to_field="product_id", db_constraint=False, on_delete=models.CASCADE)
  180. w_order = models.IntegerField(default=0) # 权重
  181. image = models.OneToOneField(to='Images', to_field='image_id', on_delete=models.CASCADE, db_constraint=False)
  182. is_show =models.BooleanField(default=1)
  183. creat_time = models.DateTimeField(auto_now_add=True)
  184. update_time = models.DateTimeField(auto_now=True)
  185. def __str__(self):
  186. return self.product.name

models

pro_celery

  1. import celery
  2. import time
  3. # broker='redis://127.0.0.1:6379/2' 不加密码
  4. backend='redis://127.0.0.1:6379/1'
  5. broker='redis://127.0.0.1:6379/2'
  6. cel=celery.Celery('test',backend=backend,broker=broker)
  7.  
  8. import os, sys
  9. import django
  10. BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # 定位到你的django根目录
  11. # sys.path.append(os.path.join(BASE_DIR, "app01"))
  12. sys.path.append(os.path.abspath(BASE_DIR))
  13. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wxshop.settings")
  14. django.setup()
  15. from django.db import transaction
  16.  
  17. @cel.task
  18. @transaction.atomic
  19. def del_order(order_id):
  20. '''
  21. 1 拿订单查询,订单号,是否支付,活跃
  22. 2 判断data是否有
  23.  
  24. :param order_id:
  25. :return:
  26. '''
  27. from app01 import models
  28. data=models.Order.objects.filter(order_id=order_id,pay_status=0,status="active").first()
  29. if data:
  30. item_data=models.Order_items.objects.filter(order_id=order_id).values("product","nums")
  31. # [{product:1,nums:3}]
  32. # {1:3,2:1}
  33. all_product_dict = { k['product']:k['nums'] for k in item_data}
  34. all_product_id =list(all_product_dict.keys())
  35. products_all=models.Product.objects.filter(product_id__in=all_product_id)
  36. sid=transaction.savepoint()
  37.  
  38. for product in products_all:
  39. for i in range(3):
  40. stock=product.stock.quantity
  41. new_stock=stock+all_product_dict[product.product_id]
  42. new_buy_count=product.buy_count-all_product_dict[product.product_id]
  43. res=models.Stock.objects.filter(quantity=stock,stock_id=product.stock).update(quantity=new_stock)
  44. if not res:
  45. if i==2:
  46. from app01.comment import func
  47. transaction.savepoint_rollback(sid)
  48. func.add_task(order_id,1)
  49. return
  50. else:
  51. continue
  52. else:
  53. break
  54. models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
  55.  
  56. row=models.Order.objects.filter(order_id=order_id,pay_status=0).update(status="dead")
  57. if row:
  58. transaction.savepoint_commit(sid)
  59. else:
  60. transaction.savepoint_rollback(sid)

celery

wxshopapi2

  1. """
  2. Django settings for wxshopapi2 project.
  3.  
  4. Generated by 'django-admin startproject' using Django 2.0.7.
  5.  
  6. For more information on this file, see
  7. https://docs.djangoproject.com/en/2.0/topics/settings/
  8.  
  9. For the full list of settings and their values, see
  10. https://docs.djangoproject.com/en/2.0/ref/settings/
  11. """
  12.  
  13. import os
  14.  
  15. # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
  16. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  17.  
  18. # Quick-start development settings - unsuitable for production
  19. # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
  20.  
  21. # SECURITY WARNING: keep the secret key used in production secret!
  22. SECRET_KEY = '$v^um*l969ywfw2$3=rv5y&ehv$b@e#w&ha(%t!_+rv3=3#74n'
  23.  
  24. # SECURITY WARNING: don't run with debug turned on in production!
  25. DEBUG = True
  26.  
  27. ALLOWED_HOSTS = []
  28.  
  29. # Application definition
  30.  
  31. INSTALLED_APPS = [
  32. 'django.contrib.admin',
  33. 'django.contrib.auth',
  34. 'django.contrib.contenttypes',
  35. 'django.contrib.sessions',
  36. 'django.contrib.messages',
  37. 'django.contrib.staticfiles',
  38. 'app01.apps.App01Config',
  39. 'rest_framework',
  40. 'xadmin',
  41. 'crispy_forms',
  42. 'reversion',
  43. ]
  44.  
  45. MIDDLEWARE = [
  46. 'django.middleware.security.SecurityMiddleware',
  47. 'django.contrib.sessions.middleware.SessionMiddleware',
  48. 'django.middleware.common.CommonMiddleware',
  49. 'django.middleware.csrf.CsrfViewMiddleware',
  50. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  51. 'django.contrib.messages.middleware.MessageMiddleware',
  52. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  53. ]
  54.  
  55. ROOT_URLCONF = 'wxshopapi2.urls'
  56.  
  57. TEMPLATES = [
  58. {
  59. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  60. 'DIRS': [os.path.join(BASE_DIR, 'templates')],
  61. 'APP_DIRS': True,
  62. 'OPTIONS': {
  63. 'context_processors': [
  64. 'django.template.context_processors.debug',
  65. 'django.template.context_processors.request',
  66. 'django.contrib.auth.context_processors.auth',
  67. 'django.contrib.messages.context_processors.messages',
  68. ],
  69. },
  70. },
  71. ]
  72.  
  73. WSGI_APPLICATION = 'wxshopapi2.wsgi.application'
  74.  
  75. # Database
  76. # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
  77.  
  78. DATABASES = {
  79. 'default': {
  80. 'ENGINE': 'django.db.backends.mysql',
  81. 'NAME': 'wxshop',
  82. 'USER':'root',
  83. 'PASSWORD':'',
  84. 'HOST':'127.0.0.1',
  85. 'PORT': 3306,
  86. 'OPTIONS': {'charset': 'utf8mb4'},
  87. }
  88. }
  89.  
  90. # Password validation
  91. # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
  92.  
  93. AUTH_PASSWORD_VALIDATORS = [
  94. {
  95. 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  96. },
  97. {
  98. 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  99. },
  100. {
  101. 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  102. },
  103. {
  104. 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  105. },
  106. ]
  107.  
  108. # Internationalization
  109. # https://docs.djangoproject.com/en/2.0/topics/i18n/
  110.  
  111. LANGUAGE_CODE = 'zh-Hans'
  112.  
  113. TIME_ZONE = 'Asia/Shanghai'
  114.  
  115. USE_I18N = True
  116.  
  117. USE_L10N = True
  118.  
  119. USE_TZ = False
  120.  
  121. # Static files (CSS, JavaScript, Images)
  122. # https://docs.djangoproject.com/en/2.0/howto/static-files/
  123.  
  124. STATIC_URL = '/static/'
  125.  
  126. STATICFILES_DIRS = [
  127. os.path.join(BASE_DIR,'static'),
  128. ]
  129. MEDIA_ROOT=os.path.join(BASE_DIR,'static/media')
  130.  
  131. MEDIA_URL = '/static/media/'
  132. CACHES = {
  133. 'default': {
  134. 'BACKEND': 'django_redis.cache.RedisCache',
  135. 'LOCATION': 'redis://127.0.0.1:6379',
  136. "OPTIONS": {
  137. "CLIENT_CLASS": "django_redis.client.DefaultClient",
  138. },
  139. },
  140. }

settings

  1. """wxshop URL Configuration
  2.  
  3. The `urlpatterns` list routes URLs to views. For more information please see:
  4. https://docs.djangoproject.com/en/2.0/topics/http/urls/
  5. Examples:
  6. Function views
  7. 1. Add an import: from my_app import views
  8. 2. Add a URL to urlpatterns: path('', views.home, name='home')
  9. Class-based views
  10. 1. Add an import: from other_app.views import Home
  11. 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
  12. Including another URLconf
  13. 1. Import the include() function: from django.urls import include, path
  14. 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
  15. """
  16. from django.contrib import admin
  17. from django.urls import path
  18. import xadmin
  19. xadmin.autodiscover()
  20.  
  21. # version模块自动注册需要版本控制的 Model
  22. from xadmin.plugins import xversion
  23. xversion.register_models()
  24. from django.conf.urls import url
  25. from app01.views import User,Banner,Goods,Category,Order
  26. urlpatterns = [
  27. path(r'xadmin/', xadmin.site.urls),
  28. path('admin/', admin.site.urls),
  29. path("user/wxapp/login",User.Login.as_view()),
  30. path("banner/list",Banner.List.as_view()),
  31. path("hotgoods/list",Goods.HotGoods.as_view()),
  32. path("category/all",Category.All.as_view()),
  33. path("goods/list",Goods.List.as_view()),
  34. path("goods/detail",Goods.Detail.as_view()),
  35. path("order/create",Order.Creat.as_view()),
  36. ]

urls

day88_11_8,事务的隔离级别celery定时订单与项目整合。的更多相关文章

  1. SQL Server 之 事务与隔离级别实例讲解

    SQL Server 之 事务与隔离级别实例讲解 SQL Server 实现了6个隔离级别来防止并发情况下,类似企图并发的访问或修改同一数据时问题的发生.本文将带你体验全部6个隔离级别.正如你接下来将 ...

  2. SQLServer 事务的隔离级别

    SQLServer事务的隔离级别 数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务 ...

  3. Hibernate中事务的隔离级别设置

    Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下

  4. MySQL事务学习-->隔离级别

    MySQL事务学习-->隔离级别 6 事务的隔离级别 设置的目的 在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别. 数据库是要被广大客户所共享访问的,那么在数据库操作过程中 ...

  5. SQL Server事务的隔离级别

    SQL Server事务的隔离级别 ########## 数据库中数据的一致性 ########## 针对并发事务出现的数据不一致性,提出了4个级别的解决方法:  隔离级别  第一类丢失更新  脏读 ...

  6. 事务的隔离级别及mysql对应操作

    /* 本次高并发解决之道 1,更改事务隔离级别为 read uncommitted读未提交 2,查询前设定延迟,延迟时间为随机 50-500 微秒 3,修改数据前将 超范围作为 限定修改条件 事务是作 ...

  7. MySQL(26):事务的隔离级别出现问题之 幻读

    1. 幻读 幻读(Phantom Read)又称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不重复读有些类型,同样是在两次查询过程中,不同的是,幻读是由于其他事务做了插入记录的操作,导致记 ...

  8. MySQL(25):事务的隔离级别出现问题之 不可重复读

    1. 不可重复读 所谓的不可重复读(Non-Repeatable Read)是指事务中两次查询的结果不一致,原因是在查询的过程中其他事务做了更新的操作. 例如,银行在做统计报表的时候,第一次查询a账户 ...

  9. MySQL(24):事务的隔离级别

    1. 事务的隔离级别引入: 数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样的就会出现脏读.重复读以及幻读的情况.在数据库操作中,为了有效保证并发读取数据的正确性,需要为事务设 ...

随机推荐

  1. Prometheus学习系列(六)之Prometheus 查询说明

    前言 本文来自Prometheus官网手册和 Prometheus简介 Prothetheus查询 Prometheus提供一个函数式的表达式语言PromQL (Prometheus Query La ...

  2. asp.net core的AOP记录

    序曲:学习编程最好的方式就是敲代码,没有比这个更好的方法,哪怕你看了上百G的视频,都不如你自己敲几行代码更为有效.还有要记得敲完代码然后写一篇随笔来记录一下你所学所想. 什么叫AOP? AOP面向切面 ...

  3. .net core 3.0web_razor page项目_使用中间件接受大文件上传报错_httpRequest.Form threw an exception of type Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException_Request body too large

    前言:在web项目的.net framework时文件上传时,自己常用一般处理程序接受上传文件,上传文件的大小限制是可以项目的webconfig里配置.   到core项目使用一般处理程序变成了中间件 ...

  4. PlayJava Day025

    JTable 用JTable类可以以表格的形式显示和编辑数据 JTable类的对象并不存储数据,它只是数据的表现 MVC 数据.表现和控制三者分离,各负其责 M = Model(模型) V = Vie ...

  5. php 将科学计算法得出的结果转换成原始数据 NumToStr

    由于php最大只支持显示 15位因的数据运算,大于15位的2数加减乘除的数据的结果,会直接用科学计数法显示, 但在现实生活中,科学计数法不利于普通人识别,所以,本函数将:科学计数法的出的结果转换成原始 ...

  6. dedecmsV5.7 百度编辑器ueditor 多图上传 在线管理 排序问题

    问题:dedecms后台百度编辑器ueditor的多图上传-在线管理的图片排序有问题,想把这个顺序调成按照文件修改时间倒序来展示 解决方法: 1.打开/include/ueditor/php/acit ...

  7. 通过U盘在物理机安装CentOS出现Timeout的问题

    错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.

  8. PWA 学习笔记(五)

    离线与缓存 资源请求的拦截代理: 1.资源请求的判断: (1)fetch 事件会拦截页面上所有的网络资源请求,但我们通常只对部分资源请求进行处理, 其余的请求会继续走浏览器默认的资源请求流程 (2)f ...

  9. Cocos2d-x.3.0开发环境搭建

    配置:win7 + VS2012 + Cocos2d-x.3.0 + Cocos Studio v1.4.0.1 前言:本文介绍在上述配置下进行游戏开发的环境搭建.开发语言为C++.如果读者不需要查看 ...

  10. Violet 6 杯省选模拟赛 蒲公英

    https://www.luogu.com.cn/problem/P4168 题目 给$n$个数字,有$m$次询问,问$a_l, a_{l+1} , \dots , a_r$的众数是什么, $1\le ...