Free tools Windows power users keep installed
One-click scans. No signup required.
Puedes dejar de escribir a mano la lista de columnas de ClickHouse y derivarla de un modelo Pydantic v2, pero no con una sola llamada. model_json_schema() devuelve JSON Schema, no SQL, y un CREATE TABLE de ClickHouse exige además decisiones de almacenamiento (motor, claves) que ningún modelo de validación contiene. Lo que sí funciona es un generador pequeño que recorra los campos del modelo, traduzca tipos con una tabla explícita y reciba el resto de cláusulas como configuración.
Por qué «un modelo es suficiente» no es del todo cierto
La documentación de Pydantic indica que BaseModel.model_json_schema() (y TypeAdapter.json_schema()) devuelve un diccionario serializable a JSON, conforme a JSON Schema Draft 2020-12 y OpenAPI 3.1.0. Es una descripción interoperable de la forma de los datos. Personalizarla sigue siendo personalizar JSON Schema; no define semántica de ClickHouse.
As an Amazon Associate I earn from qualifying purchases.
Por su parte, la referencia de CREATE TABLE describe una lista de columnas más cláusulas: motor de tabla, expresiones de clave y, según el caso, valores predeterminados, comentarios, codecs, TTL, índices secundarios, proyecciones y restricciones. Nada de eso se deduce de anotaciones como int o str.
Conclusión práctica: el modelo puede ser la fuente de verdad de nombres, tipos y nulabilidad; el motor, el ORDER BY y la partición son política de almacenamiento y deben declararse aparte.
#1 Best Overall
Opciones para conectar Pydantic con ClickHouse
| Enfoque | Ventaja | Límite |
|---|---|---|
| Generador propio que lee los campos del modelo | La definición de campos queda junto al modelo de aplicación. | Debes definir y mantener el mapeo de tipos y cláusulas. |
model_json_schema() y luego conversión |
Usa la salida estándar de Pydantic. | JSON Schema no incluye la semántica de tabla de ClickHouse; añade una capa intermedia. |
| Generador de ClickHouse Connect desde esquemas PyArrow | Función oficial documentada que construye CREATE TABLE para tipos escalares comunes. |
No es un adaptador Pydantic; crea columnas no anulables, lanza TypeError con tipos no admitidos y su documentación pide revisar el SQL. |
| DDL escrito y mantenido a mano | Acceso a todas las cláusulas y cada decisión es visible. | Duplica información si el modelo cambia por separado. |
El generador de PyArrow está descrito en Advanced inserting. Si ya usas Arrow, puedes construir el esquema Arrow a partir del modelo y reutilizarlo; si no, añadir esa dependencia solo por el DDL probablemente no compense frente a un mapeo propio.
Decisiones que debes fijar antes de escribir código
Mapeo de tipos
Python int no dice si necesitas Int32, Int64 o un tipo sin signo. Elige una anchura por defecto y, para casos distintos, anota el campo con metadatos propios. Un punto de partida razonable, que es una propuesta de diseño y no un comportamiento de Pydantic:
Rank #2
| Tipo Python | ClickHouse propuesto | Decisión pendiente |
|---|---|---|
str |
String |
¿LowCardinality(String) en campos categóricos? |
int |
Int64 |
Anchura y signo según el dominio. |
float |
Float64 |
— |
bool |
Bool |
— |
date |
Date |
— |
datetime |
DateTime64(3) |
Precisión y zona horaria. |
X | None |
Nullable(X) |
Si prefieres valores por defecto en lugar de nulos. |
Documenta aparte las reglas para Decimal, enums, listas, modelos anidados, alias y campos excluidos. Mientras no estén definidas, lo más seguro es que el generador falle explícitamente.
Cláusulas de almacenamiento
Motor, base de datos, tabla, ORDER BY y PARTITION BY entran como parámetros. Así el generador no inventa una clave de ordenación que afecta al diseño físico de la tabla.
Rank #3
Un generador mínimo (boceto ilustrativo)
El siguiente código es un boceto de diseño. No se ha ejecutado ni validado contra un servidor ClickHouse; pruébalo con los modelos que realmente admitas.
import types
from datetime import date, datetime
from typing import Union, get_args, get_origin
from pydantic import BaseModel
TYPE_MAP = {
str: "String",
int: "Int64",
float: "Float64",
bool: "Bool",
date: "Date",
datetime: "DateTime64(3)",
}
def _ch_type(name, annotation):
origin = get_origin(annotation)
if origin in (Union, types.UnionType):
args = [a for a in get_args(annotation) if a is not type(None)]
if len(args) == 1 and len(args) != len(get_args(annotation)):
return f"Nullable({_ch_type(name, args[0])})"
if annotation in TYPE_MAP:
return TYPE_MAP[annotation]
raise TypeError(f"Campo {name!r}: tipo no soportado {annotation!r}")
def create_table_sql(model, table, engine, order_by):
cols = [
f" `{name}` {_ch_type(name, f.annotation)}"
for name, f in model.model_fields.items()
]
return (
f"CREATE TABLE IF NOT EXISTS {table}n(n"
+ ",n".join(cols)
+ f"n)nENGINE = {engine}nORDER BY {order_by}"
)
class Event(BaseModel):
id: int
user: str
ts: datetime
score: float | None = None
print(create_table_sql(Event, "events", "MergeTree", "(ts, id)"))
La salida es SQL determinista con cuatro columnas, y score como Nullable(Float64). Un tipo no contemplado (por ejemplo dict) provoca TypeError en lugar de adivinar.
Aplicarlo con seguridad
- Imprime o guarda el SQL generado y revísalo antes de ejecutarlo; es la misma recomendación que hace la documentación del generador de ClickHouse Connect.
- Ejecútalo con el cliente Python, por ejemplo con
client.command(sql), como muestra la página de integración de Python. - Añade pruebas por cada tipo que el generador admite, incluido el caso en que debe fallar.
- Trata los cambios de modelo posteriores como migraciones:
CREATE TABLE IF NOT EXISTSno altera una tabla existente, así que un campo nuevo requiere unALTER TABLEdeliberado.
Cuándo no compensa generar
Si la tabla usa TTL, codecs, proyecciones, índices secundarios o un motor distinto de MergeTree, probablemente es más claro mantener ese DDL explícito, o ampliar la configuración del generador solo con lo que necesites. Un generador que pretende cubrir cualquier modelo acaba siendo una segunda implementación de CREATE TABLE.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallQuick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

