Skip to content

BaseDBModel

The base class for all SQLiter database models. Extends Pydantic's BaseModel with database-specific functionality including automatic primary keys, timestamps, table name inference, and field serialization.

from sqliter.model import BaseDBModel

Source: sqliter/model/model.py, sqliter/model/unique.py

See also: Guide -- Models, Guide -- Fields

Note

This page documents the legacy mode BaseDBModel from sqliter.model. For the ORM-mode version with lazy loading and reverse relationships, see ORM Mode.


Built-in Fields

Every model automatically includes these fields:

FieldTypeDefaultDescription
pkint0Auto-incrementing primary key (set on insert)
created_atint0Unix timestamp when the record was created
updated_atint0Unix timestamp when the record was last updated

pk is managed by SQLite's AUTOINCREMENT. The created_at and updated_at timestamps are set automatically by SqliterDB.insert() and SqliterDB.update().


Model Configuration

BaseDBModel uses the following Pydantic ConfigDict:

model_config = ConfigDict(
    extra="ignore",
    populate_by_name=True,
    validate_assignment=True,
    from_attributes=True,
)
OptionValueEffect
extra"ignore"Extra fields in input data are silently ignored
populate_by_nameTrueFields can be populated by name or alias
validate_assignmentTrueField values are validated on assignment
from_attributesTrueModels can be created from objects with attributes

Inner Class Meta

Configure database-specific attributes via the Meta inner class.

class MyModel(BaseDBModel):
    name: str

    class Meta:
        table_name = "custom_table"
        indexes = ["name"]
        unique_indexes = [("name", "email")]

Attributes:

AttributeTypeDefaultDescription
table_namestr | NoneNoneCustom table name; auto-generated from class name if not set
indexeslist[str] | list[tuple[str, ...]][]Fields for regular indexes; use tuples for composite indexes
unique_indexeslist[str] | list[tuple[str, ...]][]Fields for unique indexes; use tuples for composite indexes

Class Methods

get_table_name()

Get the database table name for the model.

@classmethod
def get_table_name(cls) -> str:

Returns:

str -- The table name. If Meta.table_name is set, returns that value. Otherwise, the class name is converted to snake_case, the suffix Model is removed (if present), and the result is pluralized.

If the inflect library is installed, grammatically correct pluralization is used (e.g., "person" becomes "people"). Otherwise, a simple "s" suffix is added.

Raises:

  • ValueError -- If the table name contains invalid characters.

Example:

class UserProfile(BaseDBModel):
    name: str

UserProfile.get_table_name()  # "user_profiles"

get_primary_key()

Returns the name of the primary key field (always "pk").

@classmethod
def get_primary_key(cls) -> str:

Returns:

str -- Always "pk".


should_create_pk()

Returns whether the primary key should be created (always True).

@classmethod
def should_create_pk(cls) -> bool:

Returns:

bool -- Always True.


serialize_field()

Serialize a field value for SQLite storage.

@classmethod
def serialize_field(
    cls,
    value: SerializableField,
) -> SerializableField:

Parameters:

ParameterTypeDefaultDescription
valueSerializableFieldrequiredThe field value to serialize

Returns:

SerializableField -- The serialized value:

  • datetime / date objects are converted to Unix timestamps (via to_unix_timestamp()).
  • list, dict, set, tuple values are serialized with pickle.
  • All other values are returned as-is.

deserialize_field()

Deserialize a field value from SQLite storage back to a Python object.

@classmethod
def deserialize_field(
    cls,
    field_name: str,
    value: SerializableField,
    *,
    return_local_time: bool,
) -> object:

Parameters:

ParameterTypeDefaultDescription
field_namestrrequiredName of the field being deserialized
valueSerializableFieldrequiredThe value from the database
return_local_timeboolrequiredWhether to localize datetime values

Returns:

object -- The deserialized value:

  • Integer values in datetime/date fields are converted back using from_unix_timestamp().
  • bytes values in list/dict/set/tuple fields are deserialized with pickle.
  • None values return None.
  • All other values are returned as-is.

model_validate_partial()

Create a model instance from partial data (not all fields required). Used internally when fetching partial field selections.

@classmethod
def model_validate_partial(
    cls,
    obj: dict[str, Any],
) -> Self:

Parameters:

ParameterTypeDefaultDescription
objdict[str, Any]requiredDictionary of field names and values

Returns:

Self -- A model instance constructed with the provided data.


Protocol

SerializableField

Protocol for fields that can be serialized or deserialized. Used as a type hint for serialize_field() and deserialize_field().

class SerializableField(Protocol):
    """Protocol for fields that can be serialized or deserialized."""

unique()

Create a Pydantic Field with a unique constraint marker in json_schema_extra.

from sqliter.model import unique
def unique(
    default: Any = ...,
    **kwargs: Any,
) -> Any:

Parameters:

ParameterTypeDefaultDescription
defaultAny...Default value for the field
**kwargsAnyAdditional arguments passed to Pydantic Field

Returns:

A Pydantic Field with json_schema_extra={"unique": True}.

Example:

from typing import Annotated

from sqliter.model import BaseDBModel, unique


class User(BaseDBModel):
    email: Annotated[str, unique()]
    username: Annotated[str, unique(default="anonymous")]

Tip

Using Annotated is optional but recommended. Without it, type checkers like MyPy will report an incompatible assignment because unique() returns a Pydantic Field, not a str. The plain syntax email: str = unique() still works at runtime.


Unique() (Deprecated)

Caution

Unique() is deprecated and will be removed in a future version. Use unique() instead.

from sqliter.model import Unique  # Deprecated

Wrapper around unique() that emits a DeprecationWarning.