day88_11_8,事务的隔离级别celery定时订单与项目整合。
一。事务的隔离级别。
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
- 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
- # print(get_son(data))
- # 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_id(data,parent_id=item['cat_id'],is_clear=False)
- return res_id
- # print(get_son_id(data,1))
- 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
- from datetime import datetime
- def add_task(order_id,seconds=5):
- from pro_celery.celery import del_order
- ctime = datetime.now()
- utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
- from datetime import timedelta
- time_delay = timedelta(seconds=seconds)
- task_time = utc_ctime + time_delay
- result = del_order.apply_async(args=[order_id, ], eta=task_time)
func.py
my_ser
- from rest_framework import serializers
- from app01 import models
- class Banner_ser(serializers.ModelSerializer):
- image_url=serializers.ImageField(source="image.image_url")
- product_id=serializers.IntegerField(source="product.product_id")
- class Meta:
- model=models.Banner
- fields="__all__"
Banner_ser
- from rest_framework import serializers
- from app01 import models
- class Category_ser(serializers.ModelSerializer):
- image_url=serializers.ImageField(source="image.image_url")
- parent_id=serializers.SerializerMethodField()
- def get_parent_id(self,obj):
- if obj.parent_id is None:
- return 0
- else:
- return obj.parent_id
- class Meta:
- model=models.Category
- fields="__all__"
Category_ser
- from rest_framework import serializers
- from app01 import models
- class Goods_ser(serializers.ModelSerializer):
- image_url=serializers.ImageField(source="image.image_url")
- stock=serializers.IntegerField(source="stock.quantity")
- class Meta:
- model=models.Product
- fields="__all__"
Goods_ser
Pay
- import time
- from app01.wx import settings
- class Wxpay:
- def pay(self,order_data):
- self.order_id = order_data["order_id"]
- self.open_id = order_data['open_id']
- self.ip = order_data['ip']
- data_body = self.get_body_data()
- import requests
- url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
- response = requests.post(url, data_body.encode("utf-8"), headers={'content-type': "application/xml"})
- res_dict = self.xml_to_dic(response.content)
- timeStamp = str(int(time.time()))
- paySign = self.get_pay_sign(res_dict, timeStamp)
- data_dic = {
- 'timeStamp': timeStamp,
- 'nonceStr': res_dict['nonce_str'],
- 'package': f"prepay_id={res_dict['prepay_id']}",
- 'signType': 'MD5',
- "paySign": paySign,
- }
- return data_dic
- def get_pay_sign(self, res_dict, timeStamp):
- data_dic = {
- 'appId': res_dict['appid'],
- 'timeStamp': timeStamp,
- 'nonceStr': res_dict['nonce_str'],
- 'package': f"prepay_id={res_dict['prepay_id']}",
- "signType": "MD5"
- }
- sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
- sign_str = f"{sign_str}&key={settings.pay_apikey}"
- import hashlib
- md5 = hashlib.md5()
- md5.update(sign_str.encode("utf-8"))
- sign = md5.hexdigest()
- return sign.upper()
- def xml_to_dic(self, xml_data):
- import xml.etree.ElementTree as ET
- '''
- xml to dict
- :param xml_data:
- :return:
- '''
- xml_dict = {}
- root = ET.fromstring(xml_data)
- for child in root:
- xml_dict[child.tag] = child.text
- return xml_dict
- def get_random(self):
- import random
- data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
- nonce_str = "".join(random.sample(data, 30))
- return nonce_str
- def get_sign(self):
- data_dic = {
- "nonce_str": self.nonce_str,
- "out_trade_no": self.out_trade_no,
- "spbill_create_ip": self.spbill_create_ip,
- "notify_url": self.notify_url,
- "openid": self.open_id,
- "body": self.body,
- "trade_type": "JSAPI",
- "appid": self.appid,
- "total_fee": "",
- "mch_id": self.mch_id
- }
- sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
- sign_str = f"{sign_str}&key={settings.pay_apikey}"
- import hashlib
- md5 = hashlib.md5()
- md5.update(sign_str.encode("utf-8"))
- sign = md5.hexdigest()
- return sign.upper()
- def get_body_data(self):
- self.appid = settings.AppId
- # openid=self.open_id
- self.mch_id = str(settings.pay_mchid)
- self.nonce_str = self.get_random()
- self.out_trade_no = self.order_id
- self.spbill_create_ip = self.ip
- self.notify_url = "https://www.test.com"
- self.body = "lzx"
- self.sign = self.get_sign()
- body_data = f"""
- <xml>
- <appid>{self.appid}</appid>
- <mch_id>{self.mch_id}</mch_id>
- <nonce_str>{self.nonce_str}</nonce_str>
- <sign>{self.sign}</sign>
- <body>{self.body}</body>
- <out_trade_no>{self.out_trade_no}</out_trade_no>
- <total_fee>1</total_fee>
- <spbill_create_ip>{ self.spbill_create_ip}</spbill_create_ip>
- <notify_url>{self.notify_url}</notify_url>
- <openid>{self.open_id}</openid>
- <trade_type>JSAPI</trade_type>
- </xml>"""
- return body_data
Wxpay
views
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from app01 import models
- from app01.my_ser import Banner_ser
- class List(APIView):
- def post(self,request):
- data = models.Banner.objects.filter(is_show=True).order_by("-w_order")
- data = Banner_ser.Banner_ser(instance=data,many=True,context={"request":request}).data
- return Response({
- "code":200,
- "msg":"ok",
- "data":data
- })
Banner
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from app01 import models
- from app01.my_ser import Category_ser
- from app01.comment import func
- class All(APIView):
- def post(self,request):
- data=models.Category.objects.filter(is_show=True)
- data=Category_ser.Category_ser(instance=data,many=True,context={"request":request}).data
- data=func.get_son(data)
- return Response({
- "code":200,
- "msg":"ok",
- "data":data
- })
Category
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from app01.my_ser import Goods_ser
- from app01 import models
- from app01.my_ser import Category_ser,Goods_ser
- from app01.comment import func
- class HotGoods(APIView):
- def post(self,request):
- data=models.Product.objects.filter(disabled=True).order_by("-buy_count","-w_order")
- data=Goods_ser.Goods_ser(instance=data,many=True,context={"request":request}).data
- return Response({"code":200,"msg":"ok","data":data})
- 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": "没有该商品"})
Goods
- import importlib
- 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']:
- if request.META.get("HTTP_X_FORWARDED_FOR"):
- host_ip = request.META["HTTP_X_FROWARDED_FOR"]
- else:
- host_ip = request.META["REMOTE_ADDR"]
- 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)
- pay_methon = "Wxpay"
- try:
- pay_file = importlib.import_module(f"app01.Pay.{pay_methon}")
- pay_class = getattr(pay_file,pay_methon)
- order_data['open_id'] = openid
- order_data['ip'] = host_ip
- data = pay_class().pay(order_data)
- except:
- transaction.savepoint_rollback(sid)
- return Response({"code": 202, "msg": "未知的支付方式"})
- transaction.savepoint_commit(sid)
- func.add_task(order_data['order_id'])
- return Response({"code": 200, "msg":"ok","data":data})
- else:
- return Response({"code": 202, "msg": "token已过期"})
- else:
- return Response({"code": 201, "msg": "缺少参数"})
- class Notity(APIView):
- def post(self,request,paymethon):
- pay_file = importlib.import_module(f"app01.Pay.{paymethon}")
- pay_class = getattr(pay_file, paymethon)
- data=pay_class().notity(request.data)
- if data['status']=="success":
- models.Order.objects.filter(order_id=data['order']).updata(pay_status=1)
Order
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from django.core.cache import cache
- from app01 import models
- import hashlib,time
- from app01.wx import wx_Login
- class Login(APIView):
- def post(self,request):
- param=request.data
- if param.get("code"):
- data=wx_Login.login(param.get("code"))
- if data:
- val=data['openid']+"&"+data["session_key"]
- key=str(int(time.time()))+data['openid']
- md5=hashlib.md5()
- md5.update(key.encode("utf-8"))
- key=md5.hexdigest()
- cache.set(key,val)
- has_user=models.Wxuser.objects.filter(openid=data['openid']).first()
- if not has_user:
- models.Wxuser.objects.create(openid=data['openid'])
- return Response({"code":200,"msg":"ok",'data':{"login_key":key}})
- else:
- return Response({"code":200,"msg":"code错误"})
- else:
- return Response({"code": 200, "msg": "缺少参数"})
User
wx
- import xadmin
- from xadmin import views
- from app01 import models
- class BaseSetting(object):
- """xadmin的基本配置"""
- enable_themes = True # 开启主题切换功能
- use_bootswatch = True
- xadmin.site.register(views.BaseAdminView, BaseSetting)
- class GlobalSettings(object):
- """xadmin的全局配置"""
- site_title = "商城后台" # 设置站点标题
- site_footer = "饼哥有限公司" # 设置站点的页脚
- menu_style = "accordion" # 设置菜单折叠
- xadmin.site.register(views.CommAdminView, GlobalSettings)
- xadmin.site.register(models.Order_items)
- xadmin.site.register(models.Product)
- xadmin.site.register(models.Order)
- xadmin.site.register(models.Category)
- xadmin.site.register(models.Stock)
- xadmin.site.register(models.Images)
- xadmin.site.register(models.Wxuser)
- xadmin.site.register(models.Banner)
adminx
- from django.db import models
- # Create your models here.
- '''
- #banner
- id
- image_url
- product_id
- is_show
- w_order
- create_time
- update_time
- #销量最高的排前面,销量一样,权重大的在前面
- #product_id
- id
- name
- price
- intor
- buy_count
- w_order (越大越前)
- detail
- image_url
- scort #库存
- is_show
- catory_id
- create_time
- update_time
- #scort库存
- id
- name
- num
- create_time
- update_time
- #category_id
- id
- cate_name
- image_url
- parent_id
- create_time
- update_time
- #imgae
- id
- imgae_url
- name
- create_time
- update_time
- #订单
- order_id
- 商品总数量
- 总价格
- 收货地址
- 用户id
- 订单状态(是否取消)
- 收货人电话
- 收人姓名
- 支付
- create_time
- update_time
- order_item
- id
- order_id
- 商品id
- 商品价格
- num
- image_url
- create_time
- update_time
- '''
- # Create your models here.
- class Wxuser(models.Model):
- id = models.AutoField(primary_key=True)
- openid=models.CharField(max_length=255)
- name = models.CharField(max_length=50)
- avatar = models.CharField(max_length=200)
- language = models.CharField(max_length=50)
- province = models.CharField(max_length=50)
- city = models.CharField(max_length=50)
- country = models.CharField(max_length=50)
- gender = models.CharField(max_length=50),
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.openid
- class Category(models.Model):
- cat_id=models.AutoField(primary_key=True)
- category_name=models.CharField(max_length=50)
- parent=models.ForeignKey(to='Category', to_field='cat_id', related_name="Category", on_delete=models.CASCADE, db_constraint=False,blank=True,null=True)
- p_order=models.IntegerField(default=0)
- is_show =models.BooleanField(default=1)
- image = models.OneToOneField(to='Images', to_field='image_id', on_delete=models.CASCADE, db_constraint=False,null=True)
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.category_name
- class Images(models.Model):
- image_id=models.AutoField(primary_key=True)
- name=models.CharField(max_length=30,default="")
- image_url=models.ImageField(upload_to="")
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.name
- class Product(models.Model):
- product_id=models.AutoField(primary_key=True)
- name=models.CharField(max_length=200)
- price=models.DecimalField(max_digits=10, decimal_places=2)
- weight=models.IntegerField(default=0)
- cat = models.ForeignKey(to="Category", to_field="cat_id", related_name="Product", db_constraint=False, on_delete=models.CASCADE)
- intor = models.TextField(max_length=250)#详细介绍
- brief = models.TextField(max_length=250)#商品简介
- image=models.OneToOneField(to='Images',to_field='image_id',on_delete=models.CASCADE,db_constraint=False)
- stock = models.OneToOneField(to="Stock", to_field="stock_id", db_constraint=False, on_delete=models.CASCADE)
- buy_count=models.IntegerField(default=0)#购买量
- disabled = models.BooleanField(default=1)#是否显示
- w_order=models.IntegerField(default=0)#权重
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.name
- 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
- class Order_items(models.Model):
- item_id = models.AutoField(primary_key=True)
- order= models.ForeignKey(to="Order", to_field="order_id", related_name="Order_items", db_constraint=False,on_delete=models.CASCADE)
- product=models.ForeignKey(to="Product", to_field="product_id", related_name="Order_items", db_constraint=False,on_delete=models.CASCADE,null=True)
- name = models.CharField(max_length=200)
- image = models.ForeignKey(to='Images', to_field='image_id',related_name="Order_items", on_delete=models.CASCADE,db_constraint=False)
- price = models.DecimalField(max_digits=10, decimal_places=2,default=0)
- amount=models.DecimalField(max_digits=10, decimal_places=2,default=0)
- nums=models.IntegerField()
- send_nums=models.IntegerField(null=True)
- brief=models.CharField(max_length=200)
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- class Stock(models.Model):
- stock_id=models.AutoField(primary_key=True)
- name=models.CharField(max_length=100)
- quantity=models.IntegerField(default=0)#库存量
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.name
- class Banner(models.Model):
- product = models.OneToOneField(to="Product", to_field="product_id", db_constraint=False, on_delete=models.CASCADE)
- w_order = models.IntegerField(default=0) # 权重
- image = models.OneToOneField(to='Images', to_field='image_id', on_delete=models.CASCADE, db_constraint=False)
- is_show =models.BooleanField(default=1)
- creat_time = models.DateTimeField(auto_now_add=True)
- update_time = models.DateTimeField(auto_now=True)
- def __str__(self):
- return self.product.name
models
pro_celery
- import celery
- import time
- # broker='redis://127.0.0.1:6379/2' 不加密码
- backend='redis://127.0.0.1:6379/1'
- broker='redis://127.0.0.1:6379/2'
- cel=celery.Celery('test',backend=backend,broker=broker)
- import os, sys
- import django
- BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # 定位到你的django根目录
- # sys.path.append(os.path.join(BASE_DIR, "app01"))
- sys.path.append(os.path.abspath(BASE_DIR))
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wxshop.settings")
- django.setup()
- from django.db import transaction
- @cel.task
- @transaction.atomic
- def del_order(order_id):
- '''
- 1 拿订单查询,订单号,是否支付,活跃
- 2 判断data是否有
- :param order_id:
- :return:
- '''
- from app01 import models
- data=models.Order.objects.filter(order_id=order_id,pay_status=0,status="active").first()
- if data:
- item_data=models.Order_items.objects.filter(order_id=order_id).values("product","nums")
- # [{product:1,nums:3}]
- # {1:3,2:1}
- all_product_dict = { k['product']:k['nums'] for k in item_data}
- all_product_id =list(all_product_dict.keys())
- products_all=models.Product.objects.filter(product_id__in=all_product_id)
- sid=transaction.savepoint()
- for product in products_all:
- for i in range(3):
- stock=product.stock.quantity
- new_stock=stock+all_product_dict[product.product_id]
- new_buy_count=product.buy_count-all_product_dict[product.product_id]
- res=models.Stock.objects.filter(quantity=stock,stock_id=product.stock).update(quantity=new_stock)
- if not res:
- if i==2:
- from app01.comment import func
- transaction.savepoint_rollback(sid)
- func.add_task(order_id,1)
- return
- else:
- continue
- else:
- break
- models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
- row=models.Order.objects.filter(order_id=order_id,pay_status=0).update(status="dead")
- if row:
- transaction.savepoint_commit(sid)
- else:
- transaction.savepoint_rollback(sid)
celery
wxshopapi2
- """
- Django settings for wxshopapi2 project.
- Generated by 'django-admin startproject' using Django 2.0.7.
- For more information on this file, see
- https://docs.djangoproject.com/en/2.0/topics/settings/
- For the full list of settings and their values, see
- https://docs.djangoproject.com/en/2.0/ref/settings/
- """
- import os
- # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
- BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- # Quick-start development settings - unsuitable for production
- # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
- # SECURITY WARNING: keep the secret key used in production secret!
- SECRET_KEY = '$v^um*l969ywfw2$3=rv5y&ehv$b@e#w&ha(%t!_+rv3=3#74n'
- # SECURITY WARNING: don't run with debug turned on in production!
- DEBUG = True
- ALLOWED_HOSTS = []
- # Application definition
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'app01.apps.App01Config',
- 'rest_framework',
- 'xadmin',
- 'crispy_forms',
- 'reversion',
- ]
- MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- ]
- ROOT_URLCONF = 'wxshopapi2.urls'
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- },
- ]
- WSGI_APPLICATION = 'wxshopapi2.wsgi.application'
- # Database
- # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'wxshop',
- 'USER':'root',
- 'PASSWORD':'',
- 'HOST':'127.0.0.1',
- 'PORT': 3306,
- 'OPTIONS': {'charset': 'utf8mb4'},
- }
- }
- # Password validation
- # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
- AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
- ]
- # Internationalization
- # https://docs.djangoproject.com/en/2.0/topics/i18n/
- LANGUAGE_CODE = 'zh-Hans'
- TIME_ZONE = 'Asia/Shanghai'
- USE_I18N = True
- USE_L10N = True
- USE_TZ = False
- # Static files (CSS, JavaScript, Images)
- # https://docs.djangoproject.com/en/2.0/howto/static-files/
- STATIC_URL = '/static/'
- STATICFILES_DIRS = [
- os.path.join(BASE_DIR,'static'),
- ]
- MEDIA_ROOT=os.path.join(BASE_DIR,'static/media')
- MEDIA_URL = '/static/media/'
- CACHES = {
- 'default': {
- 'BACKEND': 'django_redis.cache.RedisCache',
- 'LOCATION': 'redis://127.0.0.1:6379',
- "OPTIONS": {
- "CLIENT_CLASS": "django_redis.client.DefaultClient",
- },
- },
- }
settings
- """wxshop URL Configuration
- The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/2.0/topics/http/urls/
- Examples:
- Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: path('', views.home, name='home')
- Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
- Including another URLconf
- 1. Import the include() function: from django.urls import include, path
- 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
- """
- from django.contrib import admin
- from django.urls import path
- import xadmin
- xadmin.autodiscover()
- # version模块自动注册需要版本控制的 Model
- from xadmin.plugins import xversion
- xversion.register_models()
- from django.conf.urls import url
- from app01.views import User,Banner,Goods,Category,Order
- urlpatterns = [
- path(r'xadmin/', xadmin.site.urls),
- path('admin/', admin.site.urls),
- path("user/wxapp/login",User.Login.as_view()),
- path("banner/list",Banner.List.as_view()),
- path("hotgoods/list",Goods.HotGoods.as_view()),
- path("category/all",Category.All.as_view()),
- path("goods/list",Goods.List.as_view()),
- path("goods/detail",Goods.Detail.as_view()),
- path("order/create",Order.Creat.as_view()),
- ]
urls
day88_11_8,事务的隔离级别celery定时订单与项目整合。的更多相关文章
- SQL Server 之 事务与隔离级别实例讲解
SQL Server 之 事务与隔离级别实例讲解 SQL Server 实现了6个隔离级别来防止并发情况下,类似企图并发的访问或修改同一数据时问题的发生.本文将带你体验全部6个隔离级别.正如你接下来将 ...
- SQLServer 事务的隔离级别
SQLServer事务的隔离级别 数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务 ...
- Hibernate中事务的隔离级别设置
Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下
- MySQL事务学习-->隔离级别
MySQL事务学习-->隔离级别 6 事务的隔离级别 设置的目的 在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别. 数据库是要被广大客户所共享访问的,那么在数据库操作过程中 ...
- SQL Server事务的隔离级别
SQL Server事务的隔离级别 ########## 数据库中数据的一致性 ########## 针对并发事务出现的数据不一致性,提出了4个级别的解决方法: 隔离级别 第一类丢失更新 脏读 ...
- 事务的隔离级别及mysql对应操作
/* 本次高并发解决之道 1,更改事务隔离级别为 read uncommitted读未提交 2,查询前设定延迟,延迟时间为随机 50-500 微秒 3,修改数据前将 超范围作为 限定修改条件 事务是作 ...
- MySQL(26):事务的隔离级别出现问题之 幻读
1. 幻读 幻读(Phantom Read)又称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不重复读有些类型,同样是在两次查询过程中,不同的是,幻读是由于其他事务做了插入记录的操作,导致记 ...
- MySQL(25):事务的隔离级别出现问题之 不可重复读
1. 不可重复读 所谓的不可重复读(Non-Repeatable Read)是指事务中两次查询的结果不一致,原因是在查询的过程中其他事务做了更新的操作. 例如,银行在做统计报表的时候,第一次查询a账户 ...
- MySQL(24):事务的隔离级别
1. 事务的隔离级别引入: 数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样的就会出现脏读.重复读以及幻读的情况.在数据库操作中,为了有效保证并发读取数据的正确性,需要为事务设 ...
随机推荐
- Prometheus学习系列(六)之Prometheus 查询说明
前言 本文来自Prometheus官网手册和 Prometheus简介 Prothetheus查询 Prometheus提供一个函数式的表达式语言PromQL (Prometheus Query La ...
- asp.net core的AOP记录
序曲:学习编程最好的方式就是敲代码,没有比这个更好的方法,哪怕你看了上百G的视频,都不如你自己敲几行代码更为有效.还有要记得敲完代码然后写一篇随笔来记录一下你所学所想. 什么叫AOP? AOP面向切面 ...
- .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项目使用一般处理程序变成了中间件 ...
- PlayJava Day025
JTable 用JTable类可以以表格的形式显示和编辑数据 JTable类的对象并不存储数据,它只是数据的表现 MVC 数据.表现和控制三者分离,各负其责 M = Model(模型) V = Vie ...
- php 将科学计算法得出的结果转换成原始数据 NumToStr
由于php最大只支持显示 15位因的数据运算,大于15位的2数加减乘除的数据的结果,会直接用科学计数法显示, 但在现实生活中,科学计数法不利于普通人识别,所以,本函数将:科学计数法的出的结果转换成原始 ...
- dedecmsV5.7 百度编辑器ueditor 多图上传 在线管理 排序问题
问题:dedecms后台百度编辑器ueditor的多图上传-在线管理的图片排序有问题,想把这个顺序调成按照文件修改时间倒序来展示 解决方法: 1.打开/include/ueditor/php/acit ...
- 通过U盘在物理机安装CentOS出现Timeout的问题
错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.
- PWA 学习笔记(五)
离线与缓存 资源请求的拦截代理: 1.资源请求的判断: (1)fetch 事件会拦截页面上所有的网络资源请求,但我们通常只对部分资源请求进行处理, 其余的请求会继续走浏览器默认的资源请求流程 (2)f ...
- Cocos2d-x.3.0开发环境搭建
配置:win7 + VS2012 + Cocos2d-x.3.0 + Cocos Studio v1.4.0.1 前言:本文介绍在上述配置下进行游戏开发的环境搭建.开发语言为C++.如果读者不需要查看 ...
- Violet 6 杯省选模拟赛 蒲公英
https://www.luogu.com.cn/problem/P4168 题目 给$n$个数字,有$m$次询问,问$a_l, a_{l+1} , \dots , a_r$的众数是什么, $1\le ...