Django 18购物商城项目(支付功能完善、订单页面返回按钮、城市级联查询)

1、支付功能完善

1.1、向支付宝支付页面传递支付信息

order_detail.html (把get请求改成了post请求)
在这里插入图片描述

        <form method="POST" enctype="multipart/form-data" action="{% url 'axf:alipay' %}">
            {% csrf_token %}
            <input name="orderid" type="hidden" value="{{ order.id }}">
            <button type="submit" orderid="{{ order.id }}" id="alipay" class="btn btn-success btn-block">支付</button>
        </form>

order_detail.js (直接post请求,不需要点击事件了,所以里面的内容都注解了)
在这里插入图片描述

1.2、pay.py修改

因为视图里需要用到AliPay的相关信息,所以把这部分数据单独封装成了一个函数,下面是pay.py里面的全部内容。
(同样注意,这里的两个密钥用你自己的,不要复制我的,复制我的用不了的)

from alipay import AliPay


def pay(order_id, price, subject, return_url=None, notify_url=None):

    # 发起支付请求
    order_string = my_alipay().api_alipay_trade_page_pay(
        out_trade_no=order_id,  # 订单号,多次请求不能一样
        total_amount=str(price),  # 支付金额
        subject=subject,  # 交易主题
        return_url=return_url,
        notify_url=notify_url
    )

    # return_url支付成功后 - 重定向到自己的网站
    # notify_url支付成功后 - 异步发送支付结果到回调地址(地址需是服务器地址,否则无法接收到回调结果)
    # return_url中最终需要返回 "success" 字符给支付宝,否则支付宝将一直请求该地址并发送回调结果
    # notify_url支付前首先执行的,
    return "https://openapi.alipaydev.com/gateway.do?" + order_string


def my_alipay():

    alipay_public_key_string = """-----BEGIN PUBLIC KEY-----
    MIfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB
    -----END PUBLIC KEY-----"""

    app_private_key_string = """-----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQCgaYHnBs4xmVUeJ06Wncybr4OOu0svQbD/g7kfud2aMPoB3UETNWs0lxu2CtzvdlUtLFSQSI2QfVeB2fVULILUzyh0HCHMa11/hdAuXBYOTP4Xhe5QlGUTNpBJjqLKsFxLc3PmVptHHRtHlhfdF4NOLdbPfBEB8Fw2oyTo2RhbwIDAQABAoGBAJRXvbemBXy8rYhLFVQX7aVztBeEgMzc1RAWAlaijZoP/MNIlutqlQ93Rjsc5J/WMIKr4i/jyHZ7GoOQGaedDmgORxhw2ji29vgKllsuHzAD5/JzFLIr4T1N//bU6gb7DbTml7dHyEHDLg/nsPVZFmKNg7h3SudPMnpobNPfi4eBAkEA3pTFkd7yzs60Bl559y2UHwYmMFPxmgNJspsVtynv4LS+Fb5a4xDJrMeAjJt16UGE4Xm1669jd5ReckHD7ddUTwJBALh/Lh1BYEYdTXANtIjSPOvKh7Jgc44aQ3nCQP92imwmvI3zIVlnXEXIVVNc1k6dzA1Ppgj8jBMAuLYItn+uOOECQQDU4oIcxJqDRpxUwyPwT/2ttpnr+z3HSoHAfChG6atuxjBQZ6JSLwpVYPMIiOA72tiXN2vSIgwGoTe8HD6jSyJtAkAEtmrtIGBfKhxyQkdcP1KDC1dP/Rq2hIE4uPeEDvkWLh8e2Rj++Z7nwWg8iuCGfY1awbASBrFlQt10+OAAfujBAkBJHaKdVyVmdK9Xqdb4IOopO511kOSIQBZwPnfgkFdBpRrPF+Bt4ROxBi9hP5UwKosONAhi508L5QZDgkgPht2w
    -----END RSA PRIVATE KEY-----"""

    # 实例化支付应用
    alipay = AliPay(
        appid="20161021007289",
        app_notify_url=None,
        app_private_key_string=app_private_key_string,
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA",

    )
    return alipay

1.3、路由、视图

路由
在这里插入图片描述
视图
在这里插入图片描述

# 跳转去支付页面
def alipay(request):
    if request.method == "POST":
        order_id = request.POST.get("orderid")
        print(order_id)
        order = Order.objects.get(pk=order_id)
        O_price = order.O_price
        O_user = order.O_user.u_name
        return redirect(pay(order_id,O_price, O_user, return_url='http://127.0.0.1:8000/axf/payreturn'))


# 支付成功后执行
def pay_return(request):
    # 支付成功后的回调函数 -- 重定向自己的网站
    # 同时在重定向之前会校验此次支付信息是否正确

    params = request.GET.dict()
    # 获取字典里的'sign'的值,然后移除这个数据
    sign = params.pop('sign', None)
    alipay = my_alipay()
    status = alipay.verify(params, sign)  # 返回 True or False
    if status:
        order_id = params.get('out_trade_no')
        order = Order.objects.get(pk=order_id)
        order.O_status = ORDER_STATUS_NOT_SEND
        order.save()
        data = {
            'status': 200,
        }
        # 支付成功
        return redirect(reverse('axf:mine'))

    return HttpResponse('支付失败')

