Click to jump to the REST-Framework column directory
When you use the REST framework for validation processing, you might just rely on the default field validation or use explicit validation on serializer, but if you put the validation logic in a reusable component, you can reuse the code and reduce redundancy. This can be done by validating classes or functions.
Example description:
class CustomerReportRecord(models.Model) :
time_raised = models.DateTimeField(default=timezone.now, editable=False)
reference = models.CharField(unique=True, max_length=20)
description = models.TextField()
Copy the code
CustomerReportSerializer is the basis for creating or updating instances of CustomerReportRecord:
class CustomerReportSerializer(serializers.ModelSerializer) :
class Meta:
model = CustomerReportRecord
Copy the code
Using Django-shell, you can execute to get the following information:
>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
id = IntegerField(label='ID', read_only=True)
time_raised = DateTimeField(read_only=True)
reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
description = CharField(style={'type': 'textarea'})
Copy the code
UniqueValidator
Validation class for model field constraints with unique=True.
parameter
queryset
: mandatory parameter for the query set that executes the constraintmessage
: Error message returned after authentication failurelookup
: Lookup for finding existing instances with values being validated. The default is"exact"
The sample
from rest_framework.validators import UniqueValidator
class. :. slug = SlugField( max_length=100,
validators=[UniqueValidator(queryset=BlogPost.objects.all()))Copy the code
UniqueTogetherValidator
This validation class is used for combination constraints under multiple fields.
parameter
queryset
: mandatory parameter for the query set that executes the constraintmessage
: Error message returned after authentication failurefields
: mandatory argument, used to combine a list of fields or tuples of unique constraints
The sample
from rest_framework.validators import UniqueTogetherValidator
class ExampleSerializer(serializers.Serializer) :.class Meta:
validators = [
UniqueTogetherValidator(
queryset=ToDoItem.objects.all(),
fields=['list'.'position']]Copy the code
UniqueForMonthValidator, UniqueForYearValidator
These three validation classes are used to constrain the time model field.
parameter
queryset
: mandatory parameter for the query set that executes the constraintmessage
: Error message returned after authentication failurefield
: Mandatory parameter, time field name for the constraintdate_field
: mandatory argument used to determine the date range of the uniqueness constraint
The sample
from rest_framework.validators import UniqueForYearValidator
class ExampleSerializer(serializers.Serializer) :.class Meta:
validators = [
UniqueForYearValidator(
queryset=BlogPostItem.objects.all(),
field='slug',
date_field='published')]Copy the code
Serializer always requires a date field for validation. You can’t simply rely on the model class Default =… Because the values used for default values are not generated until validation runs.
Depending on how you want the API to behave, you may need to use some styles, and if you are using ModelSerializer, you may just rely on the default values generated for you by the REST Framework, But if you’re using Serializer or just want more explicit control, use one of the styles demonstrated below.
Used with writable date fields
If you want the date field to be writable, the only thing to note is that you can ensure that the date field in the input data is always available by setting the default parameter or required=True.
published = serializers.DateTimeField(required=True)
Copy the code
Used with read-only date fields
If you want the date field to be visible but not editable by the user, set read_only=True and an additional default=… Parameters.
published = serializers.DateTimeField(read_only=True, default=timezone.now)
Copy the code
Use with hidden date fields
If you want the date field to be completely hidden from the user, use the HiddenField, which does not accept user input but always returns its default value to validATED_data in the serializer.
published = serializers.HiddenField(default=timezone.now)
Copy the code
Default value Advanced usage
CurrentUserDefault
The default class that can be used to represent the current user. If you want to use it, ‘request’ must be provided as part of the context dictionary when instantiating the serializer.
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
Copy the code
CreateOnlyDefault
Used as a default value at creation time and ignored during update operations.
created_at = serializers.DateTimeField(
default=serializers.CreateOnlyDefault(timezone.now)
)
Copy the code
Complex validation
In cases where explicit validation is not sufficient for your validation needs, overriding the validate method in the Serializer class is a good idea.
class BillingRecordSerializer(serializers.ModelSerializer) :
def validate(self, attrs) :
# Apply custom validation either here, or in the view.
class Meta:
fields = ['client'.'date'.'amount']
extra_kwargs = {'client': {'required': False}}
validators = [] # Remove a default "unique together" constraint.
Copy the code
Custom authentication
The validator is can trigger serializers. Any callable object ValidationError anomalies, such as:
def even_number(value) :
if value % 2! =0:
raise serializers.ValidationError('This field must be an even number.')
Copy the code
Of course, you can use the Serializer you define to validate a particular field as follows:
class BillingRecordSerializer(serializers.ModelSerializer) :
def validate_title(self, attrs) :
# Apply custom validation either here, or in the view.
Copy the code
The format is to define the.validate_
method in Serializer.
The __call__ method can be overridden by defining the validator as a class, which is more reusable:
class MultipleOf:
def __init__(self, base) :
self.base = base
def __call__(self, value) :
ifvalue % self.base ! =0:
message = 'This field must be a multiple of %d.' % self.base
raise serializers.ValidationError(message)
Copy the code
In some advanced cases, you might want to pass the serializer field used with it to the validator as an additional context, which you can do by setting the requiRES_context = True attribute on the validator, The __call__ method is then called with serializer_field or serializer as additional arguments.
requires_context = True
def __call__(self, value, serializer_field) :.Copy the code