Models
Models in SheetAlchemy are Python classes that represent tabs in your Google Sheets. They define the structure, validation rules, and behavior of your data.
Defining Models
Basic Model
A basic model requires at minimum:
One or more field definitions
A
Metaclass with configuration
from sheetalchemy import Model, StringField, IntegerField
class Users(Model):
name = StringField(name="Name")
age = IntegerField(name="Age")
class Meta:
sheet_name = "My Google Sheet"
tab_name = "Users"
header_index = 1
Meta Configuration
The Meta class configures how the model connects to your Google Sheet.
Required Settings
Optional Settings
- load_policy: LoadPolicy = LoadPolicy.LAZY
Controls when data is loaded from Google Sheets.
LoadPolicy.LAZY: Load data when first accessed (default)LoadPolicy.INIT: Load data immediately when model is defined
Example with All Settings
from sheetalchemy import Model, LoadPolicy, StringField
class Products(Model):
name = StringField(name="Product Name")
sku = StringField(name="SKU")
class Meta:
sheet_name = "Inventory Management"
tab_name = "Products"
header_index = 1
load_policy = LoadPolicy.INIT
Load Policies
LAZY Loading (Default)
Data is loaded from Google Sheets only when you first query it:
class Users(Model):
name = StringField(name="Name")
class Meta:
sheet_name = "My Sheet"
tab_name = "Users"
header_index = 1
load_policy = LoadPolicy.LAZY # Default
# No data loaded yet
# Data is loaded here when first query executes
users = Users.manager.filter()
Advantages:
Faster application startup
Saves API calls if model is never queried
Good for models accessed conditionally
Use when:
You have many models
Not all models are always used
API quota is a concern
INIT Loading
Data is loaded immediately when the model class is defined:
class Users(Model):
name = StringField(name="Name")
class Meta:
sheet_name = "My Sheet"
tab_name = "Users"
header_index = 1
load_policy = LoadPolicy.INIT
# Data is already loaded by this point
Advantages:
Fail fast if sheet is unavailable
Consistent query performance
Better for frequently accessed data
Use when:
Model is always queried
You want to catch connection errors early
Query performance consistency is important
Model Manager
Every model automatically gets a manager attribute for querying data.
Manager Methods
- filter(**kwargs)
Filter records based on field values.
Users.manager.filter(age__gt=25, is_active=True)
- get(**kwargs)
Get a single record. Raises
ModelItemExceptionif not found or multiple found.user = Users.manager.get(name="John Doe")
- reload_model()
Reload data from Google Sheets.
Users.manager.reload_model()
- initialise_model()
Manually load data for lazy-loaded models.
Users.manager.initialise_model()
Working with Model Instances
Accessing Fields
user = Users.manager.get(name="John")
# Access field values
print(user.name)
print(user.age)
Model Methods
- to_json()
Convert model instance to JSON-serializable dictionary.
user = Users.manager.get(name="John") data = user.to_json() # {'name': 'John', 'age': 30}
- get_errors()
Get dictionary of field validation errors.
user = Users.manager.get(name="John") errors = user.get_errors() if errors: print(f"Validation errors: {errors}")
- get_raw_data()
Get the raw row data from Google Sheets.
user = Users.manager.get(name="John") raw = user.get_raw_data()
- get_raw_value(field_name)
Get the raw value for a specific field before transformation.
user = Users.manager.get(name="John") raw_age = user.get_raw_value("age")
Model Inheritance
You can create base models with common fields:
from sheetalchemy import Model, StringField, DateField
class BaseModel(Model):
created_at = DateField(name="Created", format=DateField.MM_DD_YYYY)
updated_at = DateField(name="Updated", format=DateField.MM_DD_YYYY)
class Meta:
abstract = True # Not supported yet, define in each model
class Users(Model):
name = StringField(name="Name")
created_at = DateField(name="Created", format=DateField.MM_DD_YYYY)
class Meta:
sheet_name = "My Sheet"
tab_name = "Users"
header_index = 1
Note: Abstract base models are not yet implemented. For now, define common fields in each model.
Multiple Models, Same Sheet
You can have multiple models pointing to different tabs in the same sheet:
class Users(Model):
name = StringField(name="Name")
class Meta:
sheet_name = "Company Data"
tab_name = "Users"
header_index = 1
class Products(Model):
name = StringField(name="Product")
class Meta:
sheet_name = "Company Data"
tab_name = "Products"
header_index = 1
Best Practices
Clear Model Names
Use descriptive names that match your domain:
class CustomerOrder(Model): # Good class CO(Model): # Bad - unclear
Consistent Field Naming
Match Python conventions for attributes:
first_name = StringField(name="First Name") # Good FirstName = StringField(name="First Name") # Bad
Document Your Models
Add docstrings:
class Users(Model): """ Represents user data from the Users tab. Fields: name: User's full name email: User's email address is_active: Whether user is currently active """ name = StringField(name="Name") email = StringField(name="Email") is_active = BooleanField(name="Active")
Choose Appropriate Load Policy
Use
LAZYfor models that may not be queriedUse
INITfor frequently accessed models
Handle Missing Data
Use field defaults for optional columns:
phone = StringField( name="Phone", allow_empty_or_null=True, default_val="" )
Common Patterns
Configuration Model
class Config(Model):
key = StringField(name="Key")
value = StringField(name="Value")
class Meta:
sheet_name = "App Configuration"
tab_name = "Config"
header_index = 1
load_policy = LoadPolicy.INIT # Load immediately
# Access configuration
config = {c.key: c.value for c in Config.manager.filter()}
Lookup Tables
class Countries(Model):
code = StringField(name="Code")
name = StringField(name="Country Name")
class Meta:
sheet_name = "Reference Data"
tab_name = "Countries"
header_index = 1
load_policy = LoadPolicy.INIT
# Create lookup dictionary
country_map = {c.code: c.name for c in Countries.manager.filter()}
Next Steps
Fields - Learn about field types
Querying - Master querying techniques
Advanced Usage - Explore advanced features