Creating Custom Model Field Validator
Introduction
There should be some point when we need validation on data while maintaining service. For instance,
- Users should not include special characters or whitespace for their name field while creating account.
- Purchase date should not be earlier than today's date.
- Discount price should be less than the original price.
and so forth.
Examples
1. Lookbook season year
Lookbook is a collection data of recommended products by Knower admin team corresponding to each year's season, so as to strive for better UX by letting customers search a variety of products. Lookbook season code consists of 2 model fields, which are year and season (SS & FW).
As lookbook shows products collection for the future, year of lookbook should be future as well.
For this, I decided to pass Validator (opens in a new tab) for that field (opens in a new tab) with validators
property.
Creating Custom Validator Function
Create validator function for generating lookbook season code.
Calculating year
From Python's built-in datetime (opens in a new tab) module, I extracted year
(opens in a new tab) data for catching lookbook's year.
Then, I let Django trigger ValidationError
(opens in a new tab) when lookbook's year(year
) is lesser than real time's year(this_year
) (e.g. past).
Excluding Invalid Format of Year
Also, I triggered ValidationError
when user provided extremely big unit of year (e.g. 12345).
Setting Lookbook Year Cap
There was no need for showing future products for no less than 2 years. Therefore, I also put this logic into my validator function.
Adapting Validator
I adapted my custom validator for year
field.
Calculating year
From Python's built-in datetime (opens in a new tab) module, I extracted year
(opens in a new tab) data for catching lookbook's year.
Then, I let Django trigger ValidationError
(opens in a new tab) when lookbook's year(year
) is lesser than real time's year(this_year
) (e.g. past).
Excluding Invalid Format of Year
Also, I triggered ValidationError
when user provided extremely big unit of year (e.g. 12345).
2. Discount Price of Product
Discount price is not required field, but its value should always be less than the original price.
Using clean()
Method
In order to carry out validator on model perspective, that is when you want to carry out validation while creating new QuerySet, you may use clean()
(opens in a new tab) with ease.
First, I initialized clean()
method.
class Product(models.Model): # ... def clean(self): super().clean()
Setting Validator's Logic
Validator will work only when there is discount_price
, and if discount_price
is bigger or equal to the original price, I triggered ValidationError
as well.
class Product(models.Model): # ... def clean(self): if self.discount_price: if self.discount_price >= self.price: raise ValidationError("할인가가 원가보다 같거나 높을 수는 없습니다.") super().clean()
Using clean()
Method
In order to carry out validator on model perspective, that is when you want to carry out validation while creating new QuerySet, you may use clean()
(opens in a new tab) with ease.
First, I initialized clean()
method.
class Product(models.Model): # ... def clean(self): super().clean()