当前位置: 首页 > 科技观察

Sentry开发者贡献指南-DjangoRestFramework(Serializers)

时间:2023-03-12 10:14:18 科技观察

转载本文请联系黑客下午茶公众号。Serializer用于获取复杂的python模型并将它们转换为json。序列化程序也可用于在验证传入数据后将json反序列化回Python模型。在Sentry中,我们有两种不同类型的序列化器:DjangoRestFrameworkSerializer和ModelSerializer。DjangoRestFrameworkDjangoRestFramework序列化程序用于处理进入Sentry的输入验证和数据转换。https://www.django-rest-framework.org/示例在典型的序列化程序中,指定字段以便它们根据您的规范验证数据的类型和格式。如果写入符合模型,DjangoRestFramework序列化程序也可以将信息保存到数据库中。fromrest_frameworkimportserializersfromsentry.api.serializers.rest_frameworkimportValidationErrorclassExampleSerializer(serializers.Serializer):name=serializers.CharField()age=serializers.IntegerField(required=False)type=serializers.CharField()defvalidate_type(self:attrs=attrs[源代码]源代码)['bear','rabbit','puppy']:raiseValidationError('%sisnotavalidtype'%type)returnattrsfieldcheck在上面的示例中,序列化程序将接受并验证包含三个字段的JSON:name、age和type。其中名称和类型必须是字符串,年龄必须是建议的整数。默认情况下需要字段,如果未提供,将被序列化程序标记为无效。请注意,整数字段age,required设置为False。所以可能不包括在内,序列化程序仍将被视为有效。自定义验证对于需要自定义验证(简单类型检查除外)的值,可以创建defvalidate_(self,attrs,source),其中替换为给定字段的确切变量名。因此,例如,如果我有一个名为typeName的字段,则验证方法名称将为validate_typeName,如果我有一个名为type_name的字段,则验证方法名称将为validate_type_name。在上面给出的例子中,类型被检查并且必须是一些字符串。如果某个字段与您的验证方法所期望的不匹配,则会引发ValidationError。用法在端点中,这是DjangoRestFrameworkSerializerclassExampleEndpoint(Endpoint):defpost(self,request):serializer=ExampleSerializer(request.DATA)ifnotserializer.is_valid():returnResponse(serializer.errors,status=400)的典型用法结果=序列化器.object#AssumingExampleisamodelwiththesamefieldstry:withtransaction.atomic():Example.objects.create(name=result['name'],age=result.get('age'),type=result['type'],)exceptIntegrityError:returnResponse('Thisexamplealreadyexists',status=409)returnResponse(serialize(result,request.user),status=201)ValidationdataDjangoRestFramework中的Serializer将对需要验证的传入数据使用方法(即put和post方法)).实例化序列化程序后,您可以调用serializer.is_valid()来验证数据。serializer.errors将给出有关给定数据无效的具体反馈。例如,给定{'age':5,'type':'puppy'}的输入,序列化程序将返回一个错误,指出未提供必需的字段名称。保存数据确认数据有效后,可以通过以下两种方式之一保存数据。上面给出的例子是哨兵中最常见的。获取只是验证数据的serializer.object(如果serializer.is_valid()返回False则为None)并使用.objects.create将该数据直接保存在模型中。另一种方法使用更多DjangoRestFramework的特性,ModelSerializerfromrest_frameworkimportserializersfromsentry.api.serializers.rest_frameworkimportValidationErrorclassExampleSerializer(serializer.ModelSerializer):name=serializers.CharField()age=serializers.IntegerField(required=False)type=serializersmodel:classeliders().Character=Exampledefvalidate_type(self,attrs,source):type=attrs[source]iftypenotin['bear','rabbit','puppy']:raiseValidationError('%sisnotavalidtype'%type)returnattrsclassExampleEndpoint(端点):defpost(self,请求):serializer=ExampleSerializer(request.DATA)ifnotserializer.is_valid():returnResponse(serializer.errors,status=400)example=serializer.save()returnResponse(serialize(example,request.user),status=201)模型序列化器哨兵的模型序列化程序仅用于传出数据。典型的模型序列化程序如下所示:https://github.com/getsentry/sentry/blob/master/src/sentry/api/serializers/base.py@register(Example)classExampleSerializer(Serializer):defget_attrs(self,item_list,user):attrs={}types=ExampleTypes.objects.filter(type_name__in=[i.typeforiinitem_list])foriteminitem_list:attrs[item]={}attrs[item]['type']=[tfortintypesift.name==item.type_name]returnattrsdefserialize(self,obj,attrs,user):return{'name':obj.name,'type':attrs['type'],'age':obj.age,}registerModelSerializerdecorator@的需要注册以便`returnResponse(serialize(example,request.user),status=201)`起作用。在这种情况下,它会在后台搜索匹配的模型示例,给定变量示例的模型类型。要将模型序列化器与模型相匹配,您只需要实现@register()classModelSerializer(Serializer):...get_attrs方法为什么在DjangoRestFramework具有类似功能时执行此操作?get_attrs方法就是原因。它允许您执行批量查询而不是多个查询。在我们的示例中,我可以过滤我想要的项目并使用python将它们分配给相关项目,而不是为多个项目调用ExampleTypes.objects.get(...)。在attr字典的情况下,键是项目本身。value是一个字典,包含要添加的属性的名称及其值。attrs[item]={'attribute_name':attribute}Serialize方法最后,您返回一个包含json可序列化信息的字典,该信息将与响应一起返回。