基於Django的購物車管理-添加商品到購物車

(1) 添加到購物車

前端:

html

<a @click="add_carts" class="add_cart" id="add_cart">加入購物車</a>

js

        // 加入購物車
        add_carts(){
            let url = '/carts/';
            axios.post(url, {
                sku_id: parseInt(this.sku_id),
                count: this.sku_count
            }, {
                headers: {
                    'X-CSRFToken':getCookie('csrftoken')
                },
                responseType: 'json',
                withCredentials: true
            })
                .then(response => {
                    if (response.data.code == '0') {
                        alert('添加購物車成功');
                        this.cart_total_count += this.sku_count;
                    } else { // 參數錯誤
                        alert(response.data.errmsg);
                    }
                })
                .catch(error => {
                    console.log(error.response);
                })
        },

後端

views.py

class CartsView(View):
    """購物車管理"""

    def post(self, request):
        """保存購物車"""
        # 接收參數
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)        # 可選
        # 校驗參數
        # 判斷參數是否齊全
        if not all([sku_id, count]):
            return http.HttpResponseForbidden('缺少必傳參數')
        # 校驗sku_id是否合法
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('參數sku_id錯誤')
        # 校驗count是否是數字
        try:
            count = int(count)
        except Exception as e:
            return http.HttpResponseForbidden('參數count錯誤')
        # 校驗勾選是否是bool
        if selected:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('參數selected錯誤')

        # 判斷用戶是否登錄
        user = request.user
        if user.is_authenticated:
            # 如果已登錄,操作Redis購物車
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            # 需要以增量計算的形式保存商品數據
            # hincrby方法能實現:如果sku_id在redis中存在,累加該sku_id的count的值;如果sku_id在redis中不存在,新建記錄
            pl.hincrby('carts_%s' % user.id, sku_id, count)
            # 保存商品勾選狀態
            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            # 執行
            pl.execute()
            # 響應結果
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
        else:
            # 如果用戶未登錄,操作cookie購物車
            # 獲取cookie中的購物車數據,並且判斷是否有購物車數據
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 將cart_str轉成bytes類型的字符串
                cart_str_bytes = cart_str.encode()
                # 將cart_str_bytes專程bytes類型的字典
                cart_dict_bytes = base64.b64decode(cart_str_bytes)
                # 將cart_dict_bytes轉成真正的字典
                cart_dict = pickle.loads(cart_dict_bytes)
            else:
                cart_dict = {}
            """
            {
                "sku_id1":{
                    "count":"1",
                    "selected":"True"
                },
            }
            """
            # 判斷當前要添加的商品在cart_dict中是否存在
            if sku_id in cart_dict:
                # 購物車已存在,增量計算
                origin_count = cart_dict[sku_id]['count']
                count += origin_count

            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            # 將cart_dict轉成bytes類型的字典
            cart_dict_bytes = pickle.dumps(cart_dict)
            # 將cart_dict_bytes轉成bytes類型的字符串
            cart_str_bytes = base64.b64encode(cart_dict_bytes)
            # 將cart_str_bytes轉成字符串
            cookie_cart_str = cart_str_bytes.decode()

            # 將新的購物車數據寫入到cookie
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
            response.set_cookie('carts', cookie_cart_str)

            # 響應結果
            return response

後端邏輯是:

判斷用戶是否登錄------若登錄:使用redis存儲;

redis的hincrby方法:

            # 需要以增量計算的形式保存商品數據
            # hincrby方法能實現:如果sku_id在redis中存在,累加該sku_id的count的值;如果sku_id在redis中不存在,新建記錄
            pl.hincrby('carts_%s' % user.id, sku_id, count)

若未登錄:使用前端cookie存儲

首先了解python的兩個模塊:base64, pickle

序列化(字典--->字符串)

In [1]: import pickle                                                                                                                                                                                       

In [2]: dict = {'1':{'count': 10, 'selected': True}, '2': {'count': 20, 'selected': False}}                                                                                                                 

In [3]: ret = pickle.dumps(dict)                                                                                                                                                                            

In [4]: ret                                                                                                                                                                                                 
Out[4]: b'\x80\x03}q\x00(X\x01\x00\x00\x001q\x01}q\x02(X\x05\x00\x00\x00countq\x03K\nX\x08\x00\x00\x00selectedq\x04\x88uX\x01\x00\x00\x002q\x05}q\x06(h\x03K\x14h\x04\x89uu.'

In [5]: import base64                                                                                                                                                                                       

In [6]: base64.b64encode(ret)                                                                                                                                                                               
Out[6]: b'gAN9cQAoWAEAAAAxcQF9cQIoWAUAAABjb3VudHEDSwpYCAAAAHNlbGVjdGVkcQSIdVgBAAAAMnEFfXEGKGgDSxRoBIl1dS4='

In [7]: b = base64.b64encode(ret)                                                                                                                                                                           

In [8]: cookie_cart_str = b.decode()                                                                                                                                                                        

In [9]: cookie_cart_str                                                                                                                                                                                     
Out[9]: 'gAN9cQAoWAEAAAAxcQF9cQIoWAUAAABjb3VudHEDSwpYCAAAAHNlbGVjdGVkcQSIdVgBAAAAMnEFfXEGKGgDSxRoBIl1dS4='

dict--->ret=pickle.dumps(dict) --->b=base64.b64encode(ret) --->cookie_cart_str = b.decode() -->cookie_cart_str

反序列化(序列---->字典)

In [10]: b = cookie_cart_str.encode()                                                                                                                                                                       

In [11]: b                                                                                                                                                                                                  
Out[11]: b'gAN9cQAoWAEAAAAxcQF9cQIoWAUAAABjb3VudHEDSwpYCAAAAHNlbGVjdGVkcQSIdVgBAAAAMnEFfXEGKGgDSxRoBIl1dS4='

In [12]: ret = base64.b64decode(b)                                                                                                                                                                          

In [13]: ret                                                                                                                                                                                                
Out[13]: b'\x80\x03}q\x00(X\x01\x00\x00\x001q\x01}q\x02(X\x05\x00\x00\x00countq\x03K\nX\x08\x00\x00\x00selectedq\x04\x88uX\x01\x00\x00\x002q\x05}q\x06(h\x03K\x14h\x04\x89uu.'

In [14]: dict = pickle.loads(ret)                                                                                                                                                                           

In [15]: dict                                                                                                                                                                                               
Out[15]: {'1': {'count': 10, 'selected': True}, '2': {'count': 20, 'selected': False}}

b = cookie_cart_str.encode()---->ret = base64.b64decode(b) --->dict = pickle.loads(ret)

 

這樣做的目的是不以明文的形式將購物車信息放入前端cookie中

後端代碼對於沒有登錄的用戶邏輯是:判斷購物車是否有數據--若有,先反序列化,重新計算後再序列化;若沒有直接新建字典,再序列化。

response.set_cookie('carts', cookie_cart_str)

然後將序列化後的數據放入前端cookie中。

流程分析

點擊“加入購物車”按鈕,觸發Ajax請求:

後端將序列化好的數據發給前端。

可發現前端cookie中存入了序列化的數據。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章