二十八、购物车功能实现(商品部分)

1、更改dev配置

因为前端可能携带cookie,为了保证跨域请求中,允许后端使用cookie,确保在配置文件有如下设置

CORS_ALLOW_CREDENTIALS = True

2、创建购物车应用carts(apps/)

python ../../manage.py startapp carts

3、在dev中注册应用和配置redis数据库

INSTALLED_APPS = [
  'carts.apps.CartsConfig', 
]
# 配置redis数据库
CACHES = {
    "carts": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/4",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        },
}

4、在serializers中创建序列化器CartsSerialziers

from rest_framework import serializers

from goods.models import SKU


class CartsSerialziers(serializers.Serializer):
    sku_id = serializers.IntegerField(min_value=1)
    count = serializers.IntegerField(min_value=1)
    selected = serializers.BooleanField(default=True)

    def validate(self, attrs):

        # 判断sku——id商品是否存在
        try:
            sku = SKU.objects.get(id=attrs['sku_id'])
        except:
            raise serializers.ValidationError('商品不存在')

        # 判断库存
        if attrs['count'] > sku.stock:
            raise serializers.ValidationError('商品库存不足')

        return attrs


class CartListSeriazlier(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=True,read_only=True)
    selected = serializers.BooleanField(default=True,read_only=True)

    class Meta:
        model=SKU
        fields="__all__"

class CartsDeleteSerialziers(serializers.Serializer):
    sku_id = serializers.IntegerField(min_value=True)
    
class CartsSelectedSerialziers(serializers.Serializer):
    selected = serializers.BooleanField(default=True)

5、在views中创建CartsView类,定义post方法。

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from django_redis import get_redis_connection
# Create your views here.
from carts.serializers import CartsSerialziers, CartListSeriazlier, CartsDeleteSerialziers, CartsSelectedSerialziers
import pickle, base64

from goods.models import SKU


class CartsView(APIView):
    """
        购物车数据的增删改查
    """

    def perform_authentication(self, request):
        # 不再调用post方法之前进行验证
        # request.user
        pass

    def post(self, request):

        # 1、获取数据
        data = request.data
        # 2、验证数据
        ser = CartsSerialziers(data=data)
        ser.is_valid()
        print(ser.errors)
        # 获取验证后数据
        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 3、判断用户登录状态
        try:
            user = request.user
        except:
            user = None
        if user is not None:
            # 4、已登陆 保存redis
            # 1、建立连接
            conn = get_redis_connection('carts')
            # 2、写入hash sku - id和cout
            conn.hincrby('cart_%s' % user.id, sku_id, count)
            # 3、写入set
            if selected:
                conn.sadd('cart_selected_%s' % user.id, sku_id)
                # 4、结果返回
                return Response({'message': 'ok'})

        else:
            # 5、未登录 保存cookie
            response = Response({'message': 'ok'})
            # 1、先获取cookie,判断原来是否写入过cookie
            cart_cookie = request.COOKIES.get('cart_cookie', None)
            if cart_cookie:
                # 2、写入过。解密.cart = {10: {‘count’:2, selected: True}
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 3、未写入过cart = {}
                cart = {}
            # 4、判断sku - id是否存在 累加
            sku = cart.get(sku_id)
            if sku:
                count += int(sku['count'])
            # 5、写入新数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 6、加密操作
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            # 7、写入cookie
            response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24)
            # 8、结果返回
            return response

    def get(self, request):

        # 1、判断用户登录状态
        try:
            user = request.user
        except:
            user = None
        if user is not None:
            # 2、已登陆 保存redis
            # 1、建立连接
            conn = get_redis_connection('carts')
            # 2、获取hash sku - id和cout
            sku_id_count=conn.hgetall('cart_%s' % user.id)
            # 3、获取set
            selecteds=conn.smembers('cart_selected_%s' % user.id)
            # 4\构建字典数据
            cart={}
            for sku_id,count in sku_id_count.items():
                cart[int(sku_id)]={
                    'count':int(count),
                    'selected':sku_id in selecteds
                }

        else:
            # 3、未登录 保存cookie
            # 1、先获取cookie,判断原来是否写入过cookie
            cart_cookie = request.COOKIES.get('cart_cookie', None)
            if cart_cookie:
                # 2、写入过。解密.cart = {10: {‘count’:2, selected: True}
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 3、未写入过cart = {}
                cart = {}

        # 4、获取字典中的sku_id
        sku_ids=cart.keys()
        # 5、根据sku_id, 查询商品数据对象
        skus=SKU.objects.filter(id__in=sku_ids)

        for sku in skus:
            sku.count=cart[sku.id]['count']
            sku.selected=cart[sku.id]['selected']
        # 6、序列化返回数据对象
        ser=CartListSeriazlier(skus,many=True)

        return Response(ser.data)

    def put(self, request):

        # 1、获取数据
        data = request.data
        # 2、验证数据
        ser = CartsSerialziers(data=data)
        ser.is_valid()
        print(ser.errors)
        # 获取验证后数据
        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 3、判断用户登录状态
        try:
            user = request.user
        except:
            user = None
        if user is not None:
            # 4、已登陆 保存redis
            # 1、建立连接
            conn = get_redis_connection('carts')
            # 2、更新hash sku - id和cout
            conn.hset('cart_%s' % user.id, sku_id, count)
            # 3、更新set
            if selected:
                conn.sadd('cart_selected_%s' % user.id, sku_id)
            else:
                conn.srem('cart_selected_%s' % user.id, sku_id)
            # 4、结果返回
            return Response({'count': count})

        else:
            # 5、未登录 保存cookie
            response = Response({'count': count})
            # 1、先获取cookie,判断原来是否写入过cookie
            cart_cookie = request.COOKIES.get('cart_cookie', None)
            if cart_cookie:
                # 2、写入过。解密.cart = {10: {‘count’:2, selected: True}
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 3、未写入过cart = {}
                cart = {}
            # 4、写入新数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 5、加密操作
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            # 6、写入cookie
            response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24)
            # 9、结果返回
            return response

    def delete(self, request):

        # 1、获取数据
        data = request.data
        # 2、验证数据
        ser = CartsDeleteSerialziers(data=data)
        ser.is_valid()
        print(ser.errors)
        # 获取验证后数据
        sku_id = ser.validated_data['sku_id']
        # 3、判断用户登录状态
        try:
            user = request.user
        except:
            user = None
        if user is not None:
            # 4、已登陆 删除redis
            # 1、建立连接
            conn = get_redis_connection('carts')
            # 2、删除hash sku - id和cout
            conn.hdel('cart_%s' % user.id, sku_id)
            # 3、删除set
            conn.srem('cart_selected_%s' % user.id, sku_id)
            # 4、结果返回
            return Response({'message': 'ok'})

        else:
            # 5、未登录 保存cookie
            response = Response({'message': 'ok'})
            # 1、先获取cookie,判断原来是否写入过cookie
            cart_cookie = request.COOKIES.get('cart_cookie', None)
            if cart_cookie:
                # 2、写入过。解密.cart = {10: {‘count’:2, selected: True}
                cart = pickle.loads(base64.b64decode(cart_cookie))
                # 3、删除数据
                if sku_id in cart.keys():
                    del cart[sku_id]
                # 4、加密操作
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
                # 5、写入cookie
                response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24)
            # 6、结果返回
            return response