1.4、下单支付测试截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
成功支付,并把订单状态信息存入数据库

2、订单页面返回按钮

base_order.html
在这里插入图片描述
base_order.css

/*目前此css为止所有内容*/

header {
    height: 1.5rem;
    width: 100%;
    background: yellow;
    margin-bottom: 0.3rem;
    text-align: center;
    line-height: 1.5rem;
    position: fixed;
    z-index: 10;
    border-top: 1px solid #f0f0f0;
}

.back {
    background: url(/static/img/back.png) no-repeat;
    background-size: 0.6rem;
    margin-top: 0.5rem;
    margin-left: 0.6rem;
    height: 1rem;
    z-index: 100;
    position: fixed;
}

.back > span {
    margin-top: 0.9rem;
    margin-left: 0.6rem;
}

效果
在这里插入图片描述

3、收货地址

3.1、创建全国地名表

数据下载地址:https://pan.baidu.com/s/1ZqAjTw9FznavKGiy3Wqtog
提取码:roa7 

里面有单表和多表,我们仅需要单表数据
在这里插入图片描述

3.1.1、建表pro_city_area

模型(mondels.py)

# 全国地名表
class City(models.Model):
    id = models.IntegerField(primary_key=True, max_length=11)
    name = models.CharField(max_length=40)
    pid = models.IntegerField(max_length=11)

    class Meta:
        db_table = 'pro_city_area'

迁移:

python manage.py makemigrations
python manage.py migrate
3.1.2、插入城市信息数据

在这里插入图片描述
把表里所有的数据复制进去并运行(仅复制插入语句)
在这里插入图片描述
插入后查看表
在这里插入图片描述

3.1.2、表的结构
  • pid
    省级城市:pid为0
    市级:pid除以10000为整数
    区级:pid除以100为整数
  • id
    省级id = 市级pid+省序号(万位上加)
    市级id = 区级pid+市序号(百位上加)
    区级id = 区级pid+区序号(个位上加)
    在这里插入图片描述在这里插入图片描述
3.1.3、查询(测试城市能否正确展示并记录)

查表思路:

查询 思路
所有省级 直接查pid=0的
对应的市级城市有哪些 省级的id=市级的pid
对应的区级城市有哪些 市级的id=区级的pid

3.2、城市级联查询的实现

order_addr.html(新建的,注意路径)
在这里插入图片描述

{% extends "bese_order.html" %}
{% load static %}

{% block ext_css %}
    {{ block.super }}
    <link rel="stylesheet" href="{% static 'axf/order/css/order_addr.css' %}">
{% endblock %}

{% block ext_js %}
    {{ block.super }}
    <script type="text/javascript" src="{% static 'axf/order/js/order_addr.js' %}"></script>
{% endblock %}

{% block footer %}
    <div class="title">
        <a href="#" onclick="javascript:history.back(-1);">
            <div class="arrow-box nav-left">
                返回
            </div>
        </a>
        <p class="font">编辑收货地址</p>
    </div>
{% endblock %}
{% block content %}
    <div class="container">

        <form method="POST" action="{% url 'axf:order_addrPCA' %}" class="bs-example bs-example-form" role="form">
            {% csrf_token %}
            <div class="input-group">
                <span class="input-group-addon">收货人:</span>
                <input name="order_name" type="text" class="form-control" placeholder="">
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon">&nbsp;&nbsp;&nbsp;&nbsp;话:</span>
                <input nam="order_tell" type="text" class="form-control" placeholder="">
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon">收货时间:</span>
                <input name="oder_time" type="text" class="form-control" placeholder="1">
                <span class="input-group-addon">小时后收货</span>
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon">收货地址:</span>
                <select id="p">
                    <option value="1">请选择</option>
                </select>
                <select id="c">
                    <option value="1">请选择</option>
                </select>
                <select id="a">
                    <option value="1">请选择</option>
                </select>
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon">详细地址:</span>
                <input id="addr_dail" name="order_detail" type="text" class="form-control" placeholder="">
            </div>
            <br>
            <div>
                <span id="checkbox">默认地址<input name="is_default" type="checkbox"></span>
            </div>
            <br>
            <br>
            <button type="submit" class="btn btn-success btn-block">保存</button>
        </form>
    </div>
{% endblock %}

order_addr.css(新建的)
在这里插入图片描述

.title {
    width: 100%;
    height: 50px;
    background-color: #009688;
}

.font {
    color: #fff;
    line-height: 50px;
    font-size: 20px;
    text-indent: -2em;
    text-align: center
}

.nav-left {
    float: left;
}

.arrow-box{
    width: 50px;
    height: 26px;
    position: relative;
    border-radius: 10% 10%;
    background: #fff;
    text-align: center;
    line-height: 26px;
    top: 12px;
    font-size: 14px;
    left: 10px;
}

