【问题标题】:How to validate unique constraint on django rest framework?如何验证对 django rest 框架的唯一约束?
【发布时间】:2020-05-17 19:36:46
【问题描述】:

如何使用不在请求负载中的键验证唯一约束?

我需要验证的密钥是user_idsku,但请求不包含user_id 密钥。

有效载荷示例:

{'sku': '123', data: []}

序列化器:

class ProductConfiguration(serializers.Serializer):

    min_quantity = serializers.IntegerField(required=True)
    price = serializers.DecimalField(
        required=True,
        decimal_places=2,
        max_digits=10,
        coerce_to_string=False
    )


class ProductSerializer(serializers.ModelSerializer):

    sku = serializers.CharField(required=True)
    data = ProductConfiguration(many=True, required=True)

    class Meta:
        model = WholeSale

        # the "id" and "user_id" columns should not be included on the response
        exclude = ['id', 'user']

我需要验证 usersku 密钥是否已经存在。

默认情况下,如果user_idsku 两个键在有效负载上drf 可以处理Unique 错误,如果其中一个不在有效负载上,我如何验证这两个键?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    你可以从请求中获取用户数据

    request.user

    也许将它从视图传递给序列化器

    data = request.data
    data['user_id'] = request.user.pk
    serializer = ProductSerializer(data)
    

    在序列化器中你可以这样做

    def validate(self, data):
        user = data.get('user_id')
        sku = data.get('sku')
    
        record = WholeSale.objects.filter(user=user, sku=sku).first()
    
        if not record:
            raise serializers.ValidationError("This combo doesn't exist")
    
        return super().validate(data)
    

    【讨论】:

    • 我会使用:if not WholeSale.objects.filter(user=user, sku=sku).exists(): raise Validation error
    【解决方案2】:

    假设你有这个模型结构(我只使用skuuser 字段)。为了实现你想要做的事情,在类元中提供一个独特的约束,

    class WholeSale(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
        sku = models.CharField(max_lenght=100)
    
        class Meta:
            unique_together = ['user', 'sku']
    

    ,

    只需覆盖validate_unique 方法即可同时验证usersku 字段。

    class WholeSale(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
        sku = models.CharField(max_lenght=100)
    
        def validate_unique(self, *args, **kwargs):
            # super(WholeSale, self).validate_unique(*args, **kwargs) # python2
            super().validate_unique(*args, **kwargs) # python3
            if self.__class__.objects.filter(user=self.user, sku=self.sku).\
                exists():
                raise ValidationError(
                    message='This (user, sku) already exists.',
                )
    

    无需从序列化程序显式验证

    【讨论】:

    • 至少使用最新的 django rest framework = 3.11.1 这个函数根本不会被调用:(
    【解决方案3】:
    class ProductSerializer(serializers.ModelSerializer):
        def validate(self, attrs):
            if not Sku.objects.get(sku=attrs['sku']).exists() or not User.objects.get(id=attrs['id']).exists():
                raise serializers.ValidationError("Something doesn't exist")
            
            return attrs
    
        sku = serializers.CharField(required=True)
        data = ProductConfiguration(many=True, required=True)
    
        class Meta:
            model = WholeSale
            exclude = ['id', 'user']
    

    【讨论】:

    • 问题说usersku必须一起验证...
    • 这是一个粗略的想法,你可以用它来推进问题
    猜你喜欢
    • 2013-01-06
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多