递归与树的写法-多种支付的设计-支付的接通-celery订单的回退实现

递归与树的写法

data:

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},
]
#需求
'''
问题:
我们数据不是有序的,但是我们要排序,并归类,把父集放在子集的前面,辈分等级通过level标明

'''

 实现的方法

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

实现树状的等级分类

'''
问题:

因为前端,需要通过循环多少成来,展示多个等级
for item in data:
    print(item.name)
    for item1 in item.children 
        item1.name
        
归档:我要把我的子集,都放在我的children列表里面
         
'''
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

分析

 多种支付的设计

  例如实现微信或支付宝等支付接口的封装.

 

封装的支付接口方法

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)

pay.Alipay.py

class Alipay():
    def pay(self):
        pass
        "order/notify/Alipay"

    def notity(self,data):
        data['shangcheng_id']
        data['sucess']
        if data['sucess']="00":
            return_data['stauts']="success"
            return_data['order_id'] = data['shangcheng_id']
            return  return_data
        else:
            pass

pay.Wxpay.py

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

 支付的接通

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 django.db import transaction

from django import forms
import importlib

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.savepoint_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.savepoint_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.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": 200, "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":"缺少参数"})

celery实现订单的回退

  简单的理解就是通过celery异步回调的机制,设置代码段过多少时间之后再去工作,把发起订单后为支付的数据信息返回。

task方法:

from pro_celery.celery import del_order
def add_task(order_id,seconds=5):
    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)

celery.py方法的封装

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)

 

原文地址:https://www.cnblogs.com/Gaimo/p/11830626.html