分析
用户登录后,将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