Introduction to Data Validation
In this tutorial, you'll learn about Data Validation. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Data validation verifies that input data conforms to expected formats, types, and constraints before it reaches business logic or storage.
What You'll Learn
By the end of this lesson, you will understand validation layers, classify validation types, and implement a basic validation system.
Why It Matters
Invalid data causes crashes, security vulnerabilities, and data corruption. Every application must validate data at every entry point.
Real-World Use
Durga Antivirus Pro validates file signatures before scanning. Invalid or corrupted files are rejected before any analysis, saving processing time and preventing crashes.
Validation Layers
flowchart TD
Input[User Input] --> Client[Client Validation]
Client --> Network[Network]
Network --> Server[Server Validation]
Server --> DB[Database Constraints]
DB --> Storage[Storage]
Basic Validator
# basic_validator.py
from typing import Any, Dict, List, Optional
class DataValidator:
def validate_string(self, value: Any, min_len: int = 1,
max_len: Optional[int] = None) -> List[str]:
errors = []
if not isinstance(value, str):
errors.append("Must be a string")
else:
if len(value) < min_len:
errors.append(f"Minimum {min_len} characters")
if max_len and len(value) > max_len:
errors.append(f"Maximum {max_len} characters")
return errors
def validate_number(self, value: Any, min_val: Optional[float] = None,
max_val: Optional[float] = None) -> List[str]:
errors = []
if not isinstance(value, (int, float)):
errors.append("Must be a number")
else:
if min_val is not None and value < min_val:
errors.append(f"Minimum value {min_val}")
if max_val is not None and value > max_val:
errors.append(f"Maximum value {max_val}")
return errors
def validate_email(self, value: Any) -> List[str]:
errors = []
if not isinstance(value, str):
errors.append("Email must be a string")
elif "@" not in value or "." not in value.split("@")[-1]:
errors.append("Invalid email format")
return errors
v = DataValidator()
print(f"String 'abc': {v.validate_string('abc', min_len=2)}")
print(f"String 'a': {v.validate_string('a', min_len=2)}")
print(f"Num 42: {v.validate_number(42, min_val=0, max_val=100)}")
print(f"Num -1: {v.validate_number(-1, min_val=0)}")
print(f"Email ok: {v.validate_email('user@example.com')}")
print(f"Email bad: {v.validate_email('invalid')}")
Expected output:
String 'abc': []
String 'a': ['Minimum 2 characters']
Num 42: []
Num -1: ['Minimum value 0']
Email ok: []
Email bad: ['Invalid email format']
Validation Classifier
# validator_classifier.py
from typing import Any, Dict, List
class ValidationClassifier:
TYPE_CHECK = "type_check"
FORMAT_CHECK = "format_check"
RANGE_CHECK = "range_check"
PRESENCE_CHECK = "presence_check"
BUSINESS_RULE = "business_rule"
@staticmethod
def classify(rule_name: str) -> str:
classifiers = {
"required": ValidationClassifier.PRESENCE_CHECK,
"type": ValidationClassifier.TYPE_CHECK,
"email": ValidationClassifier.FORMAT_CHECK,
"min": ValidationClassifier.RANGE_CHECK,
"max": ValidationClassifier.RANGE_CHECK,
"min_length": ValidationClassifier.RANGE_CHECK,
"match_password": ValidationClassifier.BUSINESS_RULE,
}
return classifiers.get(rule_name, ValidationClassifier.BUSINESS_RULE)
rules = ["required", "type", "email", "min", "match_password"]
for rule in rules:
print(f" {rule:20s} -> {ValidationClassifier.classify(rule)}")
Expected output:
required -> presence_check
type -> type_check
email -> format_check
min -> range_check
match_password -> business_rule
Common Mistakes
1. Trusting Client Validation
Client validation is for UX. Server validation is mandatory for security.
2. Only Checking Format, Not Semantics
A valid email format does not mean the email exists. Different checks verify different things.
3. No Validation at All Entry Points
APIs, file uploads, command-line arguments, Message Queues — all entry points need validation.
4. Inconsistent Rules
Same field validated differently in different endpoints. Centralize validation rules.
5. Letting Invalid Data Reach the Database
Always validate before database operations. DB constraints are a last resort.
Practice Questions
1. What is data validation?
The Process of verifying input data meets expected types, formats, and constraints.
2. How many validation layers are there?
Four: client, network, server, database. Server validation is the most important.
3. What is the difference between format and semantic validation?
Format checks structure (email has @), semantics checks meaning (email exists).
4. Why is database validation not enough?
DB errors are hard to handle gracefully. Validate early, in application code.
Challenge
Build a validation system for a user registration with 6+ field validators, collecting all errors, with clear messages for each violation.
FAQ
Mini Project: Validator Class
# validator_class.py
from typing import Any, Dict, List
class Validator:
def __init__(self):
self.rules: Dict[str, List] = {}
def add(self, field: str, rule: callable):
self.rules.setdefault(field, []).append(rule)
def validate(self, data: Dict) -> Dict[str, List[str]]:
errors = {}
for field, rules in self.rules.items():
val = data.get(field)
for rule in rules:
err = rule(field, val, data)
if err:
errors.setdefault(field, []).append(err)
return errors
v = Validator()
v.add("name", lambda f, v, d: "required" if not v else None)
v.add("age", lambda f, v, d: "must be int" if not isinstance(v, int) else None)
print(v.validate({"name": "", "age": "30"}))
print(v.validate({"name": "Alice", "age": 30}))
Expected output:
{'name': ['required'], 'age': ['must be int']}
{}
What's Next
You understand data validation basics. Next, learn client vs server validation, then required fields.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro