Pydantic Data Validation for User Profiles
This challenge focuses on implementing robust data validation for user profile information using the Pydantic library in Python. In real-world applications, ensuring data integrity and adherence to expected formats is crucial, especially when dealing with external data sources or user input. Pydantic provides a powerful and declarative way to achieve this.
Problem Description
Your task is to create a Pydantic model that represents a user profile. This model should enforce specific data types, formats, and value constraints for various user attributes.
Key Requirements:
-
User Model: Define a Pydantic
BaseModelnamedUserProfile. -
Attributes: The
UserProfilemodel must include the following attributes with their respective validation rules:user_id: A unique integer identifier. It must be a positive integer.username: A string representing the user's chosen username. It must be at least 3 characters long and can only contain alphanumeric characters and underscores (_).email: A string representing the user's email address. It must be a valid email format.age: An integer representing the user's age. It must be between 18 and 120 (inclusive).is_active: A boolean indicating whether the user account is active. Defaults toTrue.registration_date: A date object representing when the user registered. This field is optional and should default to the current date if not provided.
-
Validation: Pydantic's built-in validators and potentially custom validators should be used to enforce these rules.
-
Error Handling: When invalid data is provided, Pydantic should raise a
ValidationError. Your solution should demonstrate how this error occurs.
Expected Behavior:
- Valid user profile data should be successfully parsed into a
UserProfileobject. - Invalid user profile data should raise a
pydantic.ValidationErrorwith informative error messages.
Edge Cases to Consider:
- Missing optional fields.
- Data that is the correct type but does not meet value constraints (e.g., age too low, username too short).
- Data that is of the wrong type (e.g., string for
user_id). - Empty strings where they are not permitted.
Examples
Example 1: Valid User Profile
from datetime import date
input_data = {
"user_id": 12345,
"username": "john_doe_123",
"email": "john.doe@example.com",
"age": 30,
"registration_date": date(2023, 10, 27)
}
# Expected Output (a UserProfile object):
# UserProfile(user_id=12345, username='john_doe_123', email='john.doe@example.com', age=30, is_active=True, registration_date=datetime.date(2023, 10, 27))
Explanation: All fields conform to the defined Pydantic model requirements.
Example 2: Invalid Age and Username
from datetime import date
input_data = {
"user_id": 67890,
"username": "jd", # Too short
"email": "jane.doe@example.com",
"age": 15, # Too young
"registration_date": date(2024, 1, 15)
}
# Expected Output (a ValidationError):
# ValidationError: 2 validation errors for UserProfile
# username
# ensure this value has at least 3 characters (type=value_error.any_str.min_length, error_at=value, error_message='ensure this value has at least 3 characters')
# age
# ensure this value is between 18 and 120 (type=value_error.number.interval, error_at=value, error_message='ensure this value is between 18 and 120')
Explanation: The username is too short, and the age is below the minimum allowed value, triggering validation errors.
Example 3: Invalid Email Format and Incorrect Data Type
from datetime import date
input_data = {
"user_id": "abcde", # Incorrect type
"username": "valid_user",
"email": "invalid-email", # Invalid format
"age": 45
}
# Expected Output (a ValidationError):
# ValidationError: 2 validation errors for UserProfile
# user_id
# value is not a valid integer (type=type_error.integer, error_at=value, error_message='value is not a valid integer')
# email
# value is not a valid email address (type=value_error.email, error_at=value, error_message='value is not a valid email address')
Explanation: The user_id is provided as a string instead of an integer, and the email does not conform to a valid email format.
Example 4: Missing Optional Fields and Default Values
input_data = {
"user_id": 54321,
"username": "optional_user",
"email": "optional@example.com",
"age": 25
}
# Expected Output (a UserProfile object with defaults):
# UserProfile(user_id=54321, username='optional_user', email='optional@example.com', age=25, is_active=True, registration_date=datetime.date(2024, 2, 20)) # Assuming today's date is 2024-02-20
Explanation: is_active defaults to True, and registration_date defaults to the current date, as they were not provided in the input.
Constraints
- The
user_idmust be a positive integer (greater than 0). - The
usernamemust be between 3 and 50 characters long (inclusive) and contain only alphanumeric characters and underscores. - The
emailmust adhere to a standard email format. - The
agemust be an integer between 18 and 120 (inclusive). - The
registration_date(if provided) must be a validdatetime.dateobject. - You must use Pydantic v2.x.
Notes
- Pydantic offers powerful built-in types and validators. Explore the Pydantic documentation for
strvalidation (e.g.,min_length,max_length,pattern) andintvalidation (e.g.,gt,lt,ge,le). - For email validation, Pydantic has a dedicated
EmailStrtype. - For date validation, Pydantic can directly handle
datetime.dateobjects. - Consider how you would handle a scenario where the
registration_dateis in the future. Pydantic's default validators might not catch this; you might need a custom validator if this is a requirement beyond the scope of basic validation. For this challenge, focus on the provided constraints. - The goal is to demonstrate how Pydantic automatically handles validation and error reporting.