.container {
    padding: 2rem 0.5rem;
    overflow: auto;
    height: 100%;
    width: 100%;
    position: fixed;
}
.input-group-addon{
    font-size: 10px;
}
#p,#c,#a{
    width: 33.3%;
    padding: 6px 0px;
    font-size: 10px;
    font-weight: normal;
    line-height: 1;
    color: #555;
    text-align: center;
    background-color: #eee;
    border: 1px solid #000000;
    border-radius: 4px;
}
input[type="checkbox"]{
    margin-left: 0.2rem;
    margin-top: 0;
    height: 0.5rem;
    width: 0.5rem;
}
#checkbox{
    float: right;
    margin-right: 0.4rem;
}

order_addr.js(新建的,级联查询实现代码重点在里面)
在这里插入图片描述

$(function () {
    var $p = $('#p');
    var $c = $('#c');
    var $a = $('#a');
    // 点击p时获取省级城市名单
    $.get("/axf/PCA/", {"p": 0}, function (data) {
        console.log(data['ps_all']);
        var ps_all = data['ps_all'];
        for (var i = 0; i < ps_all.length; i++) {
            $p.append('<option value="' + ps_all[i][0] + '">' + ps_all[i][1] + '</option>');
            $c.hide();
            $a.hide();
        }
    });
    // p发生变化就移除c、a中的值,并获取新的
    $p.change(function () {
        if ($("#p option:selected").val() == 1) {
            $c.hide();
            $a.hide();
            $("#addr_dail").val('');
        } else {
            $c.children().not(':eq(0)').remove();
            $c.show();
            $a.children().not(':eq(0)').remove();
            $a.hide();
            c_pid = $("#p option:selected").val();
            console.log(c_pid);
            // 返回选中数据
            $.get("/axf/PCA/", {"c_pid": c_pid}, function (data) {
                var cs_all = data['cs_all'];
                for (var i = 0; i < cs_all.length; i++) {
                    $c.append('<option value="' + cs_all[i][0] + '">' + cs_all[i][1] + '</option>');
                    p_dail = $("#p option:selected").text();
                    $("#addr_dail").val(p_dail);
                }
            });
        }
    });
    // c发生变化就移除a中的值,并获取新的
    $c.change(function () {
            if ($("#c option:selected").val() == 1) {
                $a.hide();
                $("#p option:selected").val();
                $("#addr_dail").val(p_dail);
            } else {
                $a.children().not(':eq(0)').remove();
                a_pid = $("#c option:selected").val();
                console.log(a_pid);
                // 返回选中数据
                $.get("/axf/PCA/", {"a_pid": a_pid}, function (data) {
                    var as_all = data['as_all'];
                    if (as_all.length > 0) {
                        $a.show();
                        for (var i = 0; i < as_all.length; i++) {
                            $a.append('<option value="' + as_all[i][0] + '">' + as_all[i][1] + '</option>');
                            p_dail = $("#p option:selected").text();
                            c_dail = $("#c option:selected").text();
                            $("#addr_dail").val(p_dail + c_dail);
                        }
                    }
                });
            }
        });
    // a发生变化时,将p\c\a中的城市地名设为详细地址的值
    $a.change(function () {
        if ($("#a option:selected").val() == 1) {
            $("#p option:selected").val();
            $("#c option:selected").val();
            $("#addr_dail").val(p_dail+ c_dail);
        } else {
            p_dail = $("#p option:selected").text();
            c_dail = $("#c option:selected").text();
            a_dail = $("#a option:selected").text();
            $("#addr_dail").val(p_dail + c_dail + a_dail);
        }
    });
});

路由:
在这里插入图片描述
视图:
在这里插入图片描述

# p省级城市、c市级城市、a区县级城市
def order_addrPCA(request):
    data = {}
    if request.method == "GET":
        return render(request, 'order/oder_addr.html', context=data)
    else:
        return render(request, 'order/oder_addr.html', context=data)

# oder_addr.html的异步请求
def PCA(request):
    data = {}
    if request.GET.get("p"):
        ps = City.objects.filter(pid=0)
        ps_all = []
        for p in ps:
            temp = []
            temp.append(p.id)
            temp.append(p.name)
            ps_all.append(temp)
        data['ps_all'] = ps_all

    elif request.GET.get("c_pid"):
        cs = City.objects.filter(pid=request.GET.get("c_pid"))
        cs_all = []
        for c in cs:
            temp1 = []
            temp1.append(c.id)
            temp1.append(c.name)
            cs_all.append(temp1)
        data['cs_all'] = cs_all
    elif request.GET.get("a_pid"):
        a_s = City.objects.filter(pid=request.GET.get("a_pid"))
        as_all = []
        for a in a_s:
            temp2 = []
            temp2.append(a.id)
            temp2.append(a.name)
            as_all.append(temp2)
        data['as_all'] = as_all

    return JsonResponse(data)
发布了87 篇原创文章 · 获赞 20 · 访问量 1619

猜你喜欢

转载自blog.csdn.net/a__int__/article/details/103788649