【问题标题】:Django DRF Serializer fields required conditionally有条件地需要 Django DRF 序列化器字段
【发布时间】:2018-04-12 21:02:28
【问题描述】:

我有一个如下所示的序列化程序:

class MySerializer(serializers.Serializer):
    lat = serializers.FloatField(required=False)
    lng = serializers.FloatField(required=False)

我想确保如果请求带有 'lat' 字段,则 'lng' 字段将是强制性的,反之亦然。

我可以使用 validate 函数来做到这一点,但相信有更好的方法来做到这一点。

【问题讨论】:

  • 将两个字段的required 参数更改为True 怎么样?, (lat = serializers.FloatField(required=True))
  • 但我需要一个两者都不存在的选项。因此,如果用户只发送 lat 它应该会失败,如果他没有提供应该可以的 lat 或 lng,lng 只会失败。
  • 如果是这样,我认为最好也是唯一的选择是定义一个 validate() 方法或泛型 Validator 类

标签: django django-rest-framework


【解决方案1】:

您应该使用序列化程序validate 方法来检查这一点。

class MySerializer(serializers.ModelSerializer):
    lat = serializers.FloatField(required=False)
    lng = serializers.FloatField(required=False)

    def validate(self, data):
        if not data['lat'] and not data['lng']:
            raise serializers.ValidationError("They are both required.")
    return data

参考:http://www.django-rest-framework.org/api-guide/serializers/#object-level-validation

【讨论】:

  • 请注意,我写道,我知道我可以使用 validate 函数来做到这一点,并且我正在寻找一种更好的方法,因为对于一个具有许多选项的复杂序列化程序,我看不到它是如何扩展的,而且它变得非常不可读。另外,请注意您的解决方案有问题,因为它不支持排除两者的选项(它们不需要作为一对,但只要它们中的一个都是必需的)这正好说明了为什么必须另一个解决方案:)
【解决方案2】:

这是一个如何将 mixin 写入 Serializer 的示例,这将允许 有条件地要求字段。示例见文档字符串

class ConditionalRequiredMixin:
    """
    Adds flexibility to required fields by setting up `conditional_required_fields`

    For example
        conditional_required_fields = [
        ('is_blind': {
            'condition': False,
            'required_fields': ['clock', 'naming', 'alternate_trail_making', 'cube_drawing']
        }),
        ('is_blind': {
            'condition': True,
            'required_fields': ['clock2', 'naming2',]
        })
    ]

    If is_blind will be False -> fields specified in required_fields will be required

    """
    REQUIRED_MSG = ['Field is required']
    conditional_required_fields = []

    def validate(self, attrs):
        attrs = super().validate(attrs)
        for master_field, conditions in self.conditional_required_fields:
            master_field_value = attrs.get(master_field)
            condition = conditions['condition']
            if not isinstance(condition, str) and isinstance(condition, collections.Iterable):
                trigger = master_field_value in condition
            else:
                trigger = master_field_value == condition

            if trigger:
                additional_required_fields = conditions['required_fields']
                absent_fields = [f for f in additional_required_fields if attrs.get(f) is None]
                if absent_fields:
                    error_dict = {f: self.REQUIRED_MSG for f in absent_fields}
                    raise serializers.ValidationError(error_dict)
        return attrs

【讨论】:

    猜你喜欢
    • 2012-06-13
    • 1970-01-01
    • 2021-03-19
    • 2020-02-18
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    相关资源
    最近更新 更多