ValidationException API Reference
The ValidationException
class is raised when field validation fails in PyValidX models.
Class Definition
class ValidationException(Exception):
'''
Exception raised when validation fails.
Attributes:
status_code (int): HTTP status code (default: 400)
validations (Dict[str, str]): Dictionary of field names and error messages
'''
Attributes
status_code: int
The HTTP status code associated with the validation error.
Default: 400
(Bad Request)
Example:
try:
user = User(name='', email='invalid-email')
except ValidationException as e:
print(e.status_code) # 400
validations: Dict[str, str]
A dictionary containing field names as keys and their corresponding error messages as values.
Example:
try:
user = User(name='', email='invalid-email')
except ValidationException as e:
print(e.validations)
# {'name': 'This field is required', 'email': 'Invalid email format'}
Methods
to_dict() -> Dict[str, Any]
Returns the exception as a dictionary containing both status code and validation errors.
Returns:
- Dict[str, Any]
: Dictionary with status_code
and validations
keys
Example:
try:
user = User(name='', email='invalid-email')
except ValidationException as e:
error_dict = e.to_dict()
print(error_dict)
# {
# 'status_code': 400,
# 'validations': {
# 'name': 'This field is required',
# 'email': 'Invalid email format'
# }
# }
to_json() -> str
Returns the exception as a JSON string.
Returns:
- str
: JSON string containing the exception information
Example:
try:
user = User(name='', email='invalid-email')
except ValidationException as e:
json_string = e.to_json()
print(json_string)
# {'status_code': 400, 'validations': {'name': 'This field is required', 'email': 'Invalid email format'}}
Usage Examples
Basic Error Handling
from pyvalidx import ValidatedModel, field_validated
from pyvalidx.core import is_required
from pyvalidx.string import is_email
from pyvalidx.exception import ValidationException
class User(ValidatedModel):
name: str = field_validated(is_required())
email: str = field_validated(is_required(), is_email())
try:
user = User(name='', email='invalid-email')
except ValidationException as e:
print(f'Validation failed with status {e.status_code}')
for field, message in e.validations.items():
print(f'- {field}: {message}')
Web API Error Response
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/users', methods=['POST'])
def create_user() -> tuple[dict, int]:
'''
Create a new user.
Returns:
tuple: Tuple of (response, status_code)
'''
try:
user_data = request.get_json()
user = User(**user_data)
return jsonify({'success': True, 'user': user.dict()}), 201
except ValidationException as e:
return jsonify(e.to_dict()), e.status_code
Custom Error Handling
def handle_validation_error(e: ValidationException) -> dict[str, Any]:
'''
Custom error handler that formats validation errors
for better user experience.
Args:
e (ValidationException): ValidationException to handle
Returns:
dict: Formatted error response
'''
formatted_errors = []
for field, message in e.validations.items():
formatted_errors.append({
'field': field,
'message': message,
'code': f'INVALID_{field.upper()}'
})
return {
'error': 'Validation failed',
'status_code': e.status_code,
'details': formatted_errors
}
# Usage
try:
user = User(name='', email='invalid')
except ValidationException as e:
error_response = handle_validation_error(e)
print(error_response)
Logging Validation Errors
import logging
logger = logging.getLogger(__name__)
def create_user_with_logging(user_data: dict[str, Any]) -> User:
'''
Creates a new user with logging.
Args:
user_data (dict[str, Any]): User data to create
Returns:
User: Created user
'''
try:
user = User(**user_data)
logger.info(f'User created successfully: {user.email}')
return user
except ValidationException as e:
logger.warning(
f'User creation failed: {e.validations}',
extra={'validation_errors': e.validations}
)
raise
Multiple Model Validation
def validate_multiple_models(data_list: list[dict[str, Any]]) -> dict[str, Any]:
'''
Validates multiple model instances and collects all errors.
Args:
data_list (list[dict[str, Any]]): List of user data to validate
Returns:
dict: Validation results
'''
results = {
'successful': [],
'failed': [],
'total_errors': 0
}
for i, data in enumerate(data_list):
try:
user = User(**data)
results['successful'].append({
'index': i,
'user': user.dict()
})
except ValidationException as e:
results['failed'].append({
'index': i,
'errors': e.validations
})
results['total_errors'] += len(e.validations)
return results
Testing with ValidationException
import pytest
def test_user_validation_errors() -> None:
'''
Test that proper validation errors are raised.
'''
with pytest.raises(ValidationException) as exc_info:
User(name='', email='invalid-email')
exception = exc_info.value
# Test status code
assert exception.status_code == 400
# Test specific validation errors
assert 'name' in exception.validations
assert 'email' in exception.validations
assert exception.validations['name'] == 'This field is required'
assert 'Invalid email format' in exception.validations['email']
def test_exception_serialization() -> None:
'''
Test exception serialization methods.
'''
try:
User(name='', email='invalid')
except ValidationException as e:
# Test to_dict method
error_dict = e.to_dict()
assert 'status_code' in error_dict
assert 'validations' in error_dict
# Test to_json method
json_str = e.to_json()
assert isinstance(json_str, str)
assert 'status_code' in json_str
assert 'validations' in json_str
Integration Examples
FastAPI Integration
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(ValidationException)
async def validation_exception_handler(request, exc: ValidationException) -> JSONResponse:
'''
Global handler for ValidationException in FastAPI
Args:
request (Request): FastAPI request object
exc (ValidationException): ValidationException to handle
Returns:
JSONResponse: JSON response with error details
'''
return JSONResponse(
status_code=exc.status_code,
content=exc.to_dict()
)
@app.post('/users')
async def create_user(user_data: dict[str, Any]) -> dict[str, Any]:
'''
Create a new user.
Args:
user_data (dict[str, Any]): User data to create
Returns:
dict[str, Any]: Created user
'''
user = User(**user_data) # ValidationException handled automatically
return {'user': user.dict()}
Django Integration
from django.http import JsonResponse
from django.views import View
import json
class UserCreateView(View):
def post(self, request) -> JsonResponse:
'''
Create a new user.
Args:
request (HttpRequest): Django request object
Returns:
JsonResponse: JSON response with user data or error details
'''
try:
user_data = json.loads(request.body)
user = User(**user_data)
return JsonResponse({'success': True, 'user': user.dict()})
except ValidationException as e:
return JsonResponse(e.to_dict(), status=e.status_code)
Best Practices
- Always catch ValidationException: Handle validation errors gracefully in your application
- Use appropriate HTTP status codes: The default 400 is usually correct for validation errors
- Log validation errors: Keep track of common validation failures for improvement
- Provide user-friendly messages: Use custom error messages that help users fix their input
- Test error scenarios: Include tests for validation failures in your test suite
- Don't expose internal details: Sanitize error messages before showing them to end users