class CartsSelectedView(APIView):
    def perform_authentication(self, request):
        # 不再调用put方法之前进行验证
        # request.user
        pass

    def put(self, request):

        # 1、获取数据
        data = request.data
        # 2、验证数据
        ser = CartsSelectedSerialziers(data=data)
        ser.is_valid()
        print(ser.errors)
        # 获取验证后数据
        selected = ser.validated_data['selected']
        # 3、判断用户登录状态
        try:
            user = request.user
        except:
            user = None
        if user is not None:
            # 4、已登陆 保存redis
            # 1、建立连接
            conn = get_redis_connection('carts')
            # 2、获取hash sku——id和cout
            sku_id_count=conn.hgetall('cart_%s' % user.id)  #{1:2}
            sku_ids=sku_id_count.keys() #[1,2,3]
            # 3、更新set
            if selected:
                conn.sadd('cart_selected_%s' % user.id,*sku_ids)
            else:
                conn.srem('cart_selected_%s' % user.id, *sku_ids)
            # 4、结果返回
            return Response({'selected': selected})

        else:
            # 5、未登录 保存cookie
            response = Response({'selected': selected})
            # 1、先获取cookie,判断原来是否写入过cookie
            cart_cookie = request.COOKIES.get('cart_cookie', None)
            if cart_cookie:
                # 2、写入过。解密.cart = {10: {‘count’:2, selected: True}
                cart = pickle.loads(base64.b64decode(cart_cookie))

                # 3、更新所有数据
                for sku_id,data in cart.items():
                    data['selected']=selected

                # 4、加密操作
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
                # 5、写入cookie
                response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24)
            # 6、结果返回
            return response

6、注册路由

  • 主路由
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^', include('carts.urls')),
  ]
  • 子路由
from django.conf.urls import url
from django.contrib import admin
from . import views
urlpatterns = [
    url(r'^cart/$', views.CartsView.as_view()),
    url(r'^cart/selection/$', views.CartsSelectedView.as_view()),
]

猜你喜欢

转载自blog.csdn.net/weixin_42633359/article/details/84642544
今日推荐