【问题标题】:How to remove extra data from JSONField in django rest framework?如何从 django rest 框架中的 JSONField 中删除额外的数据?
【发布时间】:2021-04-15 03:35:49
【问题描述】:

我有一个这样的模型:

class Things(models.Model):
    data = models.JSONField(default=dict)

data的结构是这样的:

{
   "item" : "sugar",
   "quantity" : "2",
   "cost" : 220
}

请注意,data 不是必须包含所有 3 个键,它们都是可选的。

困难的部分是我不希望除这 3 个键之外的任何其他键出现在 data 字段中。

创建序列化程序有助于确保这 3 个字段的存在和格式,但不能确保其他字段不存在。我怎样才能在 django rest 框架中实现这个东西?

【问题讨论】:

  • 你能告诉我一些预期的输入和输出示例吗?
  • 您可以使用字段级验证器来验证传入的数据
  • 在序列化程序中创建一个 validate_ 函数。你可能会是def validate_data(self, incoming_data)

标签: django django-rest-framework django-jsonfield


【解决方案1】:

您可以在序列化程序中验证该字段:

class ThingsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Things
        fields = ['data']

    def validate_data(self, value):
        # You can validate, clean and change your data
        final_data = {
            "item": value.get("item"),
            "quantity": value.get("quantity"),
            "cost": value.get("cost", 0)
        }
        return final_data

您还可以为数据字段创建单独的序列化程序并将值传递给它,验证那里的每个字段并返回最终数据。但是,如果您的字段有限且简单,则应该这样做。

【讨论】:

  • 如果 ("item", "quantity", "cost") 中的某个键不存在怎么办?
  • 如果有大量的键怎么办,比如说100个。
  • 如果一个键不存在,那么.get() 会返回一个None,所以如果你愿意,你可以检查它并返回一个错误。如果键的数量很多,那么不要一一检查,而是创建一个列表或元组并将允许的键放在那里,然后使用 for 循环来检查和验证它​​们。
【解决方案2】:

通过在序列化程序级别使用validate_<field_name>,您还可以创建一个逻辑来确保data 内的所有字段都需要填写。

class ThingsSerializer(serializers.ModelSerializer):
     data = serializers.JSONField()
 
     class Meta:
         model = Things
         fields = ('data', )
 
     def validate_data(self, data):
         valid_keys = ('item', 'quantity', 'cost')
         errors = []
         out_data = {}
 
         for key in valid_keys:
             if key in data.keys():
                 if data.get(key):
                     out_data[key] = data.get(key)
                 else:
                     errors.append({key: 'This field should be filled.'})
             else:
                 errors.append({key: 'This field is required'})
 
         if len(errors) > 0:
             raise serializers.ValidationError(errors)
         return out_data

这里是测试:

In [25]: s = ThingsSerializer(data={'data': {'item': 'sugar', 'quantity': 2, 'cost': 20}})

In [26]: s.is_valid()
Out[26]: True

In [27]: s.errors
Out[27]: {}



In [28]: s = ThingsSerializer(data={'data': {'item': 'sugar', 'quantity': 2}})

In [29]: s.is_valid()
Out[29]: False

In [30]: s.errors
Out[30]: {'data': [{'cost': ErrorDetail(string='This field is required', code='invalid')}]}



In [34]: s = ThingsSerializer(data={'data': {'item': 'sugar', 'quantity': 2, 'cost': None}})

In [35]: s.is_valid()
Out[35]: False

In [36]: s.errors
Out[36]: {'data': [{'cost': ErrorDetail(string='This field should be filled.', code='invalid')}]}

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 2016-08-09
    • 2018-08-02
    • 2018-06-29
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多