電商項目(賣家/買家)
一、加入購物車
- 加入購物車
- 獲取商品id,數量,寫入購物車
- 購物車結算
- 首先生成訂單
- 支付寶付款
- 修改訂單的狀態
購物車模型
# 購物車表
class Cart(models.Model):
goods_number = models.IntegerField(verbose_name='商品數量')
goods_price = models.FloatField(verbose_name='商品單價')
goods_total = models.FloatField(verbose_name='商品總價')
goods = models.ForeignKey(to=Goods,on_delete=models.CASCADE)
cart_user = models.ForeignKey(to=LoginUser,on_delete=models.CASCADE)
(一)添加購物車
1.列表頁添加購物車
使用前端列表中的購物車圖標,添加商品到購物車。
因爲不需要跳轉頁面,不需要刷新頁面,所以使用ajax提交,視圖返回json對象
- 前端傳遞參數
- 需要傳遞添加的商品id
- 不需要傳遞商品的數量,每次點擊都是添加一個商品到購物車
- 視圖接口接收參數
- 商品id
- 商品數量
- 給默認值,因爲在前端商品列表頁的添加按鈕,每次添加都是添加一個
- 保存數據到購物車表
- 確定具體添加的商品
- 確定用戶
- 確定商品數量
視圖
# 添加購物車
def add_cart(request):
'''
使用post請求,完成添加購物車功能
'''
result = {'code':'10000','msg':''}
if request.method=='POST':
goods_id = request.POST.get('goods_id')
count = int(request.POST.get('count','1')) # 默認值1
user_id = request.COOKIES.get('userid')
goods = Goods.objects.get(id=goods_id)
cart = Cart()
cart.goods_number = count
cart.goods_price = goods.goods_price
cart.goods_total = goods.goods_price*count
cart.goods = goods
cart.cart_user = LoginUser.objects.get(id=user_id)
cart.save()
result['msg']='成功加入購物車'
else:
result['code']=10001
result['msg']='請求方式不正確'
return JsonResponse(result)
模板
{% block script %}
<script>
function add_cart(obj) {
var goods_id = obj.id;
url='/Buyer/add_cart/';
send_data={
'goods_id':goods_id ,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:'post',
data:send_data,
success:function (data) {
alert(data['msg'])
},
error:function (error) {
console.log(error)
}
}
)
}
</script>
{% endblock %}
路由
2.商品詳情頁添加購物車
商品詳情頁添加購物車跟列表頁相似,可以使用同一個視圖,同一個路由
模板內的js也相似,不過就是商品詳情頁需要傳遞具體商品的數量
模板
function add_cart(obj) {
var goods_id = obj.id;
url='/Buyer/add_cart/';
var count=$('#num').val();
send_data={
'goods_id':goods_id ,
'count':count,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:'post',
data:send_data,
success:function (data) {
alert(data['msg'])
},
error:function (error) {
console.log(error)
}
}
)
}
二、購物車頁面
使用模板:cart.html
顯示登錄用戶購物車中所有的商品
(一)設置選中商品的多選框
模板
$('#boxall').click(
function () {
// this.checked:布爾類型,代表this指向的#boxall對象有沒有checked屬性
if(this.checked){
// 選中時,添加goods_check的checked屬性
$('.goods_check').prop('checked',true)
}
else{
// 不選中時,去掉goods_check的checked屬性
$('.goods_check').prop('checked',false)
}
}
);
$('.goods_check').each(
function () {
$(this).click(
function () {
if(!this.checked){
$('#boxall').prop('checked', false)
}
}
)
}
);
路由
視圖
@loginValid
def cart(request):
user_id = request.COOKIES.get('userid')
carts = Cart.objects.filter(cart_user_id=user_id,).order_by('-id') # 晚添加的在上面
count = carts.count()
return render(request,'buyer/cart.html',locals())
(二)根據勾選的多選框,計算總數量,總價格
模板
function add() {
var dic = {num:0,total:0};
$('.goods_check').each(
function () {
if(this.checked){
// 數量
var num =parseInt($(this).parents('.cart_list_td').find('.num_show').val()) ;
// 小計
var total =parseFloat($(this).parents('.cart_list_td').find('.col07').text());
dic.num+=num;
dic.total+=total;
}
}
);
$('#total_mount').text(dic.total);
$('#total_num').text(dic.num);
}
三、提交購物車–加入訂單
購物車(多件商品),需要通過結算,先產生訂單,然後跳轉支付
(一)生成訂單
- 能夠處理多條商品,錄入訂單
- 接收的參數:
- goods_id–需要從前端獲取
- count–需要從前端獲取
模板
這樣,前端傳遞的數據格式,是這樣的:
goods_13=on type = checkbox 有checked屬性的時候纔會傳遞
count_17=1
count_13=1
count_11=1
路由
視圖
需要處理獲取的數據,並且存入訂單狀態表和訂單詳情表
def place_order_more(request):
data=request.GET
userid = request.COOKIES.get('userid')
# 通過獲取前端get請求的參數,找到goods_id和對應的數量
request_data=[]
for key,value in data.items():
if key.startswith('goods'):
goods_id = key.split('_')[1]
count = request.GET.get('count_'+goods_id)
request_data.append((int(goods_id),int(count)))
if request_data:
payorder = PayOrder()
order_number = str(time.time()).replace('.', '')
payorder.order_number = order_number
payorder.order_status = 0
payorder.order_total = 0
order_total = 0
total_count = 0
payorder.order_user = LoginUser.objects.get(id=userid)
payorder.save()
for goods_id_one,count_one in request_data:
goods = Goods.objects.get(id=goods_id_one)
orderinfo = OrderInfo()
orderinfo.order_id_id = payorder.id
orderinfo.goods = goods
orderinfo.goods_count = count_one
orderinfo.goods_price = goods.goods_price
orderinfo.goods_total_price = goods.goods_price * count_one
orderinfo.store_id = goods.goods_store
orderinfo.save()
order_total+=orderinfo.goods_total_price
total_count+=count_one
payorder.order_total=order_total
payorder.save()
return render(request,'buyer/place_order.html',locals())
(二)跳轉支付頁面並修改訂單狀態
無需修改
模板
payresult.html
{% extends 'buyer/base.html' %}
{% block title %}
支付結果
{% endblock %}
{% block content %}
<div class="list_model">
<h1>支付結果</h1>
<table>
{% for key,value in request.GET.items %}
<tr>
<th>{{ key }}:</th>
<td>{{ value }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
路由
視圖
def AlipayView(request):
order_id=request.GET.get('order_id') # 訂單ID
payorder=PayOrder.objects.get(id=order_id)
# 實例化支付對象
alipay = AliPay(
appid='2016101300673951',
app_notify_url=None,
app_private_key_string=alipay_private_key_string,
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA2",
)
# 實例化訂單
order_string = alipay.api_alipay_trade_page_pay(
subject='天天生鮮', # 交易主題
out_trade_no=payorder.order_number, # 訂單號
total_amount=str(payorder.order_total), # 交易總金額
return_url='http://127.0.0.1:8000/Buyer/payresult/', # 請求支付之後及時回調的一個接口
notify_url='http://127.0.0.1:8000/Buyer/payresult/' # 通知地址
)
# 發送支付請求
# 請求地址:支付網關+實例化訂單
result = 'https://openapi.alipaydev.com/gateway.do?' + order_string
return HttpResponseRedirect(result)
def payresult(request):
order_number = request.GET.get('out_trade_no')
payorder = PayOrder.objects.get(order_number=order_number)
payorder.order_status=1
payorder.save()
return render(request,'buyer/payresult.html',locals())
三、購物車優化
不顯示已提交訂單並付款的商品
1.購物車表中增加訂單號字段,與訂單表產生聯繫
就可以使用訂單表中的訂單狀態
進行數據遷移
2.使生成訂單時,多傳遞一個參數:購物車id
爲訂單相關產品增加訂單號
修改place_order_more視圖
3.就可以通過訂單號,查看當前訂單狀態了
若訂單時已付款狀態,則不顯示在購物車當中
修改cart視圖
@loginValid
def cart(request):
user_id = request.COOKIES.get('userid')
carts = Cart.objects.filter(cart_user_id=user_id,).order_by('-id') # 晚添加的在上面
cart_list = []
for one in carts:
# 說明有訂單號
if one.order_number != '0':
payorder = PayOrder.objects.get(order_number=one.order_number)
if payorder.order_status == 0:
cart_list.append(one)
else:
cart_list.append(one)
count = len(cart_list)
return render(request,'buyer/cart.html',locals())
修改cart.html模板
四、用戶中心全部訂單頁
獲取用戶的全部訂單
視圖
@loginValid
def user_center_order(request):
user_id = request.COOKIES.get('userid')
user = LoginUser.objects.get(id=user_id)
payorder = user.payorder_set.order_by('-order_date','order_status')
return render(request,'buyer/user_center_order.html',locals())
路由
模板
修改模型
user_center_order.html
{% extends 'buyer/base.html' %}
{% block title %}
全部訂單
{% endblock %}
{% block content %}
<div class="main_con clearfix">
<div class="left_menu_con clearfix">
<h3>用戶中心</h3>
<ul>
<li><a href="/Buyer/user_center_info/">· 個人信息</a></li>
<li><a href="/Buyer/user_center_order/" class="active">· 全部訂單</a></li>
<li><a href="">· 收貨地址</a></li>
</ul>
</div>
<div class="right_content clearfix">
<h3 class="common_title2">全部訂單</h3>
{% for order in payorder %}
<ul class="order_list_th w978 clearfix">
<li class="col01">{{ order.order_date }}</li>
<li class="col02">{{ order.order_number }}</li>
<li class="col02 stress">{{ order.get_order_status_display }}</li>
</ul>
<table class="order_list_table w980">
<tbody>
<tr>
<td width="55%">
{% for orderinfo in order.orderinfo_set.all %}
<ul class="order_goods_list clearfix">
<li class="col01"><img src="/static/{{ orderinfo.goods.picture }}"></li>
<li class="col02">{{ orderinfo.goods.goods_name }}<em>{{ orderinfo.goods_price }}/500g</em></li>
<li class="col03">{{ orderinfo.goods_count }}</li>
<li class="col04">{{ orderinfo.goods_total_price }}元</li>
</ul>
{% endfor %}
</td>
<td width="15%">{{ order.order_total }}元</td>
<td width="15%">{{ order.get_order_status_display }}</td>
{% if order.order_status == 0 %}
<td width="15%"><a href="/Buyer/alipayview/?order_id={{ order.id }}" class="oper_btn">去付款</a></td>
{% elif order.order_status == 1 %}
<td width="15%"><a href="" class="oper_btn">查看訂單</a></td>
{% endif %}
</tr>
</tbody>
</table>
{% endfor %}
<div class="pagenation">
<a href="#"><上一頁</a>
<a href="#" class="active">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<a href="#">下一頁></a>
</div>
</div>
</div>
{% endblock %}