zoukankan      html  css  js  c++  java
  • python测试开发django-rest-framework-93.反序列化(ModelSerializer)之UniqueTogetherValidator联合唯一校验

    前言

    前面添加商品,商品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'字段的唯一性
    该验证器可用于unique_together对模型实例施加约束。它具有两个必需参数和一个可选messages参数:

    • queryset 必需-这是应针对其强制执行唯一性的查询集。
    • fields 必填-字段名称的列表或元组,应组成唯一的集合。这些必须作为字段存在于序列化程序类中。
    • message -验证失败时应使用的错误消息。
    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 的数据

  • 相关阅读:
    Dockerfile-ADD命令-转载
    华为云上上传镜像到在线镜像仓库
    什么是4D(DRG、DLG、DOM、DEM)数据
    视频对接资料
    OpenLayer改变切片地图的样式-滤镜效果
    Docker-挂载宿主机目录到容器
    RTSP在线视频环境搭建2-海康摄像头
    配置自己风格的Clang-Format-Xcode
    GCDAsyncUdpSocket的使用
    react-native component function
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/14352695.html
Copyright © 2011-2022 走看看