vue+django2.0.2-rest-framework 生鲜项目
一、购物车功能
1、实现购物车获取购物车商品列表信息、添加购物车商品数量、删除购物车商品
1)trade/serializer.py:序列化购物车数据
几点说明:
- serializers.Serializer中没有get(list)、post(create)方法,需要自定义。
- views.py中获取当前用户 代码操作:self.request.user ; serializers.py中,要获取当前用户,代码:self.context["request"].user ,存放于context当中。
- goods是一个外键,之前我们序列化goods商品时,goods/serializers.py中有用到序列化的CategorySerializer来展示外键相关信息,一般用list方法访问时使用这种方式展示所需要的详细信息,不需要展示商品详情时不这么做。在购物车model中,因为使用了联合唯一(goods、nums),不允许我们同一个goods+nums添加多个,否则会报错,所以我们不用耦合性较高的ModelSerializers,而是用Serializers。外键处理则使用DRF提供的PrimaryKeyRelatedField字段处理:
goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all()) ,在serializers.Serializer中,‘queryset=Goods.objects.all()’这句是必须要写的,获取所有的商品数据,是个querysets集合,在serializers.ModelSerializer中,该语句是这样:goods = serializers.PrimaryKeyRelatedField(required=True, many=True,read_only),两句代码效果是一样的,第二句是因为内部有model,会自己映射,所以不用添加queryset搜查所有数据。 -
goods = GoodsSerializer():使用序列化这种方式,会将提交的某goods商品所有信息以序列化形式都展示出来,需要全部填写才能提交
goods = serializers.PrimaryKeyRelatedField:是个querysets集合,只会显示model中(__str__)return的字段信息,比如商品的名称(name),不需要我们操作。
购物车需要获取的只是goods中的商品名称,故用第二种,不能用第一种序列化的方式。
-
serializers.Serializer中,create()、update()两个方法,当需要用到时,需要我们在serializers中重载,否则会报错:`create()` must be implemented 。
而serializers.ModelSerializer中,系统已经简单帮我们实现了这两个方法,不需要我们重载
from .models import ShoppingCart from rest_framework import serializers from goods.models import Goods class ShopCartSerializer(serializers.Serializer): #获取当前登录的用户 user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) nums = serializers.IntegerField(required=True, label="数量",min_value=1, error_messages={ "min_value":"商品数量不能小于一", "required": "请选择购买数量" }) #这里是继承Serializer,必须指定queryset对象,如果继承ModelSerializer则不需要指定 #goods是一个外键,可以通过这方法获取goods object中所有的值 goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all()) #继承的Serializer没有save功能,必须写一个create方法 def create(self, validated_data): # validated_data是已经处理过的数据 #获取当前用户 # view中:self.request.user;serizlizer中:self.context["request"].user user = self.context["request"].user nums = validated_data["nums"] goods = validated_data["goods"] existed = ShoppingCart.objects.filter(user=user, goods=goods) #如果购物车中有记录,数量+nums #如果购物车车没有记录,就创建 if existed: existed = existed[0] existed.nums += nums existed.save() else: #添加到购物车 existed = ShoppingCart.objects.create(**validated_data) return existed
2)trade/views.py:
重载 get_queryset 方法,只查找与当前客户相关的购物车数据
from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from utils.permissions import IsOwnerOrReadOnly from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework.authentication import SessionAuthentication from .serializers import ShopCartSerializer from .models import ShoppingCart class ShoppingCartViewset(viewsets.ModelViewSet): """ 购物车功能 list: 获取购物车详情 create: 加入购物车 delete: 删除购物记录 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = ShopCartSerializer def get_queryset(self): return ShoppingCart.objects.filter(user=self.request.user)
3)urls.py配置:
# 购物车 router.register(r'shopcarts', ShoppingCartViewset, base_name="shopcarts")
上述已经完成了当前用户购物车数据获取、购物车商品创建,接下来我们来实现购物车商品数据更新:更新商品数量
更新数据,需要用到update () 方法,因此,我们需要在serializers中重载该方法:
1)trade/serializer.py下的 ShopCartSerializer 添加:
def update(self, instance, validated_data): # 修改商品数量 instance.nums = validated_data["nums"] instance.save() return instance
2)在view中要把商品id传过去:
因为更新单条数据,或者删除单条数据,需要用到商品id。
lookup_field = "goods_id"
trade/views.py 完整代码:
from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from utils.permissions import IsOwnerOrReadOnly from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework.authentication import SessionAuthentication from .serializers import ShopCartSerializer from .models import ShoppingCart class ShoppingCartViewset(viewsets.ModelViewSet): """ 购物车功能 list: 获取购物车详情 create: 加入购物车 delete: 删除购物记录 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = ShopCartSerializer lookup_field = "goods_id" def get_queryset(self): return ShoppingCart.objects.filter(user=self.request.user)