[{"data":1,"prerenderedAt":2268},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Frename-and-reorder-fields-pyqgis":3},{"id":4,"title":5,"body":6,"description":2257,"extension":2258,"meta":2259,"navigation":186,"path":2264,"seo":2265,"stem":2266,"__hash__":2267},"docs\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Frename-and-reorder-fields-pyqgis\u002Findex.md","Rename and Reorder Fields in PyQGIS",{"type":7,"value":8,"toc":2243},"minimark",[9,13,26,39,127,132,142,146,153,397,411,415,421,742,759,860,864,867,1073,1087,1091,1094,1451,1467,1471,1474,1598,1603,1607,1610,1702,2065,2074,2078,2122,2126,2154,2158,2170,2174,2180,2193,2199,2205,2209,2239],[10,11,5],"h1",{"id":12},"rename-and-reorder-fields-in-pyqgis",[14,15,16,17,21,22,25],"p",{},"Field names come from wherever the data was made: shapefile names truncated to ten characters (",[18,19,20],"code",{},"POPULATIO",", ",[18,23,24],{},"AREA_HA_CA","), exports with machine-generated prefixes, spreadsheets with spaces and capitals. Field order is whatever the last tool left. Before data is shared, joined or published, its schema usually needs tidying — clear names, a sensible order, no leftover columns — and when data must match a specification, the schema must be mapped exactly.",[14,27,28,29,34,35,38],{},"This recipe belongs to ",[30,31,33],"a",{"href":32},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002F","Attribute Tables & Field Management",". It renames fields in place, rebuilds a whole schema with ",[18,36,37],{},"native:refactorfields",", reorders and drops columns, sets aliases for display, and maps a supplier's schema onto a target specification.",[14,40,41],{},[42,43,48,52,56,63,72,82,88,94,98,103,107,112,116,118,121,124],"svg",{"viewBox":44,"role":45,"ariaLabel":46,"xmlns":47},"0 0 760 262","img","Renaming fields in place in the existing source compared with refactoring into a new layer from a complete field mapping","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[49,50,51],"title",{},"In place or a new schema",[53,54,55],"desc",{},"Two routes. Renaming in place changes a field's name in the existing data source through the provider, keeping everything else; it is quick but limited to renames and depends on the format's support. Refactor fields builds a new layer from a field mapping that lists each output field's name, type, length and the expression that fills it, allowing renames, reorders, drops, type changes and computed fields in one step.",[57,58],"rect",{"x":59,"y":59,"width":60,"height":61,"fill":62},"0","760","262","#f6f3ea",[64,65,71],"text",{"x":66,"y":67,"style":68,"fill":69,"textAnchor":70},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","Rename in place, or rebuild the schema",[57,73],{"x":74,"y":75,"width":76,"height":77,"rx":78,"fill":79,"stroke":80,"style":81},"24","56","340","190","8","#eef7f4","#0f766e","stroke-width:2",[64,83,87],{"x":84,"y":85,"style":86,"fill":80,"textAnchor":70},"194","94.78","text-anchor:middle;font-size:11.5px;font-family:sans-serif;font-weight:bold","rename in place",[64,89,93],{"x":84,"y":90,"style":91,"fill":92,"textAnchor":70},"124.78","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#2f3b35","renameAttribute()",[64,95,97],{"x":84,"y":96,"style":91,"fill":92,"textAnchor":70},"154.78","same data source",[64,99,102],{"x":84,"y":100,"style":91,"fill":101,"textAnchor":70},"184.78","#59645f","names only",[64,104,106],{"x":84,"y":105,"style":91,"fill":101,"textAnchor":70},"214.78","format must allow it",[57,108],{"x":109,"y":75,"width":76,"height":77,"rx":78,"fill":110,"stroke":111,"style":81},"396","#eff3ff","#2563eb",[64,113,115],{"x":114,"y":85,"style":86,"fill":111,"textAnchor":70},"566","refactor fields",[64,117,37],{"x":114,"y":90,"style":91,"fill":92,"textAnchor":70},[64,119,120],{"x":114,"y":96,"style":91,"fill":92,"textAnchor":70},"new layer",[64,122,123],{"x":114,"y":100,"style":91,"fill":101,"textAnchor":70},"rename · reorder · drop",[64,125,126],{"x":114,"y":105,"style":91,"fill":101,"textAnchor":70},"retype · compute",[128,129,131],"h2",{"id":130},"prerequisites","Prerequisites",[133,134,135,139],"ul",{},[136,137,138],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series.",[136,140,141],{},"A writable layer for in-place renames — GeoPackage, PostGIS or a memory layer. Shapefiles support renames, but names stay limited to ten characters.",[128,143,145],{"id":144},"rename-a-field-in-place","Rename a field in place",[14,147,148,149,152],{},"For a quick rename on an existing table, the layer's ",[18,150,151],{},"renameAttribute"," changes the name through the edit buffer, and the provider applies it on commit.",[154,155,160],"pre",{"className":156,"code":157,"language":158,"meta":159,"style":159},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject, edit\n\nparcels = QgsProject.instance().mapLayersByName(\"parcels\")[0]\nrenames = {\"AREA_HA_CA\": \"area_ha\", \"OWNR_NM\": \"owner_name\", \"LST_UPD\": \"last_updated\"}\n\nwith edit(parcels):\n    for old, new in renames.items():\n        idx = parcels.fields().indexOf(old)\n        if idx \u003C 0:\n            print(\"no field\", old)\n            continue\n        if not parcels.renameAttribute(idx, new):\n            raise RuntimeError(f\"could not rename {old} → {new}\")\nprint(parcels.fields().names())\n","python","",[18,161,162,181,188,213,256,261,270,285,296,314,329,335,346,388],{"__ignoreMap":159},[163,164,167,171,175,178],"span",{"class":165,"line":166},"line",1,[163,168,170],{"class":169},"snl16","from",[163,172,174],{"class":173},"s95oV"," qgis.core ",[163,176,177],{"class":169},"import",[163,179,180],{"class":173}," QgsProject, edit\n",[163,182,184],{"class":165,"line":183},2,[163,185,187],{"emptyLinePlaceholder":186},true,"\n",[163,189,191,194,197,200,204,207,210],{"class":165,"line":190},3,[163,192,193],{"class":173},"parcels ",[163,195,196],{"class":169},"=",[163,198,199],{"class":173}," QgsProject.instance().mapLayersByName(",[163,201,203],{"class":202},"sU2Wk","\"parcels\"",[163,205,206],{"class":173},")[",[163,208,59],{"class":209},"sDLfK",[163,211,212],{"class":173},"]\n",[163,214,216,219,221,224,227,230,233,235,238,240,243,245,248,250,253],{"class":165,"line":215},4,[163,217,218],{"class":173},"renames ",[163,220,196],{"class":169},[163,222,223],{"class":173}," {",[163,225,226],{"class":202},"\"AREA_HA_CA\"",[163,228,229],{"class":173},": ",[163,231,232],{"class":202},"\"area_ha\"",[163,234,21],{"class":173},[163,236,237],{"class":202},"\"OWNR_NM\"",[163,239,229],{"class":173},[163,241,242],{"class":202},"\"owner_name\"",[163,244,21],{"class":173},[163,246,247],{"class":202},"\"LST_UPD\"",[163,249,229],{"class":173},[163,251,252],{"class":202},"\"last_updated\"",[163,254,255],{"class":173},"}\n",[163,257,259],{"class":165,"line":258},5,[163,260,187],{"emptyLinePlaceholder":186},[163,262,264,267],{"class":165,"line":263},6,[163,265,266],{"class":169},"with",[163,268,269],{"class":173}," edit(parcels):\n",[163,271,273,276,279,282],{"class":165,"line":272},7,[163,274,275],{"class":169},"    for",[163,277,278],{"class":173}," old, new ",[163,280,281],{"class":169},"in",[163,283,284],{"class":173}," renames.items():\n",[163,286,288,291,293],{"class":165,"line":287},8,[163,289,290],{"class":173},"        idx ",[163,292,196],{"class":169},[163,294,295],{"class":173}," parcels.fields().indexOf(old)\n",[163,297,299,302,305,308,311],{"class":165,"line":298},9,[163,300,301],{"class":169},"        if",[163,303,304],{"class":173}," idx ",[163,306,307],{"class":169},"\u003C",[163,309,310],{"class":209}," 0",[163,312,313],{"class":173},":\n",[163,315,317,320,323,326],{"class":165,"line":316},10,[163,318,319],{"class":209},"            print",[163,321,322],{"class":173},"(",[163,324,325],{"class":202},"\"no field\"",[163,327,328],{"class":173},", old)\n",[163,330,332],{"class":165,"line":331},11,[163,333,334],{"class":169},"            continue\n",[163,336,338,340,343],{"class":165,"line":337},12,[163,339,301],{"class":169},[163,341,342],{"class":169}," not",[163,344,345],{"class":173}," parcels.renameAttribute(idx, new):\n",[163,347,349,352,355,357,360,363,366,369,372,375,377,380,382,385],{"class":165,"line":348},13,[163,350,351],{"class":169},"            raise",[163,353,354],{"class":209}," RuntimeError",[163,356,322],{"class":173},[163,358,359],{"class":169},"f",[163,361,362],{"class":202},"\"could not rename ",[163,364,365],{"class":209},"{",[163,367,368],{"class":173},"old",[163,370,371],{"class":209},"}",[163,373,374],{"class":202}," → ",[163,376,365],{"class":209},[163,378,379],{"class":173},"new",[163,381,371],{"class":209},[163,383,384],{"class":202},"\"",[163,386,387],{"class":173},")\n",[163,389,391,394],{"class":165,"line":390},14,[163,392,393],{"class":209},"print",[163,395,396],{"class":173},"(parcels.fields().names())\n",[14,398,399,403,404,406,407,410],{},[400,401,402],"strong",{},"Breakdown:"," Looking up each index by name, rather than assuming positions, keeps the script correct if fields have been added or reordered. ",[18,405,151],{}," returns False when the provider cannot rename — some formats and read-only sources — so check it. Inside ",[18,408,409],{},"edit()",", a failure rolls back every rename, leaving the table unchanged. Renaming breaks anything that refers to the old name: expressions in styles and labels, joins, forms and other scripts. Search the project for the old names before renaming a widely used layer.",[128,412,414],{"id":413},"rebuild-the-schema-with-refactor-fields","Rebuild the schema with refactor fields",[14,416,417,418,420],{},"For more than a few renames — or when order, types and dropped columns matter too — ",[18,419,37],{}," builds a new layer from a complete field mapping. Each output field is defined by name, type, length, precision and an expression that fills it.",[154,422,424],{"className":156,"code":423,"language":158,"meta":159,"style":159},"import processing\nfrom qgis.PyQt.QtCore import QVariant\n\nmapping = [\n    {\"name\": \"parcel_id\",    \"type\": QVariant.String, \"length\": 20, \"precision\": 0, \"expression\": '\"PRCL_ID\"'},\n    {\"name\": \"owner_name\",   \"type\": QVariant.String, \"length\": 120, \"precision\": 0, \"expression\": 'title(\"OWNR_NM\")'},\n    {\"name\": \"area_ha\",      \"type\": QVariant.Double, \"length\": 12, \"precision\": 4, \"expression\": \"$area \u002F 10000\"},\n    {\"name\": \"land_use\",     \"type\": QVariant.String, \"length\": 30, \"precision\": 0, \"expression\": 'lower(\"LU_CODE\")'},\n    {\"name\": \"last_updated\", \"type\": QVariant.Date,   \"length\": 0,  \"precision\": 0, \"expression\": 'to_date(\"LST_UPD\")'},\n]\nclean = processing.run(\"native:refactorfields\", {\n    \"INPUT\": parcels, \"FIELDS_MAPPING\": mapping, \"OUTPUT\": \"memory:parcels_clean\"})[\"OUTPUT\"]\nprint(clean.fields().names())\n",[18,425,426,433,445,449,459,511,554,599,643,686,690,706,735],{"__ignoreMap":159},[163,427,428,430],{"class":165,"line":166},[163,429,177],{"class":169},[163,431,432],{"class":173}," processing\n",[163,434,435,437,440,442],{"class":165,"line":183},[163,436,170],{"class":169},[163,438,439],{"class":173}," qgis.PyQt.QtCore ",[163,441,177],{"class":169},[163,443,444],{"class":173}," QVariant\n",[163,446,447],{"class":165,"line":190},[163,448,187],{"emptyLinePlaceholder":186},[163,450,451,454,456],{"class":165,"line":215},[163,452,453],{"class":173},"mapping ",[163,455,196],{"class":169},[163,457,458],{"class":173}," [\n",[163,460,461,464,467,469,472,475,478,481,484,486,489,491,494,496,498,500,503,505,508],{"class":165,"line":258},[163,462,463],{"class":173},"    {",[163,465,466],{"class":202},"\"name\"",[163,468,229],{"class":173},[163,470,471],{"class":202},"\"parcel_id\"",[163,473,474],{"class":173},",    ",[163,476,477],{"class":202},"\"type\"",[163,479,480],{"class":173},": QVariant.String, ",[163,482,483],{"class":202},"\"length\"",[163,485,229],{"class":173},[163,487,488],{"class":209},"20",[163,490,21],{"class":173},[163,492,493],{"class":202},"\"precision\"",[163,495,229],{"class":173},[163,497,59],{"class":209},[163,499,21],{"class":173},[163,501,502],{"class":202},"\"expression\"",[163,504,229],{"class":173},[163,506,507],{"class":202},"'\"PRCL_ID\"'",[163,509,510],{"class":173},"},\n",[163,512,513,515,517,519,521,524,526,528,530,532,535,537,539,541,543,545,547,549,552],{"class":165,"line":263},[163,514,463],{"class":173},[163,516,466],{"class":202},[163,518,229],{"class":173},[163,520,242],{"class":202},[163,522,523],{"class":173},",   ",[163,525,477],{"class":202},[163,527,480],{"class":173},[163,529,483],{"class":202},[163,531,229],{"class":173},[163,533,534],{"class":209},"120",[163,536,21],{"class":173},[163,538,493],{"class":202},[163,540,229],{"class":173},[163,542,59],{"class":209},[163,544,21],{"class":173},[163,546,502],{"class":202},[163,548,229],{"class":173},[163,550,551],{"class":202},"'title(\"OWNR_NM\")'",[163,553,510],{"class":173},[163,555,556,558,560,562,564,567,569,572,574,576,579,581,583,585,588,590,592,594,597],{"class":165,"line":272},[163,557,463],{"class":173},[163,559,466],{"class":202},[163,561,229],{"class":173},[163,563,232],{"class":202},[163,565,566],{"class":173},",      ",[163,568,477],{"class":202},[163,570,571],{"class":173},": QVariant.Double, ",[163,573,483],{"class":202},[163,575,229],{"class":173},[163,577,578],{"class":209},"12",[163,580,21],{"class":173},[163,582,493],{"class":202},[163,584,229],{"class":173},[163,586,587],{"class":209},"4",[163,589,21],{"class":173},[163,591,502],{"class":202},[163,593,229],{"class":173},[163,595,596],{"class":202},"\"$area \u002F 10000\"",[163,598,510],{"class":173},[163,600,601,603,605,607,610,613,615,617,619,621,624,626,628,630,632,634,636,638,641],{"class":165,"line":287},[163,602,463],{"class":173},[163,604,466],{"class":202},[163,606,229],{"class":173},[163,608,609],{"class":202},"\"land_use\"",[163,611,612],{"class":173},",     ",[163,614,477],{"class":202},[163,616,480],{"class":173},[163,618,483],{"class":202},[163,620,229],{"class":173},[163,622,623],{"class":209},"30",[163,625,21],{"class":173},[163,627,493],{"class":202},[163,629,229],{"class":173},[163,631,59],{"class":209},[163,633,21],{"class":173},[163,635,502],{"class":202},[163,637,229],{"class":173},[163,639,640],{"class":202},"'lower(\"LU_CODE\")'",[163,642,510],{"class":173},[163,644,645,647,649,651,653,655,657,660,662,664,666,669,671,673,675,677,679,681,684],{"class":165,"line":298},[163,646,463],{"class":173},[163,648,466],{"class":202},[163,650,229],{"class":173},[163,652,252],{"class":202},[163,654,21],{"class":173},[163,656,477],{"class":202},[163,658,659],{"class":173},": QVariant.Date,   ",[163,661,483],{"class":202},[163,663,229],{"class":173},[163,665,59],{"class":209},[163,667,668],{"class":173},",  ",[163,670,493],{"class":202},[163,672,229],{"class":173},[163,674,59],{"class":209},[163,676,21],{"class":173},[163,678,502],{"class":202},[163,680,229],{"class":173},[163,682,683],{"class":202},"'to_date(\"LST_UPD\")'",[163,685,510],{"class":173},[163,687,688],{"class":165,"line":316},[163,689,212],{"class":173},[163,691,692,695,697,700,703],{"class":165,"line":331},[163,693,694],{"class":173},"clean ",[163,696,196],{"class":169},[163,698,699],{"class":173}," processing.run(",[163,701,702],{"class":202},"\"native:refactorfields\"",[163,704,705],{"class":173},", {\n",[163,707,708,711,714,717,720,723,725,728,731,733],{"class":165,"line":337},[163,709,710],{"class":202},"    \"INPUT\"",[163,712,713],{"class":173},": parcels, ",[163,715,716],{"class":202},"\"FIELDS_MAPPING\"",[163,718,719],{"class":173},": mapping, ",[163,721,722],{"class":202},"\"OUTPUT\"",[163,724,229],{"class":173},[163,726,727],{"class":202},"\"memory:parcels_clean\"",[163,729,730],{"class":173},"})[",[163,732,722],{"class":202},[163,734,212],{"class":173},[163,736,737,739],{"class":165,"line":348},[163,738,393],{"class":209},[163,740,741],{"class":173},"(clean.fields().names())\n",[14,743,744,746,747,750,751,754,755,758],{},[400,745,402],{}," The output has exactly the fields in the mapping, in that order; anything not listed is dropped. Because each field is filled by an expression, renaming, recasing text, converting text dates to real dates and recomputing area all happen in the same step. The source layer is untouched, so the mapping can be refined and re-run. Field types are given as ",[18,748,749],{},"QVariant"," types on QGIS 3; on recent releases the mapping also accepts a ",[18,752,753],{},"sub_type"," key for list fields and QGIS 4 uses ",[18,756,757],{},"QMetaType"," values.",[14,760,761],{},[42,762,765,768,771,774,789,792,798,804,809,813,816,820,824,830,834,839,843,847,851,855],{"viewBox":763,"role":45,"ariaLabel":764,"xmlns":47},"0 0 760 250","A field mapping listing each output field with name, type and the expression that fills it from source fields",[49,766,767],{},"A field mapping",[53,769,770],{},"A field mapping is a list of output fields in order. Each entry names the output field, its type, length and precision, and the expression that computes it from the source, often just the old field name. Source fields not referenced by any expression are dropped. The same list can be saved and reused for every delivery in the same format.",[57,772],{"x":59,"y":59,"width":60,"height":773,"fill":62},"250",[775,776,777],"defs",{},[778,779,785],"marker",{"id":780,"viewBox":781,"refX":78,"refY":782,"markerWidth":783,"markerHeight":783,"orient":784},"rnMapArrow","0 0 10 10","5","7","auto-start-reverse",[786,787],"path",{"d":788,"fill":92},"M0 0 L10 5 L0 10 z",[64,790,791],{"x":66,"y":67,"style":68,"fill":69,"textAnchor":70},"Each output field: name, type, expression",[57,793],{"x":74,"y":794,"width":795,"height":796,"rx":78,"fill":797,"stroke":101,"style":81},"52","230","176","#fffdf7",[64,799,803],{"x":800,"y":801,"style":802,"fill":69,"textAnchor":70},"139","78.6","text-anchor:middle;font-size:11.0px;font-family:sans-serif;font-weight:bold","source fields",[64,805,808],{"x":800,"y":806,"style":807,"fill":92,"textAnchor":70},"104.6","text-anchor:middle;font-size:9.5px;font-family:monospace","PRCL_ID",[64,810,812],{"x":800,"y":811,"style":807,"fill":92,"textAnchor":70},"130.6","OWNR_NM",[64,814,24],{"x":800,"y":815,"style":807,"fill":92,"textAnchor":70},"156.6",[64,817,819],{"x":800,"y":818,"style":807,"fill":92,"textAnchor":70},"182.6","LU_CODE",[64,821,823],{"x":800,"y":822,"style":807,"fill":92,"textAnchor":70},"208.6","TMP_X",[165,825],{"x1":826,"y1":827,"x2":828,"y2":827,"stroke":92,"style":829},"254","140","296","stroke-width:1.8;marker-end:url(#rnMapArrow)",[57,831],{"x":832,"y":794,"width":833,"height":796,"rx":78,"fill":79,"stroke":80,"style":81},"300","436",[64,835,838],{"x":836,"y":837,"style":802,"fill":80,"textAnchor":70},"518","83.6","mapping (in order)",[64,840,842],{"x":836,"y":841,"style":807,"fill":92,"textAnchor":70},"107.6","parcel_id   ← \"PRCL_ID\"",[64,844,846],{"x":836,"y":845,"style":807,"fill":92,"textAnchor":70},"131.6","owner_name  ← title(\"OWNR_NM\")",[64,848,850],{"x":836,"y":849,"style":807,"fill":92,"textAnchor":70},"155.6","area_ha     ← $area \u002F 10000",[64,852,854],{"x":836,"y":853,"style":807,"fill":92,"textAnchor":70},"179.6","land_use    ← lower(\"LU_CODE\")",[64,856,859],{"x":836,"y":857,"style":858,"fill":101,"textAnchor":70},"203.6","text-anchor:middle;font-size:10.0px;font-family:sans-serif","TMP_X not mapped → dropped",[128,861,863],{"id":862},"reorder-and-drop-columns-quickly","Reorder and drop columns quickly",[14,865,866],{},"When only order and selection change, generating the mapping from the existing fields saves typing.",[154,868,870],{"className":156,"code":869,"language":158,"meta":159,"style":159},"def mapping_for(layer, order, rename=None):\n    rename = rename or {}\n    fields = layer.fields()\n    out = []\n    for name in order:\n        f = fields.field(name)\n        out.append({\"name\": rename.get(name, name), \"type\": f.type(), \"length\": f.length(),\n                    \"precision\": f.precision(), \"expression\": f'\"{name}\"'})\n    return out\n\nordered = processing.run(\"native:refactorfields\", {\n    \"INPUT\": clean,\n    \"FIELDS_MAPPING\": mapping_for(clean, [\"parcel_id\", \"land_use\", \"area_ha\", \"owner_name\"]),\n    \"OUTPUT\": \"memory:parcels_ordered\"})[\"OUTPUT\"]\n",[18,871,872,892,908,918,928,940,950,970,1000,1008,1012,1025,1032,1057],{"__ignoreMap":159},[163,873,874,877,881,884,886,889],{"class":165,"line":166},[163,875,876],{"class":169},"def",[163,878,880],{"class":879},"svObZ"," mapping_for",[163,882,883],{"class":173},"(layer, order, rename",[163,885,196],{"class":169},[163,887,888],{"class":209},"None",[163,890,891],{"class":173},"):\n",[163,893,894,897,899,902,905],{"class":165,"line":183},[163,895,896],{"class":173},"    rename ",[163,898,196],{"class":169},[163,900,901],{"class":173}," rename ",[163,903,904],{"class":169},"or",[163,906,907],{"class":173}," {}\n",[163,909,910,913,915],{"class":165,"line":190},[163,911,912],{"class":173},"    fields ",[163,914,196],{"class":169},[163,916,917],{"class":173}," layer.fields()\n",[163,919,920,923,925],{"class":165,"line":215},[163,921,922],{"class":173},"    out ",[163,924,196],{"class":169},[163,926,927],{"class":173}," []\n",[163,929,930,932,935,937],{"class":165,"line":258},[163,931,275],{"class":169},[163,933,934],{"class":173}," name ",[163,936,281],{"class":169},[163,938,939],{"class":173}," order:\n",[163,941,942,945,947],{"class":165,"line":263},[163,943,944],{"class":173},"        f ",[163,946,196],{"class":169},[163,948,949],{"class":173}," fields.field(name)\n",[163,951,952,955,957,960,962,965,967],{"class":165,"line":272},[163,953,954],{"class":173},"        out.append({",[163,956,466],{"class":202},[163,958,959],{"class":173},": rename.get(name, name), ",[163,961,477],{"class":202},[163,963,964],{"class":173},": f.type(), ",[163,966,483],{"class":202},[163,968,969],{"class":173},": f.length(),\n",[163,971,972,975,978,980,982,984,987,989,992,994,997],{"class":165,"line":287},[163,973,974],{"class":202},"                    \"precision\"",[163,976,977],{"class":173},": f.precision(), ",[163,979,502],{"class":202},[163,981,229],{"class":173},[163,983,359],{"class":169},[163,985,986],{"class":202},"'\"",[163,988,365],{"class":209},[163,990,991],{"class":173},"name",[163,993,371],{"class":209},[163,995,996],{"class":202},"\"'",[163,998,999],{"class":173},"})\n",[163,1001,1002,1005],{"class":165,"line":298},[163,1003,1004],{"class":169},"    return",[163,1006,1007],{"class":173}," out\n",[163,1009,1010],{"class":165,"line":316},[163,1011,187],{"emptyLinePlaceholder":186},[163,1013,1014,1017,1019,1021,1023],{"class":165,"line":331},[163,1015,1016],{"class":173},"ordered ",[163,1018,196],{"class":169},[163,1020,699],{"class":173},[163,1022,702],{"class":202},[163,1024,705],{"class":173},[163,1026,1027,1029],{"class":165,"line":337},[163,1028,710],{"class":202},[163,1030,1031],{"class":173},": clean,\n",[163,1033,1034,1037,1040,1042,1044,1046,1048,1050,1052,1054],{"class":165,"line":348},[163,1035,1036],{"class":202},"    \"FIELDS_MAPPING\"",[163,1038,1039],{"class":173},": mapping_for(clean, [",[163,1041,471],{"class":202},[163,1043,21],{"class":173},[163,1045,609],{"class":202},[163,1047,21],{"class":173},[163,1049,232],{"class":202},[163,1051,21],{"class":173},[163,1053,242],{"class":202},[163,1055,1056],{"class":173},"]),\n",[163,1058,1059,1062,1064,1067,1069,1071],{"class":165,"line":390},[163,1060,1061],{"class":202},"    \"OUTPUT\"",[163,1063,229],{"class":173},[163,1065,1066],{"class":202},"\"memory:parcels_ordered\"",[163,1068,730],{"class":173},[163,1070,722],{"class":202},[163,1072,212],{"class":173},[14,1074,1075,1077,1078,1081,1082,1086],{},[400,1076,402],{}," Reading type, length and precision from the existing fields preserves them exactly; only the order and the selection change. Fields left out of ",[18,1079,1080],{},"order"," are dropped. Putting identifiers first and long free-text columns last makes the attribute table and exported CSVs easier to read. For deleting a few fields from an existing table without rewriting it, ",[30,1083,1085],{"href":1084},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fdelete-fields-pyqgis\u002F","deleting fields"," is simpler.",[128,1088,1090],{"id":1089},"normalise-names-automatically","Normalise names automatically",[14,1092,1093],{},"Spreadsheet and shapefile exports often have names that are awkward in expressions and SQL: spaces, capitals, accents, punctuation, leading digits. A small normaliser turns every name into lower-case snake_case and makes duplicates unique, which is a sensible default before any further work.",[154,1095,1097],{"className":156,"code":1096,"language":158,"meta":159,"style":159},"import re\nimport unicodedata\n\ndef normalise(name):\n    s = unicodedata.normalize(\"NFKD\", name).encode(\"ascii\", \"ignore\").decode()\n    s = re.sub(r\"[^0-9a-zA-Z]+\", \"_\", s).strip(\"_\").lower()\n    return s if s and not s[0].isdigit() else f\"f_{s}\"\n\ndef normalised_mapping(layer):\n    seen, out = {}, []\n    for f in layer.fields():\n        new = normalise(f.name())\n        seen[new] = seen.get(new, 0) + 1\n        if seen[new] > 1:\n            new = f\"{new}_{seen[new]}\"\n        out.append({\"name\": new, \"type\": f.type(), \"length\": f.length(),\n                    \"precision\": f.precision(), \"expression\": f'\"{f.name()}\"'})\n    return out\n\nfor m in normalised_mapping(parcels)[:6]:\n    print(m[\"expression\"], \"→\", m[\"name\"])\n",[18,1098,1099,1106,1113,1117,1127,1154,1195,1239,1243,1253,1263,1275,1285,1305,1320,1350,1368,1394,1401,1406,1426],{"__ignoreMap":159},[163,1100,1101,1103],{"class":165,"line":166},[163,1102,177],{"class":169},[163,1104,1105],{"class":173}," re\n",[163,1107,1108,1110],{"class":165,"line":183},[163,1109,177],{"class":169},[163,1111,1112],{"class":173}," unicodedata\n",[163,1114,1115],{"class":165,"line":190},[163,1116,187],{"emptyLinePlaceholder":186},[163,1118,1119,1121,1124],{"class":165,"line":215},[163,1120,876],{"class":169},[163,1122,1123],{"class":879}," normalise",[163,1125,1126],{"class":173},"(name):\n",[163,1128,1129,1132,1134,1137,1140,1143,1146,1148,1151],{"class":165,"line":258},[163,1130,1131],{"class":173},"    s ",[163,1133,196],{"class":169},[163,1135,1136],{"class":173}," unicodedata.normalize(",[163,1138,1139],{"class":202},"\"NFKD\"",[163,1141,1142],{"class":173},", name).encode(",[163,1144,1145],{"class":202},"\"ascii\"",[163,1147,21],{"class":173},[163,1149,1150],{"class":202},"\"ignore\"",[163,1152,1153],{"class":173},").decode()\n",[163,1155,1156,1158,1160,1163,1166,1168,1171,1174,1177,1180,1182,1184,1187,1190,1192],{"class":165,"line":263},[163,1157,1131],{"class":173},[163,1159,196],{"class":169},[163,1161,1162],{"class":173}," re.sub(",[163,1164,1165],{"class":169},"r",[163,1167,384],{"class":202},[163,1169,1170],{"class":209},"[",[163,1172,1173],{"class":169},"^",[163,1175,1176],{"class":209},"0-9a-zA-Z]",[163,1178,1179],{"class":169},"+",[163,1181,384],{"class":202},[163,1183,21],{"class":173},[163,1185,1186],{"class":202},"\"_\"",[163,1188,1189],{"class":173},", s).strip(",[163,1191,1186],{"class":202},[163,1193,1194],{"class":173},").lower()\n",[163,1196,1197,1199,1202,1205,1207,1210,1212,1215,1217,1220,1223,1226,1229,1231,1234,1236],{"class":165,"line":272},[163,1198,1004],{"class":169},[163,1200,1201],{"class":173}," s ",[163,1203,1204],{"class":169},"if",[163,1206,1201],{"class":173},[163,1208,1209],{"class":169},"and",[163,1211,342],{"class":169},[163,1213,1214],{"class":173}," s[",[163,1216,59],{"class":209},[163,1218,1219],{"class":173},"].isdigit() ",[163,1221,1222],{"class":169},"else",[163,1224,1225],{"class":169}," f",[163,1227,1228],{"class":202},"\"f_",[163,1230,365],{"class":209},[163,1232,1233],{"class":173},"s",[163,1235,371],{"class":209},[163,1237,1238],{"class":202},"\"\n",[163,1240,1241],{"class":165,"line":287},[163,1242,187],{"emptyLinePlaceholder":186},[163,1244,1245,1247,1250],{"class":165,"line":298},[163,1246,876],{"class":169},[163,1248,1249],{"class":879}," normalised_mapping",[163,1251,1252],{"class":173},"(layer):\n",[163,1254,1255,1258,1260],{"class":165,"line":316},[163,1256,1257],{"class":173},"    seen, out ",[163,1259,196],{"class":169},[163,1261,1262],{"class":173}," {}, []\n",[163,1264,1265,1267,1270,1272],{"class":165,"line":331},[163,1266,275],{"class":169},[163,1268,1269],{"class":173}," f ",[163,1271,281],{"class":169},[163,1273,1274],{"class":173}," layer.fields():\n",[163,1276,1277,1280,1282],{"class":165,"line":337},[163,1278,1279],{"class":173},"        new ",[163,1281,196],{"class":169},[163,1283,1284],{"class":173}," normalise(f.name())\n",[163,1286,1287,1290,1292,1295,1297,1300,1302],{"class":165,"line":348},[163,1288,1289],{"class":173},"        seen[new] ",[163,1291,196],{"class":169},[163,1293,1294],{"class":173}," seen.get(new, ",[163,1296,59],{"class":209},[163,1298,1299],{"class":173},") ",[163,1301,1179],{"class":169},[163,1303,1304],{"class":209}," 1\n",[163,1306,1307,1309,1312,1315,1318],{"class":165,"line":390},[163,1308,301],{"class":169},[163,1310,1311],{"class":173}," seen[new] ",[163,1313,1314],{"class":169},">",[163,1316,1317],{"class":209}," 1",[163,1319,313],{"class":173},[163,1321,1323,1326,1328,1330,1332,1334,1336,1338,1341,1343,1346,1348],{"class":165,"line":1322},15,[163,1324,1325],{"class":173},"            new ",[163,1327,196],{"class":169},[163,1329,1225],{"class":169},[163,1331,384],{"class":202},[163,1333,365],{"class":209},[163,1335,379],{"class":173},[163,1337,371],{"class":209},[163,1339,1340],{"class":202},"_",[163,1342,365],{"class":209},[163,1344,1345],{"class":173},"seen[new]",[163,1347,371],{"class":209},[163,1349,1238],{"class":202},[163,1351,1353,1355,1357,1360,1362,1364,1366],{"class":165,"line":1352},16,[163,1354,954],{"class":173},[163,1356,466],{"class":202},[163,1358,1359],{"class":173},": new, ",[163,1361,477],{"class":202},[163,1363,964],{"class":173},[163,1365,483],{"class":202},[163,1367,969],{"class":173},[163,1369,1371,1373,1375,1377,1379,1381,1383,1385,1388,1390,1392],{"class":165,"line":1370},17,[163,1372,974],{"class":202},[163,1374,977],{"class":173},[163,1376,502],{"class":202},[163,1378,229],{"class":173},[163,1380,359],{"class":169},[163,1382,986],{"class":202},[163,1384,365],{"class":209},[163,1386,1387],{"class":173},"f.name()",[163,1389,371],{"class":209},[163,1391,996],{"class":202},[163,1393,999],{"class":173},[163,1395,1397,1399],{"class":165,"line":1396},18,[163,1398,1004],{"class":169},[163,1400,1007],{"class":173},[163,1402,1404],{"class":165,"line":1403},19,[163,1405,187],{"emptyLinePlaceholder":186},[163,1407,1409,1412,1415,1417,1420,1423],{"class":165,"line":1408},20,[163,1410,1411],{"class":169},"for",[163,1413,1414],{"class":173}," m ",[163,1416,281],{"class":169},[163,1418,1419],{"class":173}," normalised_mapping(parcels)[:",[163,1421,1422],{"class":209},"6",[163,1424,1425],{"class":173},"]:\n",[163,1427,1429,1432,1435,1437,1440,1443,1446,1448],{"class":165,"line":1428},21,[163,1430,1431],{"class":209},"    print",[163,1433,1434],{"class":173},"(m[",[163,1436,502],{"class":202},[163,1438,1439],{"class":173},"], ",[163,1441,1442],{"class":202},"\"→\"",[163,1444,1445],{"class":173},", m[",[163,1447,466],{"class":202},[163,1449,1450],{"class":173},"])\n",[14,1452,1453,1455,1456,1459,1460,1463,1464,1466],{},[400,1454,402],{}," Unicode normalisation strips accents so ",[18,1457,1458],{},"Fläche"," becomes ",[18,1461,1462],{},"flache","; any run of non-alphanumeric characters becomes one underscore; names starting with a digit get a prefix because many databases reject them. Counting repeats makes colliding names unique instead of letting the second silently overwrite the first. The function returns a ready field mapping, so the whole cleanup is one ",[18,1465,37],{}," call — and printing old-to-new pairs first lets you review the result before committing to it.",[128,1468,1470],{"id":1469},"set-aliases-for-readable-forms-and-tables","Set aliases for readable forms and tables",[14,1472,1473],{},"Sometimes the stored names must stay as they are — a database schema shared with other systems — but people should see friendly labels. Aliases change what QGIS displays without touching the data.",[154,1475,1477],{"className":156,"code":1476,"language":158,"meta":159,"style":159},"aliases = {\"parcel_id\": \"Parcel ID\", \"owner_name\": \"Owner\", \"area_ha\": \"Area (ha)\",\n           \"land_use\": \"Land use\", \"last_updated\": \"Last updated\"}\nfor name, alias in aliases.items():\n    idx = ordered.fields().indexOf(name)\n    if idx >= 0:\n        ordered.setFieldAlias(idx, alias)\nprint([ordered.attributeDisplayName(i) for i in range(ordered.fields().count())])\n",[18,1478,1479,1516,1537,1549,1559,1573,1578],{"__ignoreMap":159},[163,1480,1481,1484,1486,1488,1490,1492,1495,1497,1499,1501,1504,1506,1508,1510,1513],{"class":165,"line":166},[163,1482,1483],{"class":173},"aliases ",[163,1485,196],{"class":169},[163,1487,223],{"class":173},[163,1489,471],{"class":202},[163,1491,229],{"class":173},[163,1493,1494],{"class":202},"\"Parcel ID\"",[163,1496,21],{"class":173},[163,1498,242],{"class":202},[163,1500,229],{"class":173},[163,1502,1503],{"class":202},"\"Owner\"",[163,1505,21],{"class":173},[163,1507,232],{"class":202},[163,1509,229],{"class":173},[163,1511,1512],{"class":202},"\"Area (ha)\"",[163,1514,1515],{"class":173},",\n",[163,1517,1518,1521,1523,1526,1528,1530,1532,1535],{"class":165,"line":183},[163,1519,1520],{"class":202},"           \"land_use\"",[163,1522,229],{"class":173},[163,1524,1525],{"class":202},"\"Land use\"",[163,1527,21],{"class":173},[163,1529,252],{"class":202},[163,1531,229],{"class":173},[163,1533,1534],{"class":202},"\"Last updated\"",[163,1536,255],{"class":173},[163,1538,1539,1541,1544,1546],{"class":165,"line":190},[163,1540,1411],{"class":169},[163,1542,1543],{"class":173}," name, alias ",[163,1545,281],{"class":169},[163,1547,1548],{"class":173}," aliases.items():\n",[163,1550,1551,1554,1556],{"class":165,"line":215},[163,1552,1553],{"class":173},"    idx ",[163,1555,196],{"class":169},[163,1557,1558],{"class":173}," ordered.fields().indexOf(name)\n",[163,1560,1561,1564,1566,1569,1571],{"class":165,"line":258},[163,1562,1563],{"class":169},"    if",[163,1565,304],{"class":173},[163,1567,1568],{"class":169},">=",[163,1570,310],{"class":209},[163,1572,313],{"class":173},[163,1574,1575],{"class":165,"line":263},[163,1576,1577],{"class":173},"        ordered.setFieldAlias(idx, alias)\n",[163,1579,1580,1582,1585,1587,1590,1592,1595],{"class":165,"line":272},[163,1581,393],{"class":209},[163,1583,1584],{"class":173},"([ordered.attributeDisplayName(i) ",[163,1586,1411],{"class":169},[163,1588,1589],{"class":173}," i ",[163,1591,281],{"class":169},[163,1593,1594],{"class":209}," range",[163,1596,1597],{"class":173},"(ordered.fields().count())])\n",[14,1599,1600,1602],{},[400,1601,402],{}," Aliases appear in the attribute table header, forms, identify results and the expression builder, while expressions and exports still use the real names. They are stored in the layer's style and project, so saving a QML keeps them. Aliases are the right tool for display; renames are the right tool when the data itself will be read by other people or systems.",[128,1604,1606],{"id":1605},"map-a-supplier-schema-onto-a-specification","Map a supplier schema onto a specification",[14,1608,1609],{},"Deliveries from contractors often arrive with their own field names. A mapping saved once and reused for every delivery converts each into the agreed schema and reports anything that does not fit.",[14,1611,1612],{},[42,1613,1616,1619,1622,1625,1632,1635,1640,1645,1649,1655,1659,1663,1667,1670,1676,1680,1685,1691,1695,1699],{"viewBox":1614,"role":45,"ariaLabel":1615,"xmlns":47},"0 0 760 216","A saved field mapping converting each supplier delivery into the target specification, reporting missing and unmapped fields",[49,1617,1618],{},"Delivery to specification",[53,1620,1621],{},"A target specification lists required fields with names and types. A saved mapping from the supplier's names to the specification is applied to each delivery. Fields the specification requires but the delivery lacks are reported as missing; extra delivery fields are reported as unmapped. Conforming deliveries pass straight through.",[57,1623],{"x":59,"y":59,"width":60,"height":1624,"fill":62},"216",[775,1626,1627],{},[778,1628,1630],{"id":1629,"viewBox":781,"refX":78,"refY":782,"markerWidth":783,"markerHeight":783,"orient":784},"rnSpecArrow",[786,1631],{"d":788,"fill":92},[64,1633,1634],{"x":66,"y":67,"style":68,"fill":69,"textAnchor":70},"One mapping, every delivery",[57,1636],{"x":74,"y":1637,"width":1638,"height":1639,"rx":78,"fill":797,"stroke":101,"style":81},"60","200","130",[64,1641,1644],{"x":1642,"y":1643,"style":86,"fill":69,"textAnchor":70},"124","115.78","delivery",[64,1646,1648],{"x":1642,"y":1647,"style":91,"fill":101,"textAnchor":70},"141.78","supplier names",[165,1650],{"x1":1651,"y1":1652,"x2":1653,"y2":1652,"stroke":92,"style":1654},"224","125","266","stroke-width:1.8;marker-end:url(#rnSpecArrow)",[57,1656],{"x":1657,"y":1637,"width":1658,"height":1639,"rx":78,"fill":79,"stroke":80,"style":81},"270","220",[64,1660,1662],{"x":66,"y":1661,"style":86,"fill":80,"textAnchor":70},"102.78","saved mapping",[64,1664,1666],{"x":66,"y":1665,"style":91,"fill":101,"textAnchor":70},"128.78","JSON",[64,1668,1669],{"x":66,"y":96,"style":91,"fill":101,"textAnchor":70},"spec ← supplier",[165,1671],{"x1":1672,"y1":1673,"x2":1674,"y2":1675,"stroke":92,"style":1654},"490","100","532","80",[165,1677],{"x1":1672,"y1":1678,"x2":1674,"y2":1679,"stroke":92,"style":1654},"150","170",[57,1681],{"x":1682,"y":794,"width":1638,"height":1637,"rx":78,"fill":1683,"stroke":1684,"style":81},"536","#e8efe6","#15803d",[64,1686,1690],{"x":1687,"y":1688,"style":802,"fill":1689,"textAnchor":70},"636","85.6","#166534","conforming layer",[57,1692],{"x":1682,"y":827,"width":1638,"height":1637,"rx":78,"fill":1693,"stroke":1694,"style":81},"#fdf2e2","#b45309",[64,1696,1698],{"x":1687,"y":1697,"style":802,"fill":1694,"textAnchor":70},"164.6","report",[64,1700,1701],{"x":1687,"y":818,"style":858,"fill":101,"textAnchor":70},"missing · unmapped",[154,1703,1705],{"className":156,"code":1704,"language":158,"meta":159,"style":159},"import json\n\nspec = json.load(open(\"\u002Fdata\u002Fspecs\u002Fparcels_v3.json\"))        # [{\"name\", \"type\", \"length\", \"from\"}]\ntype_map = {\"string\": QVariant.String, \"double\": QVariant.Double,\n            \"int\": QVariant.LongLong, \"date\": QVariant.Date}\n\ndelivery = QgsVectorLayer(\"\u002Fdata\u002Finbox\u002Fcontractor_parcels.gpkg\", \"delivery\", \"ogr\")\nnames = set(delivery.fields().names())\nmissing = [s[\"name\"] for s in spec if s[\"from\"] not in names]\nunmapped = sorted(names - {s[\"from\"] for s in spec})\n\nmapping = [{\"name\": s[\"name\"], \"type\": type_map[s[\"type\"]], \"length\": s.get(\"length\", 0),\n            \"precision\": s.get(\"precision\", 0),\n            \"expression\": f'\"{s[\"from\"]}\"' if s[\"from\"] in names else \"NULL\"} for s in spec]\nconformed = processing.run(\"native:refactorfields\", {\n    \"INPUT\": delivery, \"FIELDS_MAPPING\": mapping, \"OUTPUT\": \"memory:\"})[\"OUTPUT\"]\nprint(\"missing:\", missing, \"| unmapped:\", unmapped)\n",[18,1706,1707,1714,1718,1743,1763,1777,1781,1806,1819,1861,1893,1897,1939,1954,2010,2023,2047],{"__ignoreMap":159},[163,1708,1709,1711],{"class":165,"line":166},[163,1710,177],{"class":169},[163,1712,1713],{"class":173}," json\n",[163,1715,1716],{"class":165,"line":183},[163,1717,187],{"emptyLinePlaceholder":186},[163,1719,1720,1723,1725,1728,1731,1733,1736,1739],{"class":165,"line":190},[163,1721,1722],{"class":173},"spec ",[163,1724,196],{"class":169},[163,1726,1727],{"class":173}," json.load(",[163,1729,1730],{"class":209},"open",[163,1732,322],{"class":173},[163,1734,1735],{"class":202},"\"\u002Fdata\u002Fspecs\u002Fparcels_v3.json\"",[163,1737,1738],{"class":173},"))        ",[163,1740,1742],{"class":1741},"sjoCn","# [{\"name\", \"type\", \"length\", \"from\"}]\n",[163,1744,1745,1748,1750,1752,1755,1757,1760],{"class":165,"line":215},[163,1746,1747],{"class":173},"type_map ",[163,1749,196],{"class":169},[163,1751,223],{"class":173},[163,1753,1754],{"class":202},"\"string\"",[163,1756,480],{"class":173},[163,1758,1759],{"class":202},"\"double\"",[163,1761,1762],{"class":173},": QVariant.Double,\n",[163,1764,1765,1768,1771,1774],{"class":165,"line":258},[163,1766,1767],{"class":202},"            \"int\"",[163,1769,1770],{"class":173},": QVariant.LongLong, ",[163,1772,1773],{"class":202},"\"date\"",[163,1775,1776],{"class":173},": QVariant.Date}\n",[163,1778,1779],{"class":165,"line":263},[163,1780,187],{"emptyLinePlaceholder":186},[163,1782,1783,1786,1788,1791,1794,1796,1799,1801,1804],{"class":165,"line":272},[163,1784,1785],{"class":173},"delivery ",[163,1787,196],{"class":169},[163,1789,1790],{"class":173}," QgsVectorLayer(",[163,1792,1793],{"class":202},"\"\u002Fdata\u002Finbox\u002Fcontractor_parcels.gpkg\"",[163,1795,21],{"class":173},[163,1797,1798],{"class":202},"\"delivery\"",[163,1800,21],{"class":173},[163,1802,1803],{"class":202},"\"ogr\"",[163,1805,387],{"class":173},[163,1807,1808,1811,1813,1816],{"class":165,"line":287},[163,1809,1810],{"class":173},"names ",[163,1812,196],{"class":169},[163,1814,1815],{"class":209}," set",[163,1817,1818],{"class":173},"(delivery.fields().names())\n",[163,1820,1821,1824,1826,1829,1831,1834,1836,1838,1840,1843,1845,1847,1850,1852,1855,1858],{"class":165,"line":298},[163,1822,1823],{"class":173},"missing ",[163,1825,196],{"class":169},[163,1827,1828],{"class":173}," [s[",[163,1830,466],{"class":202},[163,1832,1833],{"class":173},"] ",[163,1835,1411],{"class":169},[163,1837,1201],{"class":173},[163,1839,281],{"class":169},[163,1841,1842],{"class":173}," spec ",[163,1844,1204],{"class":169},[163,1846,1214],{"class":173},[163,1848,1849],{"class":202},"\"from\"",[163,1851,1833],{"class":173},[163,1853,1854],{"class":169},"not",[163,1856,1857],{"class":169}," in",[163,1859,1860],{"class":173}," names]\n",[163,1862,1863,1866,1868,1871,1874,1877,1880,1882,1884,1886,1888,1890],{"class":165,"line":316},[163,1864,1865],{"class":173},"unmapped ",[163,1867,196],{"class":169},[163,1869,1870],{"class":209}," sorted",[163,1872,1873],{"class":173},"(names ",[163,1875,1876],{"class":169},"-",[163,1878,1879],{"class":173}," {s[",[163,1881,1849],{"class":202},[163,1883,1833],{"class":173},[163,1885,1411],{"class":169},[163,1887,1201],{"class":173},[163,1889,281],{"class":169},[163,1891,1892],{"class":173}," spec})\n",[163,1894,1895],{"class":165,"line":331},[163,1896,187],{"emptyLinePlaceholder":186},[163,1898,1899,1901,1903,1906,1908,1911,1913,1915,1917,1920,1922,1925,1927,1930,1932,1934,1936],{"class":165,"line":337},[163,1900,453],{"class":173},[163,1902,196],{"class":169},[163,1904,1905],{"class":173}," [{",[163,1907,466],{"class":202},[163,1909,1910],{"class":173},": s[",[163,1912,466],{"class":202},[163,1914,1439],{"class":173},[163,1916,477],{"class":202},[163,1918,1919],{"class":173},": type_map[s[",[163,1921,477],{"class":202},[163,1923,1924],{"class":173},"]], ",[163,1926,483],{"class":202},[163,1928,1929],{"class":173},": s.get(",[163,1931,483],{"class":202},[163,1933,21],{"class":173},[163,1935,59],{"class":209},[163,1937,1938],{"class":173},"),\n",[163,1940,1941,1944,1946,1948,1950,1952],{"class":165,"line":348},[163,1942,1943],{"class":202},"            \"precision\"",[163,1945,1929],{"class":173},[163,1947,493],{"class":202},[163,1949,21],{"class":173},[163,1951,59],{"class":209},[163,1953,1938],{"class":173},[163,1955,1956,1959,1961,1963,1965,1967,1970,1972,1975,1977,1979,1982,1984,1986,1988,1990,1993,1995,1998,2001,2003,2005,2007],{"class":165,"line":390},[163,1957,1958],{"class":202},"            \"expression\"",[163,1960,229],{"class":173},[163,1962,359],{"class":169},[163,1964,986],{"class":202},[163,1966,365],{"class":209},[163,1968,1969],{"class":173},"s[",[163,1971,1849],{"class":202},[163,1973,1974],{"class":173},"]",[163,1976,371],{"class":209},[163,1978,996],{"class":202},[163,1980,1981],{"class":169}," if",[163,1983,1214],{"class":173},[163,1985,1849],{"class":202},[163,1987,1833],{"class":173},[163,1989,281],{"class":169},[163,1991,1992],{"class":173}," names ",[163,1994,1222],{"class":169},[163,1996,1997],{"class":202}," \"NULL\"",[163,1999,2000],{"class":173},"} ",[163,2002,1411],{"class":169},[163,2004,1201],{"class":173},[163,2006,281],{"class":169},[163,2008,2009],{"class":173}," spec]\n",[163,2011,2012,2015,2017,2019,2021],{"class":165,"line":1322},[163,2013,2014],{"class":173},"conformed ",[163,2016,196],{"class":169},[163,2018,699],{"class":173},[163,2020,702],{"class":202},[163,2022,705],{"class":173},[163,2024,2025,2027,2030,2032,2034,2036,2038,2041,2043,2045],{"class":165,"line":1352},[163,2026,710],{"class":202},[163,2028,2029],{"class":173},": delivery, ",[163,2031,716],{"class":202},[163,2033,719],{"class":173},[163,2035,722],{"class":202},[163,2037,229],{"class":173},[163,2039,2040],{"class":202},"\"memory:\"",[163,2042,730],{"class":173},[163,2044,722],{"class":202},[163,2046,212],{"class":173},[163,2048,2049,2051,2053,2056,2059,2062],{"class":165,"line":1370},[163,2050,393],{"class":209},[163,2052,322],{"class":173},[163,2054,2055],{"class":202},"\"missing:\"",[163,2057,2058],{"class":173},", missing, ",[163,2060,2061],{"class":202},"\"| unmapped:\"",[163,2063,2064],{"class":173},", unmapped)\n",[14,2066,2067,2069,2070,2073],{},[400,2068,402],{}," Keeping the specification and the supplier mapping in a JSON file makes the conversion data, not code — update the file when the specification or the supplier changes. Missing source fields are filled with NULL so the output always has the full schema, and are reported so someone can chase them. Unmapped fields are listed rather than silently dropped, which often reveals useful columns the specification should adopt. Add ",[18,2071,2072],{},"from qgis.core import QgsVectorLayer"," when running this alone.",[128,2075,2077],{"id":2076},"qgis-version-compatibility","QGIS version compatibility",[14,2079,2080,2082,2083,2085,2086,21,2088,21,2091,21,2094,2097,2098,2101,2102,21,2104,21,2107,2097,2110,2113,2114,2117,2118,2121],{},[18,2081,151],{},", field aliases and ",[18,2084,37],{}," work on QGIS 3.34 LTR, 3.40 LTR and QGIS 4. The field mapping format with ",[18,2087,991],{},[18,2089,2090],{},"type",[18,2092,2093],{},"length",[18,2095,2096],{},"precision"," and ",[18,2099,2100],{},"expression"," keys is stable; recent releases add ",[18,2103,753],{},[18,2105,2106],{},"type_name",[18,2108,2109],{},"alias",[18,2111,2112],{},"comment"," keys. On QGIS 4, types are ",[18,2115,2116],{},"QMetaType.Type"," values such as ",[18,2119,2120],{},"QMetaType.Type.QString",".",[128,2123,2125],{"id":2124},"troubleshooting","Troubleshooting",[133,2127,2128,2136,2142,2148],{},[136,2129,2130,2135],{},[400,2131,2132,2134],{},[18,2133,151],{}," returns False."," The provider does not support renaming, or the layer is read-only; use refactor fields.",[136,2137,2138,2141],{},[400,2139,2140],{},"Styles and labels broke after renaming."," They referenced the old names; update expressions or use aliases instead.",[136,2143,2144,2147],{},[400,2145,2146],{},"Refactor produced NULL columns."," The expression references a misspelled source field.",[136,2149,2150,2153],{},[400,2151,2152],{},"Shapefile names are still truncated."," Shapefiles limit names to ten characters; write to GeoPackage.",[128,2155,2157],{"id":2156},"conclusion","Conclusion",[14,2159,2160,2161,2163,2164,2166,2167,2169],{},"Rename a few fields in place with ",[18,2162,151],{}," inside ",[18,2165,409],{},", rebuild whole schemas with ",[18,2168,37],{}," where each field is named, typed and filled by an expression, reorder and drop by generating mappings from existing fields, use aliases when stored names must stay, and keep supplier-to-specification mappings in a file reused for every delivery.",[128,2171,2173],{"id":2172},"frequently-asked-questions","Frequently Asked Questions",[14,2175,2176,2179],{},[400,2177,2178],{},"Does refactoring keep feature ids?","\nIn memory and GeoPackage outputs, new ids are assigned. Keep a business key field to link back to the source.",[14,2181,2182,2185,2186,2188,2189,2192],{},[400,2183,2184],{},"Can I rename fields in PostGIS?","\nYes, through ",[18,2187,151],{}," or with ",[18,2190,2191],{},"ALTER TABLE … RENAME COLUMN"," via the connections API.",[14,2194,2195,2198],{},[400,2196,2197],{},"Do aliases export to other formats?","\nOnly to formats that store them, such as GeoPackage with QGIS metadata; most formats keep the real names.",[14,2200,2201,2204],{},[400,2202,2203],{},"Can I add a computed field while refactoring?","\nYes — any expression works, including geometry functions and constants.",[128,2206,2208],{"id":2207},"related","Related",[133,2210,2211,2216,2222,2227,2233],{},[136,2212,2213,2215],{},[30,2214,33],{"href":32}," — the guide this recipe belongs to",[136,2217,2218],{},[30,2219,2221],{"href":2220},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fchange-field-type-pyqgis\u002F","Change a Field Type in PyQGIS",[136,2223,2224],{},[30,2225,2226],{"href":1084},"Delete Fields in PyQGIS",[136,2228,2229],{},[30,2230,2232],{"href":2231},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fcalculate-field-with-expression-pyqgis\u002F","Calculate a Field with an Expression in PyQGIS",[136,2234,2235],{},[30,2236,2238],{"href":2237},"\u002Fqgis-plugin-development\u002Fattribute-forms-and-layer-actions\u002Fconfigure-editor-widgets-pyqgis\u002F","Configure Editor Widgets in PyQGIS",[2240,2241,2242],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}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 pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}",{"title":159,"searchDepth":183,"depth":183,"links":2244},[2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256],{"id":130,"depth":183,"text":131},{"id":144,"depth":183,"text":145},{"id":413,"depth":183,"text":414},{"id":862,"depth":183,"text":863},{"id":1089,"depth":183,"text":1090},{"id":1469,"depth":183,"text":1470},{"id":1605,"depth":183,"text":1606},{"id":2076,"depth":183,"text":2077},{"id":2124,"depth":183,"text":2125},{"id":2156,"depth":183,"text":2157},{"id":2172,"depth":183,"text":2173},{"id":2207,"depth":183,"text":2208},"Tidy a layer's schema from Python — renaming fields in place with renameAttribute, building a clean output schema with native:refactorfields, reordering and dropping columns, setting aliases for readable forms, and mapping one schema onto another for data exchange.","md",{"slug":2260,"type":2261,"breadcrumb":2262,"datePublished":2263,"dateModified":2263},"rename-and-reorder-fields-pyqgis","article","Rename and Reorder Fields","2026-10-02","\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Frename-and-reorder-fields-pyqgis",{"title":5,"description":2257},"spatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Frename-and-reorder-fields-pyqgis\u002Findex","xbpioK7hROD0uFNDBFscDQMxNFLu_JAggDgW1vBeGGk",1790966260302]