1. 购物车
接口:http://127.0.0.1:8000/shopcarts/
需求:
- 添加商品到购物车
- 购物车中所有商品信息(详情)
- 删除购物车记录
1.1 添加商品到购物车
1、trade/seriliazers.py
:
class ShopCartSerializer(serializers.Serializer):
"""购物车"""
# 获取当前登录用户
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
nums = serializers.IntegerField(required=True, label='数量', min_value=1,
error_messages={
'min_value': '商品数量不能小于一',
'required': '请选择购买数量'
})
# 外键,获取 goods 中所有值,必须指定 queryset,继承 ModelSerializer 无需指定
goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all())
add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")
def create(self, validated_data):
"""
serializers.Serializer 没有 save() 需要重写 create
:param validated_data:已处理过的数据(前端提交的数据)
:return:
"""
# 获取当前用户
user = self.context['request'].user
nums = validated_data['nums']
goods = validated_data['goods']
# 查询数据库,若有记录(表示添加到购物车,该商品),数量 + nums,否则就添加到购物车
existed = ShoppingCart.objects.filter(user=user, goods=goods)
# 数量增加
if existed:
existed = existed[0]
existed.nums += nums
existed.save()
else:
# 添加到购物车
existed = ShoppingCart.objects.create(**validated_data)
return existed
def update(self, instance, validated_data):
"""更新购物车,修改数量"""
instance.nums = validated_data['nums']
instance.save()
return instance
这里之所以采用继承 Serializer
而不是 ModelSerializer
,是因为 ModelSerializer 的 creat()
方法会之前创建一条新的记录,当用户将同一商品多次添加到购物车时应该只需数量变化,而不是重写创建一条新的购物车记录,所以需要重写 create()
方法。
2、trade/views.py
:
class ShoppingCartViewSet(viewsets.ModelViewSet):
"""
购物车功能:
list:获取购物车详情
create:加入购物车
delete:删除购物车记录
"""
serializer_class = ShopCartSerializer
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
# 商品 ID,用于购物车更新(update() 商品数量)
lookup_field = "goods_id"
def get_queryset(self):
"""获取当前用户购物车列表"""
return ShoppingCart.objects.filter(user=self.request.user)
3、配置路由 MxShop/urls.py
:
router.register(r'shopcarts', ShoppingCartViewSet, basename='shopcarts') # 购物车
1.2 获取购物车商品详情
接口:
# 获取所有商品信息:get
http://127.0.0.1:8000/shopcarts/
# 单独获取某个商品详情:get
http://127.0.0.1:8000/shopcarts/1/
1、trade/serializers.py
:
class ShopCartDetailSerializer(serializers.ModelSerializer):
"""购物车中商品详情"""
# 一个购物车对应一个商品.
goods = GoodsSerializer(many=False, required=True)
class Meta:
model = ShoppingCart
fields = ('goods', 'nums')
2、trade/views.py
:
class ShoppingCartViewSet(viewsets.ModelViewSet):
....
def get_serializer_class(self):
"""动态选择 serializer"""
if self.action == 'list':
return ShopCartDetailSerializer
else:
return ShopCartSerializer
动态选择 serializer
,当添加或删除购物车商品时:ShopCartSerializer
,获取购物车商品详情(列表)时:ShopCartDetailSerializer
。
2. 订单管理
接口地址:http://127.0.0.1:8000/orders/
需求分析:
- 用户添加商品到购物车,点击结算
- 填上地址留言(必须),结算(提交)订单
- 会员中心可查看所以的订单列表,点击单个订单可查看订单详细信息
支持:创建订单、获取个人订单(列表、详情)、删除订单
1、trade/serializers.py
:
class OrderGoodsSerializer(serializers.ModelSerializer):
"""订单中的商品"""
goods = GoodsSerializer(many=False)
class Meta:
model = OrderGoods
fields = '__all__'
class OrderDetailSerializer(serializers.ModelSerializer):
"""
订单中商品详细信息
"""
# goods字段需要嵌套一个OrderGoodsSerializer
goods = OrderGoodsSerializer(many=True)
add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")
class Meta:
model = OrderInfo
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
"""订单"""
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
# 生成订单时,不需 post以下数据
pay_status = serializers.CharField(read_only=True)
trade_no = serializers.CharField(read_only=True)
order_sn = serializers.CharField(read_only=True)
pay_time = serializers.DateTimeField(read_only=True)
nonce_str = serializers.CharField(read_only=True)
pay_type = serializers.CharField(read_only=True)
add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M")
def generate_order_sn(self):
"""
生成订单号:当前时间+userid+随机数
:return:
"""
from random import Random
random_str = Random()
order_sn = "{time_str}{userid}{ranstr}".format(time_str=time.strftime("%Y%m%d%H%M%S"),
userid=self.context['request'].user.id,
ranstr=random_str.randint(10, 99))
return order_sn
def validate(self, attrs):
"""validate 中添加 order_sn,然后再 view 中就可以 save"""
attrs['order_sn'] = self.generate_order_sn()
return attrs
class Meta:
model = OrderInfo
fields = '__all__'
三个 serializer
:
OrderGoodsSerializer
:订单中商品(OrderGoods
)OrderDetailSerializer
:订单中商品详细信息(OrderInfo
)OrderSerializer
:订单(OrderInfo
)
前端 vue
页面中需要提交的信息只有 订单留言、订单金额、收货地址、签收人、联系电话,其他诸如 订单号、支付状态、交易号等不需要在前端提交。
流程:表单字段验证通过后,validate()
中调用 generate_order_sn()
生成订单号,并将其保存到 attrs
字典中,之后 view
视图 save()
保存,订单创建成功。
2、trade/views.py
:
class OrderViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin,
mixins.RetrieveModelMixin):
"""
订单相关
list:获取个人订单
create:创建订单
delete:删除订单
"""
serializer_class = OrderSerializer
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
def get_serializer_class(self):
# 订单详情
if self.action == 'retrieve':
return OrderDetailSerializer
else:
return OrderSerializer
def perform_create(self, serializer):
"""
提交订单之前步骤
1、将购物车中商品保存到 OrderGoods
2、清空购物车
:param serializer:
:return:
"""
order = serializer.save()
# 获取购物车中所有商品
shop_carts = ShoppingCart.objects.filter(user=self.request.user)
for shop in shop_carts:
order_goods = OrderGoods()
order_goods.goods = shop.goods
order_goods.goods_num = shop.nums
order_goods.order = order
order_goods.save()
# 清空购物车
shop.delete()
return order
def get_queryset(self):
return OrderInfo.objects.filter(user=self.request.user)
保存之前将购物车中商品保存到 OrderGoods
中,另外就是清空购物车。
3、配置路由 MxShop/urls.py
:
router.register(r'orders', OrderViewSet, basename='orders') # 订单