分析
用戶登錄后,將Cookie中的購物車商品合并到redis數據庫中。如果此時redis中已經有相同id的商品,則使用Cookie中的數據覆蓋redis中的數據。
合并功能需要在用戶登錄后實現,但登錄視圖中應避免過多與登錄邏輯無關的邏輯,所以考慮對合并功能封裝成一個函數,在登錄視圖中調用。
實現
在carts應用下創建utils.py文件,在utils.py中定義合并購物車功能的函數。
import base64
import picklefrom django_redis import get_redis_connectiondef merge_carts_cookies_redis(request, user, response):"""合并購物車數據"""# 獲取cookie中的數據cookie_cart_str = request.COOKIES.get('carts')if not cookie_cart_str:return response# 從cookie中取出數據,放入字典cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart_str.encode()))new_cart_dict = {}new_cart_selected_add = []new_cart_selected_remove = []# 覆蓋for sku_id, cookie_dict in cookie_cart_dict.items():new_cart_dict[sku_id] = cookie_dict['count']if cookie_dict['selected']:new_cart_selected_add.append(sku_id)else:new_cart_selected_remove.append(sku_id)redis_conn = get_redis_connection('carts')pl = redis_conn.pipeline()if new_cart_dict:# 同步商品數據pl.hmset('carts_%s' % user.id, new_cart_dict)if new_cart_selected_add:pl.sadd('selected_%s' % user.id, *new_cart_selected_add)else:pl.srem('selected_%s' % user.id, *new_cart_selected_remove)pl.execute()response.delete_cookie('carts')return response
在登錄視圖類LoginView中,登錄成功后調用上述合并函數,LoginView視圖類全部代碼如下
class LoginView(View):def get(self, request):return render(request, 'login.html')def post(self, request):username = request.POST.get('username')password = request.POST.get('password')remembered = request.POST.get('remembered')if not all([username, password]):return HttpResponseForbidden('缺少必須參數')if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):return HttpResponseForbidden('請輸入正確的用戶名')if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):return HttpResponseForbidden('密碼8-20位')user = authenticate(username=username, password=password)if user is None:return render(request, 'login.html', {'account_errmsg': '賬號或密碼錯誤'})login(request, user)print(request.session.session_key)if remembered != 'on':request.session.set_expiry(0)else:request.session.set_expiry(None) # 2周過期# 在Django中,request.GET.get('next')的值是一個字符串,它代表用戶在登錄前嘗試訪問的原始URL。# 這個值由Django自動添加到登錄URL中,用于在用戶成功登錄后將其重定向回原始頁面。next = request.GET.get('next')print(next)if next:# 重定向到nextresponse = redirect(next)else:# 重定向到首頁response = redirect(reverse('contents:index'))# 新增設置cookieresponse.set_cookie('username', user.username, max_age=3600 * 24 * 14)response = merge_carts_cookies_redis(request,user,response)return response