前言
前面添加商品,商品code只能添加一次可以用唯一字段校验UniqueValidator,如果用户收藏商品,一个用户可以收藏多个商品,一个商品也可以被多个人收藏。
但是同一个人针对同一个商品,只能收藏一次,于是可以用UniqueTogetherValidator联合唯一校验
收藏商品
添加商品和收藏商品 models.py 模型设计
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class Goods(models.Model):
"""商品表"""
goods_name = models.CharField(max_length=30,
default="",
verbose_name="商品名称")
goods_code = models.CharField(max_length=30,
unique=True,
verbose_name="商品代号")
merchant_id = models.CharField(max_length=30,
default="",
blank=True, null=True,
verbose_name="商户ID")
merchant_name = models.CharField(max_length=30,
default="",
blank=True, null=True,
verbose_name="商户名称")
# goods_price = models.FloatField(blank=True, null=True,
# default=0,
# verbose_name="商品价格")
goods_price = models.DecimalField(max_digits=10, decimal_places=2,
blank=True, null=True,
default=0, verbose_name="商品价格")
goods_stock = models.IntegerField(blank=True, null=True,
default=0,
verbose_name="商品库存")
goods_groupid = models.IntegerField(blank=True, null=True,
default=0,
verbose_name="商品分组")
goods_status = models.IntegerField(choices=(
(0, '下架'),
(1, '出售中')
),
default=1,
verbose_name="0下架 1出售中")
price = models.FloatField(blank=True, null=True,
default=0,
verbose_name="成本价")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="修改时间")
class Meta:
verbose_name_plural = '商品'
verbose_name = "商品信息"
def __str__(self):
return self.goods_code
class UserCollect(models.Model):
"""用户收藏商品"""
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户id")
goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品", help_text="商品id")
status = models.CharField(choices=(
(0, '取消收藏'),
(1, '已收藏')
),
default=1,
verbose_name="0取消收藏 1已收藏")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="修改时间")
class Meta:
verbose_name = '用户收藏'
verbose_name_plural = verbose_name
# 唯一联合,一个商品只能收藏一次
unique_together = ("user", "goods")
def __str__(self):
return self.user.username
序列化收藏商品
序列化的时候user字段是隐藏字段,不需要用户传过来,用户只要登录了可以通过request.user获取当前登录的账号
status有2个状态,不需要用户传入,设置read_only=True
validators.UniqueTogetherValidator联合校验'user', 'goods'字段的唯一性
from .models import Goods, UserCollect
from rest_framework import validators
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class UserCollectSerializer(serializers.ModelSerializer):
# 获取当前登录的用户
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
status = serializers.ChoiceField(choices=(
(0, '取消收藏'),
(1, '已收藏')
),
read_only=True)
def to_representation(self, instance):
"""to_representation自定义序列化数据的返回"""
data = super().to_representation(instance)
data.update(status=instance.get_status_display())
return data
class Meta:
# validate实现唯一联合,一个商品只能收藏一次
validators = [
validators.UniqueTogetherValidator(
queryset=UserCollect.objects.all(),
fields=('user', 'goods'),
# message的信息可以自定义
message="已收藏"
)
]
model = UserCollect
# 收藏的时候需要返回商品的id,因为取消收藏的时候必须知道商品的id是多少
fields = '__all__' # 返回全部的字段
添加收藏和查询的视图
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class UserCollectAPIView(APIView):
"""我的收藏"""
def get(self, request, *args, **kwargs):
"""查询我的收藏"""
collect = UserCollect.objects.all().filter(status=1, user=request.user) # 查询自己的收藏
serializer = UserCollectSerializer(instance=collect, many=True, context={"request": request})
return Response({
"code": 0,
"msg": "success!",
"data": serializer.data
})
def post(self, request, *args, **kwargs):
"""添加收藏"""
verify_data = UserCollectSerializer(data=request.data, context={"request": request})
if verify_data.is_valid():
save = verify_data.save()
return Response({
"code": 0,
"msg": "success!",
"data": UserCollectSerializer(instance=save, context={"request": request}).data
})
else:
return Response({
"code": 10086,
"msg": "参数不合法",
"data": verify_data.errors
})
测试我的收藏功能
收藏商品的时候,传商品id即可
如果已经收藏,会提示已收藏
查询的时候,每个用户只查询自己的,并且状态为1 的数据
DRF中的UniqueTogetherValidator 相关用法可以参考官方文档https://www.django-rest-framework.org/api-guide/validators/#uniquetogethervalidator