[{"data":1,"prerenderedAt":1126},["ShallowReactive",2],{"navigation_docs":3,"-essentials-schema-evolution":106,"-essentials-schema-evolution-surround":1121},[4,26,57,83],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","/getting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","/getting-started/introduction","1.getting-started/1.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","/getting-started/installation","1.getting-started/2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","/getting-started/quick-start","1.getting-started/3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core Concepts","i-lucide-book-open","/essentials","2.essentials",[32,37,42,47,52],{"title":33,"path":34,"stem":35,"icon":36},"Models","/essentials/models","2.essentials/1.models","i-lucide-box",{"title":38,"path":39,"stem":40,"icon":41},"Collections","/essentials/collections","2.essentials/2.collections","i-lucide-folder",{"title":43,"path":44,"stem":45,"icon":46},"Views","/essentials/views","2.essentials/3.views","i-lucide-table",{"title":48,"path":49,"stem":50,"icon":51},"Schema Evolution","/essentials/schema-evolution","2.essentials/4.schema-evolution","i-lucide-git-branch",{"title":53,"path":54,"stem":55,"icon":56},"Relations","/essentials/relations","2.essentials/5.relations","i-lucide-link",{"title":58,"icon":59,"path":60,"stem":61,"children":62,"page":25},"Advanced","i-lucide-settings","/advanced","3.advanced",[63,68,73,78],{"title":64,"path":65,"stem":66,"icon":67},"Time-Series","/advanced/time-series","3.advanced/1.time-series","i-lucide-chart-line",{"title":69,"path":70,"stem":71,"icon":72},"Async Support","/advanced/async","3.advanced/2.async","i-lucide-zap",{"title":74,"path":75,"stem":76,"icon":77},"PostgreSQL","/advanced/postgresql","3.advanced/3.postgresql","i-lucide-database",{"title":79,"path":80,"stem":81,"icon":82},"Performance Guide","/advanced/performance","3.advanced/4.performance","i-lucide-gauge",{"title":84,"icon":85,"path":86,"stem":87,"children":88,"page":25},"API Reference","i-lucide-file-code","/api","4.api",[89,94,98,101],{"title":90,"path":91,"stem":92,"icon":93},"Engine","/api/engine","4.api/1.engine","i-lucide-cog",{"title":95,"path":96,"stem":97,"icon":41},"Collection","/api/collection","4.api/2.collection",{"title":33,"path":99,"stem":100,"icon":36},"/api/models","4.api/3.models",{"title":102,"path":103,"stem":104,"icon":105},"Exceptions","/api/exceptions","4.api/4.exceptions","i-lucide-alert-triangle",{"id":107,"title":48,"body":108,"description":1114,"extension":1115,"links":1116,"meta":1117,"navigation":1118,"path":49,"seo":1119,"stem":50,"__hash__":1120},"docs/2.essentials/4.schema-evolution.md",{"type":109,"value":110,"toc":1104},"minimark",[111,120,124,127,132,135,287,298,313,317,320,423,435,438,442,449,548,553,580,589,620,625,630,704,710,714,720,814,825,829,832,978,981,1007,1011,1085,1100],[112,113,114,115,119],"p",{},"Zero-migration schema evolution is CentauroDB's core design goal. You change your Python model, and old data keeps working. No migration files, no ",[116,117,118],"code",{},"ALTER TABLE",", no downtime. This guide shows you each operation step by step.",[121,122,123],"tip",{},"Unlike traditional ORMs, there are no migration files to create, review, or apply. Just update your Python class and re-run your application.",[112,125,126],{},"CentauroDB enforces guardrails at class-definition time that make this safe by default. Each of the operations below explains what happens under the hood and why it works.",[128,129,131],"h2",{"id":130},"adding-a-field","Adding a field",[112,133,134],{},"Just add the field with a default value. Old rows don't have the new key in their JSON — Pydantic fills in the default on read.",[136,137,142],"pre",{"className":138,"code":139,"language":140,"meta":141,"style":141},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# v1 — your model today\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n\n# v2 — one week later, you need a location\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n    location: str = \"unknown\"   # old rows get \"unknown\" on read\n","python","",[116,143,144,153,174,194,212,219,225,238,251,264],{"__ignoreMap":141},[145,146,149],"span",{"class":147,"line":148},"line",1,[145,150,152],{"class":151},"sHwdD","# v1 — your model today\n",[145,154,156,160,164,168,171],{"class":147,"line":155},2,[145,157,159],{"class":158},"spNyl","class",[145,161,163],{"class":162},"sBMFI"," Sensor",[145,165,167],{"class":166},"sMK4o","(",[145,169,170],{"class":162},"CentauroModel",[145,172,173],{"class":166},"):\n",[145,175,177,181,184,187,191],{"class":147,"line":176},3,[145,178,180],{"class":179},"sTEyZ","    __centauro_name__ ",[145,182,183],{"class":166},"=",[145,185,186],{"class":166}," \"",[145,188,190],{"class":189},"sfazB","Sensor",[145,192,193],{"class":166},"\"\n",[145,195,197,200,203,206,209],{"class":147,"line":196},4,[145,198,199],{"class":179},"    unit",[145,201,202],{"class":166},":",[145,204,205],{"class":162}," str",[145,207,208],{"class":166}," =",[145,210,211],{"class":166}," \"\"\n",[145,213,215],{"class":147,"line":214},5,[145,216,218],{"emptyLinePlaceholder":217},true,"\n",[145,220,222],{"class":147,"line":221},6,[145,223,224],{"class":151},"# v2 — one week later, you need a location\n",[145,226,228,230,232,234,236],{"class":147,"line":227},7,[145,229,159],{"class":158},[145,231,163],{"class":162},[145,233,167],{"class":166},[145,235,170],{"class":162},[145,237,173],{"class":166},[145,239,241,243,245,247,249],{"class":147,"line":240},8,[145,242,180],{"class":179},[145,244,183],{"class":166},[145,246,186],{"class":166},[145,248,190],{"class":189},[145,250,193],{"class":166},[145,252,254,256,258,260,262],{"class":147,"line":253},9,[145,255,199],{"class":179},[145,257,202],{"class":166},[145,259,205],{"class":162},[145,261,208],{"class":166},[145,263,211],{"class":166},[145,265,267,270,272,274,276,278,281,284],{"class":147,"line":266},10,[145,268,269],{"class":179},"    location",[145,271,202],{"class":166},[145,273,205],{"class":162},[145,275,208],{"class":166},[145,277,186],{"class":166},[145,279,280],{"class":189},"unknown",[145,282,283],{"class":166},"\"",[145,285,286],{"class":151},"   # old rows get \"unknown\" on read\n",[112,288,289,293,294,297],{},[290,291,292],"strong",{},"Why it works:"," CentauroDB requires every field to have a default. When Pydantic deserializes old JSON that lacks ",[116,295,296],{},"\"location\"",", it uses the default value. No database change needed.",[121,299,300,301,304,305,308,309,312],{},"Choose your defaults thoughtfully — they represent the value old data will appear to have. An empty string, ",[116,302,303],{},"0",", ",[116,306,307],{},"False",", or ",[116,310,311],{},"None"," are common choices depending on the field semantics.",[128,314,316],{"id":315},"removing-a-field","Removing a field",[112,318,319],{},"Delete the field from your class. Old rows still store the key in their JSON, but Pydantic silently ignores unknown keys.",[136,321,323],{"className":138,"code":322,"language":140,"meta":141,"style":141},"# v1\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n    location: str = \"\"\n\n# v2 — location is no longer needed\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n",[116,324,325,330,342,354,366,378,382,387,399,411],{"__ignoreMap":141},[145,326,327],{"class":147,"line":148},[145,328,329],{"class":151},"# v1\n",[145,331,332,334,336,338,340],{"class":147,"line":155},[145,333,159],{"class":158},[145,335,163],{"class":162},[145,337,167],{"class":166},[145,339,170],{"class":162},[145,341,173],{"class":166},[145,343,344,346,348,350,352],{"class":147,"line":176},[145,345,180],{"class":179},[145,347,183],{"class":166},[145,349,186],{"class":166},[145,351,190],{"class":189},[145,353,193],{"class":166},[145,355,356,358,360,362,364],{"class":147,"line":196},[145,357,199],{"class":179},[145,359,202],{"class":166},[145,361,205],{"class":162},[145,363,208],{"class":166},[145,365,211],{"class":166},[145,367,368,370,372,374,376],{"class":147,"line":214},[145,369,269],{"class":179},[145,371,202],{"class":166},[145,373,205],{"class":162},[145,375,208],{"class":166},[145,377,211],{"class":166},[145,379,380],{"class":147,"line":221},[145,381,218],{"emptyLinePlaceholder":217},[145,383,384],{"class":147,"line":227},[145,385,386],{"class":151},"# v2 — location is no longer needed\n",[145,388,389,391,393,395,397],{"class":147,"line":240},[145,390,159],{"class":158},[145,392,163],{"class":162},[145,394,167],{"class":166},[145,396,170],{"class":162},[145,398,173],{"class":166},[145,400,401,403,405,407,409],{"class":147,"line":253},[145,402,180],{"class":179},[145,404,183],{"class":166},[145,406,186],{"class":166},[145,408,190],{"class":189},[145,410,193],{"class":166},[145,412,413,415,417,419,421],{"class":147,"line":266},[145,414,199],{"class":179},[145,416,202],{"class":166},[145,418,205],{"class":162},[145,420,208],{"class":166},[145,422,211],{"class":166},[112,424,425,427,428,431,432,434],{},[290,426,292],{}," CentauroDB bans ",[116,429,430],{},"extra=\"forbid\""," on models. Pydantic's default behavior is to silently ignore extra keys in JSON, so old rows with ",[116,433,296],{}," load without error.",[112,436,437],{},"The old data remains in the JSON blob but is invisible to your Python code. If you later re-add a field with the same name, the old values reappear.",[128,439,441],{"id":440},"renaming-a-field","Renaming a field",[112,443,444,445,448],{},"Use ",[116,446,447],{},"renamed_from()"," to create an alias chain. Old JSON reads correctly under the new name, and new writes use the new name:",[136,450,452],{"className":138,"code":451,"language":140,"meta":141,"style":141},"from centaurodb import renamed_from\n\n# v1: field was called \"temp\"\n# v2: renamed to \"temperature\"\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    temperature: float = renamed_from(\"temp\", default=0.0)\n",[116,453,454,469,473,478,483,495,507],{"__ignoreMap":141},[145,455,456,460,463,466],{"class":147,"line":148},[145,457,459],{"class":458},"s7zQu","from",[145,461,462],{"class":179}," centaurodb ",[145,464,465],{"class":458},"import",[145,467,468],{"class":179}," renamed_from\n",[145,470,471],{"class":147,"line":155},[145,472,218],{"emptyLinePlaceholder":217},[145,474,475],{"class":147,"line":176},[145,476,477],{"class":151},"# v1: field was called \"temp\"\n",[145,479,480],{"class":147,"line":196},[145,481,482],{"class":151},"# v2: renamed to \"temperature\"\n",[145,484,485,487,489,491,493],{"class":147,"line":214},[145,486,159],{"class":158},[145,488,163],{"class":162},[145,490,167],{"class":166},[145,492,170],{"class":162},[145,494,173],{"class":166},[145,496,497,499,501,503,505],{"class":147,"line":221},[145,498,180],{"class":179},[145,500,183],{"class":166},[145,502,186],{"class":166},[145,504,190],{"class":189},[145,506,193],{"class":166},[145,508,509,512,514,517,519,523,525,527,530,532,535,539,541,545],{"class":147,"line":227},[145,510,511],{"class":179},"    temperature",[145,513,202],{"class":166},[145,515,516],{"class":162}," float",[145,518,208],{"class":166},[145,520,522],{"class":521},"s2Zo4"," renamed_from",[145,524,167],{"class":166},[145,526,283],{"class":166},[145,528,529],{"class":189},"temp",[145,531,283],{"class":166},[145,533,534],{"class":166},",",[145,536,538],{"class":537},"sHdIc"," default",[145,540,183],{"class":166},[145,542,544],{"class":543},"sbssI","0.0",[145,546,547],{"class":166},")\n",[112,549,550],{},[290,551,552],{},"What happens:",[554,555,556,567,573],"ul",{},[557,558,559,560,563,564],"li",{},"Old JSON ",[116,561,562],{},"{\"temp\": 42.0}"," → reads as ",[116,565,566],{},"temperature=42.0",[557,568,569,570],{},"New writes serialize as ",[116,571,572],{},"{\"temperature\": 42.0}",[557,574,575,576,579],{},"SQL views use ",[116,577,578],{},"COALESCE(json_extract(meta, '$.temperature'), json_extract(meta, '$.temp'))"," to read both",[112,581,582,583,588],{},"After renaming, ",[584,585,587],"a",{"href":586},"/essentials/views#refreshing-a-view","refresh the view"," to update the SQL column:",[136,590,592],{"className":138,"code":591,"language":140,"meta":141,"style":141},"coll.refresh_view(\"dashboard\", Sensor)\n",[116,593,594],{"__ignoreMap":141},[145,595,596,599,602,605,607,609,612,614,616,618],{"class":147,"line":148},[145,597,598],{"class":179},"coll",[145,600,601],{"class":166},".",[145,603,604],{"class":521},"refresh_view",[145,606,167],{"class":166},[145,608,283],{"class":166},[145,610,611],{"class":189},"dashboard",[145,613,283],{"class":166},[145,615,534],{"class":166},[145,617,163],{"class":521},[145,619,547],{"class":166},[621,622,624],"h3",{"id":623},"renaming-more-than-once","Renaming more than once",[112,626,627,629],{},[116,628,447],{}," accepts multiple old names for fields that have been renamed across several versions:",[136,631,633],{"className":138,"code":632,"language":140,"meta":141,"style":141},"# v1: \"temp\" → v2: \"temperature\" → v3: \"temp_celsius\"\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    temp_celsius: float = renamed_from(\"temp\", \"temperature\", default=0.0)\n",[116,634,635,640,652,664],{"__ignoreMap":141},[145,636,637],{"class":147,"line":148},[145,638,639],{"class":151},"# v1: \"temp\" → v2: \"temperature\" → v3: \"temp_celsius\"\n",[145,641,642,644,646,648,650],{"class":147,"line":155},[145,643,159],{"class":158},[145,645,163],{"class":162},[145,647,167],{"class":166},[145,649,170],{"class":162},[145,651,173],{"class":166},[145,653,654,656,658,660,662],{"class":147,"line":176},[145,655,180],{"class":179},[145,657,183],{"class":166},[145,659,186],{"class":166},[145,661,190],{"class":189},[145,663,193],{"class":166},[145,665,666,669,671,673,675,677,679,681,683,685,687,689,692,694,696,698,700,702],{"class":147,"line":196},[145,667,668],{"class":179},"    temp_celsius",[145,670,202],{"class":166},[145,672,516],{"class":162},[145,674,208],{"class":166},[145,676,522],{"class":521},[145,678,167],{"class":166},[145,680,283],{"class":166},[145,682,529],{"class":189},[145,684,283],{"class":166},[145,686,534],{"class":166},[145,688,186],{"class":166},[145,690,691],{"class":189},"temperature",[145,693,283],{"class":166},[145,695,534],{"class":166},[145,697,538],{"class":537},[145,699,183],{"class":166},[145,701,544],{"class":543},[145,703,547],{"class":166},[112,705,706,707,601],{},"CentauroDB and Pydantic try each name in order until one matches. The full alias chain is preserved in views via ",[116,708,709],{},"COALESCE",[128,711,713],{"id":712},"renaming-a-class","Renaming a class",[112,715,716,719],{},[116,717,718],{},"__centauro_name__"," decouples your Python class name from the database identity. Rename the class freely — the stored name stays the same:",[136,721,723],{"className":138,"code":722,"language":140,"meta":141,"style":141},"# v1\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n\n# v2 — class renamed, DB identity unchanged\nclass SensorReading(CentauroModel):\n    __centauro_name__ = \"Sensor\"   # old rows still match\n    unit: str = \"\"\n",[116,724,725,729,741,753,765,769,774,787,802],{"__ignoreMap":141},[145,726,727],{"class":147,"line":148},[145,728,329],{"class":151},[145,730,731,733,735,737,739],{"class":147,"line":155},[145,732,159],{"class":158},[145,734,163],{"class":162},[145,736,167],{"class":166},[145,738,170],{"class":162},[145,740,173],{"class":166},[145,742,743,745,747,749,751],{"class":147,"line":176},[145,744,180],{"class":179},[145,746,183],{"class":166},[145,748,186],{"class":166},[145,750,190],{"class":189},[145,752,193],{"class":166},[145,754,755,757,759,761,763],{"class":147,"line":196},[145,756,199],{"class":179},[145,758,202],{"class":166},[145,760,205],{"class":162},[145,762,208],{"class":166},[145,764,211],{"class":166},[145,766,767],{"class":147,"line":214},[145,768,218],{"emptyLinePlaceholder":217},[145,770,771],{"class":147,"line":221},[145,772,773],{"class":151},"# v2 — class renamed, DB identity unchanged\n",[145,775,776,778,781,783,785],{"class":147,"line":227},[145,777,159],{"class":158},[145,779,780],{"class":162}," SensorReading",[145,782,167],{"class":166},[145,784,170],{"class":162},[145,786,173],{"class":166},[145,788,789,791,793,795,797,799],{"class":147,"line":240},[145,790,180],{"class":179},[145,792,183],{"class":166},[145,794,186],{"class":166},[145,796,190],{"class":189},[145,798,283],{"class":166},[145,800,801],{"class":151},"   # old rows still match\n",[145,803,804,806,808,810,812],{"class":147,"line":253},[145,805,199],{"class":179},[145,807,202],{"class":166},[145,809,205],{"class":162},[145,811,208],{"class":166},[145,813,211],{"class":166},[112,815,816,818,819,821,822,824],{},[290,817,292],{}," CentauroDB filters rows by ",[116,820,718],{},", not the Python class name. As long as the ",[116,823,718],{}," value matches, old and new rows are read correctly.",[128,826,828],{"id":827},"combining-operations","Combining operations",[112,830,831],{},"You can apply multiple schema changes at once:",[136,833,835],{"className":138,"code":834,"language":140,"meta":141,"style":141},"# v1\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    temp: float = 0.0\n    old_field: str = \"\"\n\n# v2 — rename field, add new field, remove old_field\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    temperature: float = renamed_from(\"temp\", default=0.0)\n    location: str = \"unknown\"\n    # old_field removed — Pydantic ignores it in old rows\n",[116,836,837,841,853,865,879,892,896,901,913,925,955,972],{"__ignoreMap":141},[145,838,839],{"class":147,"line":148},[145,840,329],{"class":151},[145,842,843,845,847,849,851],{"class":147,"line":155},[145,844,159],{"class":158},[145,846,163],{"class":162},[145,848,167],{"class":166},[145,850,170],{"class":162},[145,852,173],{"class":166},[145,854,855,857,859,861,863],{"class":147,"line":176},[145,856,180],{"class":179},[145,858,183],{"class":166},[145,860,186],{"class":166},[145,862,190],{"class":189},[145,864,193],{"class":166},[145,866,867,870,872,874,876],{"class":147,"line":196},[145,868,869],{"class":179},"    temp",[145,871,202],{"class":166},[145,873,516],{"class":162},[145,875,208],{"class":166},[145,877,878],{"class":543}," 0.0\n",[145,880,881,884,886,888,890],{"class":147,"line":214},[145,882,883],{"class":179},"    old_field",[145,885,202],{"class":166},[145,887,205],{"class":162},[145,889,208],{"class":166},[145,891,211],{"class":166},[145,893,894],{"class":147,"line":221},[145,895,218],{"emptyLinePlaceholder":217},[145,897,898],{"class":147,"line":227},[145,899,900],{"class":151},"# v2 — rename field, add new field, remove old_field\n",[145,902,903,905,907,909,911],{"class":147,"line":240},[145,904,159],{"class":158},[145,906,163],{"class":162},[145,908,167],{"class":166},[145,910,170],{"class":162},[145,912,173],{"class":166},[145,914,915,917,919,921,923],{"class":147,"line":253},[145,916,180],{"class":179},[145,918,183],{"class":166},[145,920,186],{"class":166},[145,922,190],{"class":189},[145,924,193],{"class":166},[145,926,927,929,931,933,935,937,939,941,943,945,947,949,951,953],{"class":147,"line":266},[145,928,511],{"class":179},[145,930,202],{"class":166},[145,932,516],{"class":162},[145,934,208],{"class":166},[145,936,522],{"class":521},[145,938,167],{"class":166},[145,940,283],{"class":166},[145,942,529],{"class":189},[145,944,283],{"class":166},[145,946,534],{"class":166},[145,948,538],{"class":537},[145,950,183],{"class":166},[145,952,544],{"class":543},[145,954,547],{"class":166},[145,956,958,960,962,964,966,968,970],{"class":147,"line":957},11,[145,959,269],{"class":179},[145,961,202],{"class":166},[145,963,205],{"class":162},[145,965,208],{"class":166},[145,967,186],{"class":166},[145,969,280],{"class":189},[145,971,193],{"class":166},[145,973,975],{"class":147,"line":974},12,[145,976,977],{"class":151},"    # old_field removed — Pydantic ignores it in old rows\n",[112,979,980],{},"Then refresh your views:",[136,982,983],{"className":138,"code":591,"language":140,"meta":141,"style":141},[116,984,985],{"__ignoreMap":141},[145,986,987,989,991,993,995,997,999,1001,1003,1005],{"class":147,"line":148},[145,988,598],{"class":179},[145,990,601],{"class":166},[145,992,604],{"class":521},[145,994,167],{"class":166},[145,996,283],{"class":166},[145,998,611],{"class":189},[145,1000,283],{"class":166},[145,1002,534],{"class":166},[145,1004,163],{"class":521},[145,1006,547],{"class":166},[128,1008,1010],{"id":1009},"summary","Summary",[1012,1013,1014,1030],"table",{},[1015,1016,1017],"thead",{},[1018,1019,1020,1024,1027],"tr",{},[1021,1022,1023],"th",{},"Operation",[1021,1025,1026],{},"What you do",[1021,1028,1029],{},"Why it works",[1031,1032,1033,1045,1056,1072],"tbody",{},[1018,1034,1035,1039,1042],{},[1036,1037,1038],"td",{},"Add field",[1036,1040,1041],{},"Add field with default",[1036,1043,1044],{},"Pydantic fills the default on old rows",[1018,1046,1047,1050,1053],{},[1036,1048,1049],{},"Remove field",[1036,1051,1052],{},"Delete the field",[1036,1054,1055],{},"Pydantic ignores unknown JSON keys",[1018,1057,1058,1061,1065],{},[1036,1059,1060],{},"Rename field",[1036,1062,444,1063],{},[116,1064,447],{},[1036,1066,1067,1068,1071],{},"Pydantic ",[116,1069,1070],{},"AliasChoices"," reads old names",[1018,1073,1074,1077,1082],{},[1036,1075,1076],{},"Rename class",[1036,1078,1079,1080],{},"Keep same ",[116,1081,718],{},[1036,1083,1084],{},"DB identity is independent of class name",[1086,1087,1089,1090,1092,1093,1095,1096,601],"callout",{"icon":1088},"i-lucide-arrow-right","For the full ",[116,1091,447],{}," parameter reference and ",[116,1094,1070],{}," details, see the ",[584,1097,1099],{"href":1098},"/api/models#renamed_from","API reference",[1101,1102,1103],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":141,"searchDepth":155,"depth":155,"links":1105},[1106,1107,1108,1111,1112,1113],{"id":130,"depth":155,"text":131},{"id":315,"depth":155,"text":316},{"id":440,"depth":155,"text":441,"children":1109},[1110],{"id":623,"depth":176,"text":624},{"id":712,"depth":155,"text":713},{"id":827,"depth":155,"text":828},{"id":1009,"depth":155,"text":1010},"Add, remove, and rename fields without migrations — just update your Python class and redeploy.","md",null,{},{"icon":51},{"title":48,"description":1114},"RYlbEdZFxuWYLhbllHO6fw8StR0mAVl6PFM6cz0MOo8",[1122,1124],{"title":43,"path":44,"stem":45,"description":1123,"icon":46,"children":-1},"Turn JSON blobs into queryable SQL columns with auto-generated views and indexes.",{"title":53,"path":54,"stem":55,"description":1125,"icon":56,"children":-1},"Link parent and child objects with parent_ref — build one-to-many relationships without foreign key migrations.",1781105062208]