购物车页面如下:
购物车表cart_line主要存储了如下的几个字段(还包括一些其它的字段)
id
count :产品的数量
product_product_id :产品id
product_hot_item_id :
res_partner_id:用户id
1. 点击加入购物车时,向后台发请求,后台根据前台传递的参数从数据库对应的表中读取相应的信息,然后 插入到cart_line表中(如果购物车中已经存在该商品,则改变cart_line中对应表的数量,否则新创建一个订单插入到购物车中)
前台请求的js代码大致如下:
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: params,
id: undefined
};
$.ajax({
type : 'POST',
url : "/shop/cart_line/add",
contentType : 'application/json',
dataType : 'json',
data : JSON.stringify(jsonp),
success : function(data){
$.unblockUI();
if (data.status == 200) {
var $q = $(".my_cart_quantity");
$q.parent().parent().removeClass("hidden");
var origin_quantity = parseInt($q.html());
var updated_quantity = product_quantity;
if (!isNaN(origin_quantity))
updated_quantity = (origin_quantity - 0) + (product_quantity - 0);
$q.html(updated_quantity).hide().fadeIn(600);
}
},
error : function(data){
alert('加入购物车失败!')
$.unblockUI();
},
})
2. 购物车的页面
(1) 购物车的页面初始化时会将cart_line中的每一行都读取出来然后显示在页面中,主要的js函数如下:
$scope.getCart = function () {
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: {},
id: undefined
};
$http.post("/shop/cart_line/view", jsonp).success(function (data) {
$scope.order = data;
$scope.result = data.result;
$scope.amount_total = 0;
$scope.total_num=0;
$scope.select_num=0;
$scope.primaryType = [];
if($scope.result.uid !== 3){
data.result.items.forEach(function (value) {
var o = {};
var t = value.items;
o.number = t.count;
o.image_small = t.image_url;
o.with_context = t.name_template;
o.hot_item_id = t.product_hot_item_id;
o.product_id = t.product_product_id;
o.lst_price = t.price;
o.attritubes = t.attritubes;
if(t.product_hot_item_id)
o.href = '/shop/product/' + t.product_hot_item_id;
else
o.href = '/ourShop/product/' + t.product_tmpl_id;
o.item_status = true;
//$scope.isfavo(o);//收藏功能,暂不使用
$scope.primaryType.push(o);
$scope.total_num += o.number;
$scope.amount_total += o.lst_price * o.number;
$scope.select_num += 1;
});
$scope.amount_total = $scope.amount_total.toFixed(2);
$('.oe_cart').css('display','block');
}
else
$('#oe_cart_public').css('display','block');
});
};
(2)改变购物车页面中的商品数量
<div class="tc-amount">增加数量时,向后台发请求,后台根据product_id从cart_line中找到对应的商品并改变其数量 ,重新从cart_line中读取数据,利用angularjs更新页面。
<span class="input-group-addon">
<a ng-click="sub_item(line)" class="js_add_order_line_json">
<i class="glyphicon glyphicon-minus"></i>
</a>
</span>
<input type="text" class="tc-text amount" ng-model="line.number" ng-binding="line.number" ng-change="new_item_num(line, '{{line.number}}')" />
<span class="input-group-addon">
<a ng-click="add_item(line)" class="js_add_order_line_json">
<i class="glyphicon glyphicon-plus"></i>
</a>
</span>
</div>
$scope.add_item = function (ev) {
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: {
product_hot_item_id: ev.hot_item_id,
product_id: ev.product_id,
count: 1
},
id: undefined
};
$http.post("/shop/cart_line/add", jsonp).success(function (data) {
$scope.getCart();
});
};
减少数量时的逻辑同增加数量相似,有一点是若当前商品的数量为1,减少为0后,后台需要从cart_line表中删除对应的产品。
$scope.sub_item = function (ev) {
if (ev.number < 1)return;
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: {
product_hot_item_id: ev.hot_item_id,
product_id: ev.product_id,
count: 1
},
id: undefined
};
$http.post("/shop/cart_line/sub", jsonp).success(function (data) {
$scope.getCart();
});
};
(3)选中或不选中购物车中的某个商品时,相应的总价随着改变。
在复选框上利用ng-model绑定一个状态值item_status,使其随着复选框的选中状态而改变,当复选框选中时,item_status变为true,反之变为false.然后利用ng-click绑定一个 点击事件 ng-click="checked()" checked()函数中对所有的商品进行循环计算总价,如果某个产品的item_staus为false,那么该商品不会被用于计算总价
<td class="check_item">
<input type="checkbox" ng-model="line.item_status" ng-change="checked()"></input>
</td>
$scope.checked = function () {$scope.amount_total = 0;$scope.select_num = 0;$scope.all_item_status = true;$scope.primaryType.forEach(function (value) {if (value.item_status == false)$scope.all_item_status = false;$scope.amount_total += (value.item_status == true ? 1 : 0) * value.number * value.lst_price;$scope.select_num += value.item_status == true ? 1 : 0;});$scope.amount_total = $scope.amount_total.toFixed(2);};全选或全不选的逻辑实现如下:
<div class="sele_all">
<input type="checkbox" ng-model="all_item_status" ng-change="all_checked(all_item_status)"> 全选</input>
</div>
$scope.all_checked = function (ev) {$scope.amount_total = 0;$scope.select_num = 0;$scope.primaryType.forEach(function (value) {value.item_status = ev;$scope.amount_total += (value.item_status == true ? 1 : 0) * value.number * value.lst_price;$scope.select_num += value.item_status == true ? 1 : 0;});$scope.amount_total = $scope.amount_total.toFixed(2);};value.item_status = ev; 这一行代码即让每个商品对应的复选框随着全选或全不选按钮的状态而改变。
(4)删除购物车商品,对于每一个商品向后台发请求,删除cart_line中的该商品
$scope.del_allitem = function () {
if($scope.all_item_status)
{
$scope.primaryType.forEach(function (value) {
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: {
product_hot_item_id: value.hot_item_id,
product_id: value.product_id,
count: value.number
},
id: undefined
};
$http.post("/shop/cart_line/sub", jsonp).success(function (data) {
});
});
$window.location = "/shop/cart";
}
};
3 对应的后台逻辑代码如下:
model/cart.py
class CartLine(orm.Model):
_name = 'cart.line'
_columns = {
'count': fields.integer(string="count"),
'product_hot_item_id': fields.many2one('product.hot.item'),
'product_product_id': fields.many2one('product.product'),
'res_partner_id': fields.many2one('res.partner')
}
# 清空购物车
def clear_cart(self, cr, uid, res_partner_id):
record = self.search(cr, uid, [
('res_partner_id', '=', res_partner_id),
])
self.unlink(cr, uid, record)
pass
def set_item_count(self, cr, uid, res_partner_id, product_hot_item_id, product_product_id, count):
print count, uid, res_partner_id
pass
def get_cart_info(self, cr, uid, res_partner_id):
record = self.search(cr, uid, [
('res_partner_id', '=', int(res_partner_id)),
])
results = self.browse(cr, uid, record)
return results
def add_item(self, cr, uid, res_partner_id, product_hot_item_id, product_product_id, count):
records = self.search(cr, uid, [
('res_partner_id', '=', int(res_partner_id)),
('product_product_id', '=', int(product_product_id))
])
if len(records) != 0:
record = records[0]
re = self.browse(cr, uid, record)[0]
self.write(cr, uid, record, {
'count': re.count + count if re.count + count >= 0 else 0
})
else:
if product_hot_item_id:
self.create(cr, uid, {
'count': count if count >= 0 else 0,
'res_partner_id': res_partner_id,
'product_hot_item_id': product_hot_item_id,
'product_product_id': product_product_id
})
else:
self.create(cr, uid, {
'count': count if count >= 0 else 0,
'res_partner_id': res_partner_id,
'product_product_id': product_product_id
})
pass
def del_item(self, cr, uid, res_partner_id, product_hot_item_id, product_product_id, count):
records = self.search(cr, uid, [
('res_partner_id', '=', res_partner_id),
('product_product_id', '=', product_product_id)
])
if len(records) != 0:
record = records[0]
re = self.browse(cr, uid, record)[0]
if (re.count > count):
self.write(cr, uid, record, {
'count': re.count - count if re.count - count >= 0 else 0
})
else:
self.unlink(cr, uid, records)
else:
pass
def set_item(self, cr, uid, res_partner_id, product_hot_item_id, product_product_id, count):
records = self.search(cr, uid, [
('res_partner_id', '=', int(res_partner_id)),
('product_product_id', '=', int(product_product_id))
])
if len(records) != 0:
record = records[0]
re = self.browse(cr, uid, record)[0]
self.write(cr, uid, record, {
'count':count if count >= 0 else 0
})
else:
if product_hot_item_id:
self.create(cr, uid, {
'count': count if count >= 0 else 0,
'res_partner_id': res_partner_id,
'product_hot_item_id': product_hot_item_id,
'product_product_id': product_product_id
})
else:
self.create(cr, uid, {
'count': count if count >= 0 else 0,
'res_partner_id': res_partner_id,
'product_product_id': product_product_id
})
pass
controllers/cart.py
class cart_controller(http.Controller):
@http.route(['/shop/cart_line/add'], type='json', auth="public", methods=['POST'], website=True)
def add_item(self, product_hot_item_id, product_id, count):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
try:
res_partner_id = self.get_res_partner_id(cr, uid)
cart_obj = request.registry.get('cart.line')
cart_obj.add_item(cr, uid, res_partner_id, product_hot_item_id, product_id, count)
except Exception:
print Exception
return {'success': False}
else:
return {'success': True}
@http.route(['/shop/cart_line/set'], type='json', auth="public", methods=['POST'], website=True)
def set_item(self, product_hot_item_id, product_id, count):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
try:
res_partner_id = self.get_res_partner_id(cr, uid)
cart_obj = request.registry.get('cart.line')
cart_obj.set_item(cr, uid, res_partner_id, product_hot_item_id, product_id, count)
except Exception:
print Exception
return {'success': False}
else:
return {'success': True}
def get_res_partner_id(self, cr, uid):
cr.execute("SELECT partner_id FROM res_users WHERE id=%s", (uid,))
res_partner_id = cr.fetchone()[0]
return res_partner_id
@http.route(['/shop/cart_line/sub'], type='json', auth="public", methods=['POST'], website=True)
def del_item(self, product_hot_item_id, product_id, count):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
try:
res_partner_id=self.get_res_partner_id(cr,uid)
cart_obj = request.registry.get('cart.line')
cart_obj.del_item(cr,uid,res_partner_id,product_hot_item_id,product_id,count)
except Exception:
print Exception
return {'success':False}
else:
return {'success':True}
@http.route(['/shop/cart'], type='http', auth="public", website=True)
def cart(self, **post):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
order = request.website.sale_get_order()
if order:
from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context)
to_currency = order.pricelist_id.currency_id
compute_currency = lambda price: pool['res.currency']._compute(cr, uid, from_currency, to_currency, price,
context=context)
else:
compute_currency = lambda price: price
values = {
'order': order,
'compute_currency': compute_currency,
'suggested_products': [],
}
if order:
_order = order
if not context.get('pricelist'):
_order = order.with_context(pricelist=order.pricelist_id.id)
values['suggested_products'] = _order._cart_accessories()
return request.website.render("website_sale.cart", values)
@http.route(['/shop/cart_line/view'], type='json', auth="public", methods=['POST'], website=True)
def show_cart(self,**kwargs):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
res_partner_id = self.get_res_partner_id(cr,uid)
cart_obj = request.registry.get('cart.line')
items_set=cart_obj.get_cart_info(cr,uid,res_partner_id)
items =[self.get_info(cr,x) for x in items_set]
result= {"items":items,"uid":uid}
return result
def get_info(self, cr,x):
product_product=x.product_product_id
keys=["name_template","product_tmpl_id"]
cr.execute("SELECT "+",".join(keys) +" FROM product_product WHERE id =%s",(product_product.id,))
values=cr.fetchone()
item=dict(zip(keys,values))
if x.product_hot_item_id.id:
product_hot_item=x.product_hot_item_id
# keys=["image_url"]
# cr.execute("SELECT "+",".join(keys)+" FROM product_hot_item WHERE id=%s",(product_hot_item.id,))
# values=cr.fetchone()
# hitem=dict(zip(keys,values))
item.update({"image_url":order_preview.getSmallImage(product_hot_item.id)})
item['product_hot_item_id']=product_hot_item.id
else:
product_hot_item_images_obj = request.registry.get('product.hot.item.images')
product_hotItem_id = values[1]
product_hotItem_image_ids = product_hot_item_images_obj.search(cr, SUPERUSER_ID, [('product_template_id', '=',product_hotItem_id)])
product_hotItem_image = product_hot_item_images_obj.browse(cr, SUPERUSER_ID, product_hotItem_image_ids[0])
item.update({"image_url":product_hotItem_image.url_small})
item['product_hot_item_id'] = False
item['product_product_id']=product_product.id
item['count']=x.count
item['price']=product_product.lst_price
item['attritubes']=[{'name':x.attribute_id.name,'value':x.name} for x in product_product.attribute_value_ids]
return {'items':item}