Serializer is used to take complex Python models and convert them to JSON. The serializer can also be used to deserialize JSON back into the Python model after validating incoming data.
At Sentry, we have two different types of Serializer: Django Rest Framework Serializer and Model Serializer.
Django Rest Framework
The Django Rest Framework serializer handles input validation and conversion of data entering a Sentry.
- www.django-rest-framework.org/
The sample
In a typical Serializer, fields are specified so that they validate the type and format of the data against your specification. The Django Rest Framework serializer can also save information to the database if writing is appropriate for the Model.
from rest_framework import serializers
from sentry.api.serializers.rest_framework import ValidationError
class ExampleSerializer(serializers.Serializer) :
name = serializers.CharField()
age = serializers.IntegerField(required=False)
type = serializers.CharField()
def validate_type(self, attrs, source) :
type = attrs[source]
if type not in ['bear'.'rabbit'.'puppy'] :raise ValidationError('%s is not a valid type' % type)
return attrs
Copy the code
Field inspection
In the above example, serializer will accept and validate JSON containing three fields: Name, age, and Type. Where name and type must be strings, and age must be the suggested INTEGER. By default, the field is required, and serializer will be marked as invalid if it is not provided. Note that the INTEGER field age,required is set to False. Therefore, Serializer may not be included and will still be considered valid.
Custom authentication
For values that require custom validation (other than simple type checking),
def validate_<variable_name>(self, attrs, source)
You can create where
is replaced with the exact variable name for the given field. So, for example, if I have a field name typeName, the validation method name will be validate_typeName, and if I have a field named type_name, the validation method name will be validate_type_name. In the example given above, the type is checked and must be some string. If a field does not match what your validation method expects, a ValidationError is raised.
usage
In endpoint, this is a typical use of Django Rest Framework Serializer
class ExampleEndpoint(Endpoint) :
def post(self, request) :
serializer = ExampleSerializer(request.DATA)
if not serializer.is_valid():
return Response(serializer.errors, status=400)
result = serializer.object
#Assuming Example is a model with the same fields
try:
with transaction.atomic():
Example.objects.create(
name=result['name'],
age=result.get('age'),
type=result['type'],)except IntegrityError:
return Response('This example already exists', status=409)
return Response(serialize(result, request.user), status=201)
Copy the code
Validation data
The Serializer from the Django Rest Framework will be used for methods that need to validate incoming data (that is, the PUT and POST methods). Once the serializer is instantiated, you can call serializer.is_Valid () to validate the data. Serializer. Errors will give specific feedback about the invalidity of a given data.
For example, given input
{
'age':5.'type':'puppy'
}
Copy the code
Serializer will return an error indicating that the required field name was not provided.
Save the data
After confirming that the data is valid, you can save the data in either of the following ways. The example given above is the most common in Sentry. Take serializer. Object, which is just the validated data (if serializer.is_valid() returns False, None) and use
.objects.create to save the data directly in the model.
Another approach uses one more feature of the Django Rest Framework, ModelSerializer
from rest_framework import serializers
from sentry.api.serializers.rest_framework import ValidationError
class ExampleSerializer(serializer.ModelSerializer) :
name = serializers.CharField()
age = serializers.IntegerField(required=False)
type = serializers.CharField()
class Meta:
model = Example
def validate_type(self, attrs, source) :
type = attrs[source]
if type not in ['bear'.'rabbit'.'puppy'] :raise ValidationError('%s is not a valid type' % type)
return attrs
class ExampleEndpoint(Endpoint) :
def post(self, request) :
serializer = ExampleSerializer(request.DATA)
if not serializer.is_valid():
return Response(serializer.errors, status=400)
example = serializer.save()
return Response(serialize(example, request.user), status=201)
Copy the code
Model Serializer
Sentry’s Model Serializers are only used for outgoing data. A typical Model Serializer looks like this:
- Github.com/getsentry/s…
@register(Example)
class ExampleSerializer(Serializer) :
def get_attrs(self, item_list, user) :
attrs = {}
types = ExampleTypes.objects.filter(
type_name__in=[i.type for i in item_list]
)
for item in item_list:
attrs[item] = {}
attrs[item]['type'] = [t for t in types if t.name == item.type_name]
return attrs
def serialize(self, obj, attrs, user) :
return {
'name':obj.name,
'type':attrs['type'].'age': obj.age,
}
Copy the code
The registered Model Serializer
Decorator @register is required in order to
`return Response(serialize(example, request.user), status=201) `Copy the code
Works. In this case, it searches in the background for the matching model Example, given the model type of the variable Example. To match the Model Serializer with the Model, you simply execute
@register(<ModelName>)
class ModelSerializer(Serializer) :.Copy the code
Get_attrs method
Why do this when Django Rest Framework has similar functionality? The get_attrs method is the reason. It allows you to perform batch queries instead of multiple queries. In our example, INSTEAD of calling exampletypes.objects.get (…), I can filter the items I want and assign them to the related items using Python. More than one item. In the case of the ATTR dictionary, the key is the item itself. And value is a dictionary that contains the name of the attribute to be added and its value.
attrs[item] = {'attribute_name': attribute}
Copy the code
Serialize method
Finally, you return a dictionary with JSON-serializable information, which is returned with response.
More and more
- Sentry Enterprise level Data security solution – Relay getting started