Sentry 开发者贡献指南 - Django Rest Framework(Serializers)
开发 前端
Serializer 用于获取复杂的 python 模型并将它们转换为 json。序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型。

本文转载自微信公众号「黑客下午茶」,作者为少 。转载本文请联系黑客下午茶公众号。

Serializer 用于获取复杂的 python 模型并将它们转换为 json。序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型。

在 Sentry,我们有两种不同类型的序列化器 :Django Rest Framework Serializer 和 Model Serializer。

Django Rest Framework

Django Rest Framework 序列化程序用于处理进入 Sentry 的数据的输入验证和转换。

  • https://www.django-rest-framework.org/

示例

在典型的 serializer 中,指定了字段,以便它们根据您的规范验证数据的类型和格式。如果写入适合 model,Django Rest Framework 序列化程序还可以将信息保存到数据库中。

  1. from rest_framework import serializers 
  2. from sentry.api.serializers.rest_framework import ValidationError 
  3.  
  4. class ExampleSerializer(serializers.Serializer): 
  5.     name = serializers.CharField() 
  6.     age = serializers.IntegerField(required=False
  7.     type = serializers.CharField() 
  8.  
  9.     def validate_type(self, attrs, source): 
  10.         type = attrs[source] 
  11.         if type not in ['bear''rabbit''puppy']: 
  12.             raise ValidationError('%s is not a valid type' % type) 
  13.     return attrs 

字段检查

在上面的示例中, serializer 将接受并验证包含三个字段的 json:name、age 和 type。其中 name 和 type 必须是strings, age 必须是建议的 integer。默认情况下,字段是必需的,如果不提供,serializer 将标记为无效。请注意,integer 字段 age,required 设置为 False。因此可能不包括在内,serializer 仍将被视为有效。

自定义验证

对于需要自定义验证的值(除了简单的类型检查),

def validate_(self, attrs, source)

可以创建其中 替换为给定字段的确切变量名称。因此,例如,如果我有一个字段名称 typeName,验证方法名称将是 validate_typeName, 而如果我有一个名为 type_name 的字段,验证方法名称将是 validate_type_name。在上面给出的示例中,类型被检查并且必须是某个字符串。如果某个字段与您的验证方法所期望的不匹配,则会引发 ValidationError。

用法

在 endpoint 中,这是 Django Rest Framework Serializer 的典型用法

  1. class ExampleEndpoint(Endpoint): 
  2.     def post(self, request): 
  3.         serializer = ExampleSerializer(request.DATA) 
  4.         if not serializer.is_valid(): 
  5.             return Response(serializer.errors, status=400) 
  6.  
  7.         result = serializer.object 
  8.  
  9.         #Assuming Example is a model with the same fields  
  10.         try: 
  11.             with transaction.atomic(): 
  12.                 Example.objects.create
  13.                     name=result['name'], 
  14.                     age=result.get('age'), 
  15.                     type=result['type'], 
  16.                 ) 
  17.         except IntegrityError: 
  18.             return Response('This example already exists', status=409) 
  19.  
  20.         return Response(serialize(result, request.user), status=201) 

验证数据

来自 Django Rest Framework 的 Serializer 将用于需要验证的传入数据的方法(即 put 和 post 方法)。一旦序列化器被实例化,你可以调用 serializer.is_valid() 来验证数据。 serializer.errors 将给出关于给定数据无效的具体反馈。

例如给定的输入

  1.     'age':5, 
  2.     'type':'puppy' 

serializer 将返回一个错误,指出未提供所需的字段名称。

保存数据

确认数据有效后,您可以通过以下两种方式之一保存数据。上面给出的例子是 sentry 中最常见的。取 serializer.object,它只是经过验证的数据(如果 serializer.is_valid() 返回 False,则为 None) 并使用 .objects.create 将该数据直接保存在 model 中.

另一种方法使用了更多的 Django Rest Framework 的特性, ModelSerializer

  1. from rest_framework import serializers 
  2. from sentry.api.serializers.rest_framework import ValidationError 
  3.  
  4. class ExampleSerializer(serializer.ModelSerializer): 
  5.     name = serializers.CharField() 
  6.     age = serializers.IntegerField(required=False
  7.     type = serializers.CharField() 
  8.  
  9.     class Meta: 
  10.         model = Example 
  11.   
  12.     def validate_type(self, attrs, source): 
  13.         type = attrs[source] 
  14.         if type not in ['bear''rabbit''puppy']: 
  15.             raise ValidationError('%s is not a valid type' % type) 
  16.         return attrs 
  17.  
  18. class ExampleEndpoint(Endpoint): 
  19.     def post(self, request): 
  20.         serializer = ExampleSerializer(request.DATA) 
  21.         if not serializer.is_valid(): 
  22.             return Response(serializer.errors, status=400) 
  23.  
  24.         example = serializer.save() 
  25.         return Response(serialize(example, request.user), status=201) 

Model Serializer

Sentry's Model Serializers 仅用于传出数据。典型的 model serializer 如下所示:

  • https://github.com/getsentry/sentry/blob/master/src/sentry/api/serializers/base.py
  1. @register(Example) 
  2. class ExampleSerializer(Serializer): 
  3.     def get_attrs(self, item_list, user): 
  4.         attrs = {} 
  5.         types = ExampleTypes.objects.filter( 
  6.             type_name__in=[i.type for i in item_list] 
  7.         ) 
  8.  
  9.         for item in item_list: 
  10.             attrs[item] = {} 
  11.             attrs[item]['type'] = [t for t in types if t.name == item.type_name] 
  12.         return attrs 
  13.  
  14.     def serialize(self, obj, attrs, user): 
  15.         return { 
  16.             'name':obj.name
  17.             'type':attrs['type'], 
  18.             'age': obj.age, 
  19.         } 

注册 Model Serializer

装饰器 @register 是必需的,以便

  1. `return Response(serialize(example, request.user), status=201)` 

works. 在这种情况下,它会在后台搜索匹配的模型 Example, 给定变量 example 的 model 类型。要将 model serializer 与 Model 匹配,您只需执行

  1. @register(<ModelName>) 
  2. class ModelSerializer(Serializer): 
  3. ... 

get_attrs 方法

当 Django Rest Framework 具有类似功能时,为什么要这样做? get_attrs 方法就是原因。它允许您执行批量查询而不是多个查询。在我们的示例中,我可以过滤我想要的 item,并使用 python 将它们分配给相关 item, 而不是调用 ExampleTypes.objects.get(...) 多个 item。在 attr 字典的情况下,key 是 item 本身。并且 value 是一个字典,其中包含要添加的属性的名称及其值。

  1. attrs[item] = {'attribute_name': attribute} 

Serialize 方法

 

最后,您返回一个带有 json 可序列化信息的字典,该信息将与 response 一起返回。

 

责任编辑:武晓燕 来源: 黑客下午茶

同话题下的热门内容

YouTube-DL 官网托管平台被三大唱片公司起诉Podman与Docker有什么不同?腾讯研发动画组件,以后动画制作用PAGRedis 使用 List 实现消息队列的利与弊面试突击:为什么HashMap会产生死循环? 2022 Web 前端面试题及答案之JavaScript 篇Three.js 的 3D 粒子动画:群星送福细说Java中的空指针异常

编辑推荐

太厉害了,终于有人能把TCP/IP协议讲的明明白白了!Javascript如何监听页面刷新和关闭事件利用Pytorch进行CNN详细剖析面试 | 必须要会的50个React面试题一份全面的React、Angular和Vue.js比较指南
我收藏的内容
点赞
收藏

51CTO技术栈视频号