compub/src/compub/models/geography.py

95 lines
2.7 KiB
Python

from typing import Any, Optional
from pydantic import validator
from sqlalchemy.sql.schema import Column
from sqlalchemy.sql.sqltypes import Unicode
from sqlalchemy_utils.primitives.country import Country
from sqlalchemy_utils.types import CountryType
from sqlmodel.main import Field, Relationship
from .base import AbstractBase
__all__ = [
'StateProvince',
'City',
'Street',
'Address',
]
class StateProvince(AbstractBase, table=True):
__tablename__ = 'state_province'
# Fields
country: str = Field(sa_column=Column(CountryType, nullable=False, index=True))
name: str = Field(max_length=255, sa_column=Column(Unicode(255), nullable=False, index=True))
# Relationships
cities: list['City'] = Relationship(
back_populates='state_province', sa_relationship_kwargs={'lazy': 'selectin'}
)
@validator('country', pre=True)
def country_as_uppercase_string(cls, v: Any) -> str:
if isinstance(v, Country):
return v.code
if isinstance(v, str):
return v.upper()
raise TypeError
class City(AbstractBase, table=True):
__tablename__ = 'city'
# Fields
zip_code: str = Field(max_length=5, nullable=False, index=True)
name: str = Field(max_length=255, sa_column=Column(Unicode(255), nullable=False, index=True))
# Relationships
state_province_id: Optional[int] = Field(
foreign_key='state_province.id', default=None, nullable=False, index=True
)
state_province: Optional[StateProvince] = Relationship(
back_populates='cities', sa_relationship_kwargs={'lazy': 'selectin'}
)
streets: list['Street'] = Relationship(
back_populates='city', sa_relationship_kwargs={'lazy': 'selectin'}
)
class Street(AbstractBase, table=True):
__tablename__ = 'street'
# Fields
name: str = Field(max_length=255, sa_column=Column(Unicode(255), nullable=False, index=True))
# Relationships
city_id: Optional[int] = Field(
foreign_key='city.id', default=None, nullable=False, index=True
)
city: Optional[City] = Relationship(
back_populates='streets', sa_relationship_kwargs={'lazy': 'selectin'}
)
addresses: list['Address'] = Relationship(
back_populates='street', sa_relationship_kwargs={'lazy': 'selectin'}
)
class Address(AbstractBase, table=True):
__tablename__ = 'address'
# Fields
house_number: str = Field(max_length=8, nullable=False)
supplement: str = Field(max_length=255)
# Relationships
street_id: Optional[int] = Field(
foreign_key='street.id', default=None, nullable=False, index=True
)
street: Optional[Street] = Relationship(
back_populates='addresses', sa_relationship_kwargs={'lazy': 'selectin'}
)