[{"data":1,"prerenderedAt":1753},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fdelete-fields-pyqgis":3},{"id":4,"title":5,"body":6,"description":1742,"extension":1743,"meta":1744,"navigation":273,"path":1749,"seo":1750,"stem":1751,"__hash__":1752},"docs\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fdelete-fields-pyqgis\u002Findex.md","Delete and Rename Fields in PyQGIS",{"type":7,"value":8,"toc":1729},"minimark",[9,13,22,31,206,211,232,236,239,579,605,609,616,734,743,747,750,899,911,914,929,938,942,945,1054,1132,1149,1153,1156,1253,1505,1517,1521,1527,1589,1603,1607,1652,1656,1662,1666,1672,1681,1691,1697,1701,1725],[10,11,5],"h1",{"id":12},"delete-and-rename-fields-in-pyqgis",[14,15,16,17,21],"p",{},"Deleting a field looks symmetrical with adding one, and it is not. Field indexes are ",[18,19,20],"em",{},"positional",": remove the field at index 3 and every field after it shifts down by one. A loop that resolves an index, deletes it, resolves the next and deletes that will remove the wrong columns — and because the operation succeeds, nothing tells you until the data is already gone. Renaming has its own asymmetry: not every provider supports it, and the ones that do not fail silently.",[14,23,24,25,30],{},"This page is a focused recipe within ",[26,27,29],"a",{"href":28},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002F","Attribute Tables and Field Management in PyQGIS",". It covers deleting one or several fields safely, renaming, keeping a whitelist rather than a blacklist, and the non-destructive alternative that writes a clean copy.",[14,32,33],{},[34,35,40,44,48,55,72,81,87,135,143,148,177,181,185],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 268","img","Deleting fields in ascending index order removes the wrong columns because indexes shift, whereas descending order removes exactly the intended ones","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"Why deletion order matters",[45,46,47],"desc",{},"A five-column table is shown. Deleting index one then index three in ascending order removes the intended second column but then the wrong fourth column, because every index after the first deletion has shifted down. Deleting index three then index one in descending order removes exactly the two intended columns.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","268","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"delOrderArrow","0 0 10 10","8","5","7","auto-start-reverse",[68,69],"path",{"d":70,"fill":71},"M0 0 L10 5 L0 10 z","#2f3b35",[73,74,80],"text",{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"380","24","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Delete indexes 1 and 3 — the order decides which columns actually go",[73,82,86],{"x":83,"y":84,"style":85,"fill":78},"30","62","font-size:11.5px;font-weight:bold;font-family:sans-serif","start",[88,89,90,99,105,111,114,117,121,124,128,131],"g",{},[49,91],{"x":92,"y":93,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},"96","44","112","4","#fffdf7","#59645f","stroke-width:1.5",[73,100,104],{"x":101,"y":102,"style":103,"fill":71,"textAnchor":79},"152","64","text-anchor:middle;font-size:11px;font-family:sans-serif","0 · id",[49,106],{"x":107,"y":93,"width":94,"height":83,"rx":95,"fill":108,"fillOpacity":109,"stroke":108,"style":110},"212","#b91c1c",0.2,"stroke-width:2",[73,112,113],{"x":53,"y":102,"style":103,"fill":71,"textAnchor":79},"1 · tmp_a",[49,115],{"x":116,"y":93,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},"328",[73,118,120],{"x":119,"y":102,"style":103,"fill":71,"textAnchor":79},"384","2 · owner",[49,122],{"x":123,"y":93,"width":94,"height":83,"rx":95,"fill":108,"fillOpacity":109,"stroke":108,"style":110},"444",[73,125,127],{"x":126,"y":102,"style":103,"fill":71,"textAnchor":79},"500","3 · tmp_b",[49,129],{"x":130,"y":93,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},"560",[73,132,134],{"x":133,"y":102,"style":103,"fill":71,"textAnchor":79},"616","4 · value",[49,136],{"x":137,"y":138,"width":139,"height":140,"rx":141,"fill":96,"stroke":108,"style":142},"16","94","728","76","10","stroke-width:2.5",[73,144,147],{"x":145,"y":146,"style":85,"fill":108},"36","116","ascending: delete 1, then 3",[88,149,150,153,156,158,161,163,166,169,172],{},[49,151],{"x":92,"y":152,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},"128",[73,154,104],{"x":101,"y":155,"style":103,"fill":71,"textAnchor":79},"148",[49,157],{"x":107,"y":152,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},[73,159,160],{"x":53,"y":155,"style":103,"fill":71,"textAnchor":79},"1 · owner",[49,162],{"x":116,"y":152,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},[73,164,165],{"x":119,"y":155,"style":103,"fill":71,"textAnchor":79},"2 · tmp_b",[49,167],{"x":123,"y":152,"width":94,"height":83,"rx":95,"fill":108,"fillOpacity":168,"stroke":108,"style":142},0.35,[73,170,171],{"x":126,"y":155,"style":103,"fill":71,"textAnchor":79},"3 · value ✗",[73,173,176],{"x":174,"y":155,"style":175,"fill":108},"580","font-size:11px;font-weight:bold;font-family:sans-serif","wrong column deleted",[49,178],{"x":137,"y":179,"width":139,"height":140,"rx":141,"fill":96,"stroke":180,"style":142},"182","#15803d",[73,182,184],{"x":145,"y":183,"style":85,"fill":180},"204","descending: delete 3, then 1",[88,186,187,190,193,195,197,199,202],{},[49,188],{"x":92,"y":189,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},"216",[73,191,104],{"x":101,"y":192,"style":103,"fill":71,"textAnchor":79},"236",[49,194],{"x":107,"y":189,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},[73,196,160],{"x":53,"y":192,"style":103,"fill":71,"textAnchor":79},[49,198],{"x":116,"y":189,"width":94,"height":83,"rx":95,"fill":96,"stroke":97,"style":98},[73,200,201],{"x":119,"y":192,"style":103,"fill":71,"textAnchor":79},"2 · value",[73,203,205],{"x":204,"y":192,"style":175,"fill":180},"470","exactly the two intended",[207,208,210],"h2",{"id":209},"prerequisites","Prerequisites",[212,213,214,222,229],"ul",{},[215,216,217,221],"li",{},[218,219,220],"strong",{},"QGIS 3.34 LTR"," (bundled Python 3.12) or newer.",[215,223,224,225,228],{},"A ",[218,226,227],{},"writable"," vector layer, and a backup. Field deletion through the provider is immediate and cannot be undone.",[215,230,231],{},"The field names you intend to remove, not their indexes — resolve indexes at the moment of deletion.",[207,233,235],{"id":234},"delete-fields-safely","Delete fields safely",[14,237,238],{},"Resolve every index first, filter out the misses, and delete in descending order.",[240,241,246],"pre",{"className":242,"code":243,"language":244,"meta":245,"style":245},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject, QgsVectorDataProvider\n\nlayer = QgsProject.instance().mapLayersByName(\"parcels\")[0]\nprovider = layer.dataProvider()\n\nif not provider.capabilities() & QgsVectorDataProvider.DeleteAttributes:\n    raise RuntimeError(f\"{layer.name()} does not support deleting fields\")\n\ntargets = [\"tmp_a\", \"tmp_b\", \"scratch\"]\nindexes = [layer.fields().indexOf(name) for name in targets]\nmissing = [name for name, i in zip(targets, indexes) if i == -1]\nindexes = sorted((i for i in indexes if i != -1), reverse=True)\n\nif missing:\n    print(\"not present, skipping:\", \", \".join(missing))\n\nif indexes:\n    provider.deleteAttributes(indexes)\n    layer.updateFields()\n    print(\"remaining fields:\", layer.fields().names())\n","python","",[247,248,249,268,275,300,311,316,334,367,372,399,422,462,509,514,522,541,546,554,560,566],"code",{"__ignoreMap":245},[250,251,254,258,262,265],"span",{"class":252,"line":253},"line",1,[250,255,257],{"class":256},"snl16","from",[250,259,261],{"class":260},"s95oV"," qgis.core ",[250,263,264],{"class":256},"import",[250,266,267],{"class":260}," QgsProject, QgsVectorDataProvider\n",[250,269,271],{"class":252,"line":270},2,[250,272,274],{"emptyLinePlaceholder":273},true,"\n",[250,276,278,281,284,287,291,294,297],{"class":252,"line":277},3,[250,279,280],{"class":260},"layer ",[250,282,283],{"class":256},"=",[250,285,286],{"class":260}," QgsProject.instance().mapLayersByName(",[250,288,290],{"class":289},"sU2Wk","\"parcels\"",[250,292,293],{"class":260},")[",[250,295,51],{"class":296},"sDLfK",[250,298,299],{"class":260},"]\n",[250,301,303,306,308],{"class":252,"line":302},4,[250,304,305],{"class":260},"provider ",[250,307,283],{"class":256},[250,309,310],{"class":260}," layer.dataProvider()\n",[250,312,314],{"class":252,"line":313},5,[250,315,274],{"emptyLinePlaceholder":273},[250,317,319,322,325,328,331],{"class":252,"line":318},6,[250,320,321],{"class":256},"if",[250,323,324],{"class":256}," not",[250,326,327],{"class":260}," provider.capabilities() ",[250,329,330],{"class":256},"&",[250,332,333],{"class":260}," QgsVectorDataProvider.DeleteAttributes:\n",[250,335,337,340,343,346,349,352,355,358,361,364],{"class":252,"line":336},7,[250,338,339],{"class":256},"    raise",[250,341,342],{"class":296}," RuntimeError",[250,344,345],{"class":260},"(",[250,347,348],{"class":256},"f",[250,350,351],{"class":289},"\"",[250,353,354],{"class":296},"{",[250,356,357],{"class":260},"layer.name()",[250,359,360],{"class":296},"}",[250,362,363],{"class":289}," does not support deleting fields\"",[250,365,366],{"class":260},")\n",[250,368,370],{"class":252,"line":369},8,[250,371,274],{"emptyLinePlaceholder":273},[250,373,375,378,380,383,386,389,392,394,397],{"class":252,"line":374},9,[250,376,377],{"class":260},"targets ",[250,379,283],{"class":256},[250,381,382],{"class":260}," [",[250,384,385],{"class":289},"\"tmp_a\"",[250,387,388],{"class":260},", ",[250,390,391],{"class":289},"\"tmp_b\"",[250,393,388],{"class":260},[250,395,396],{"class":289},"\"scratch\"",[250,398,299],{"class":260},[250,400,402,405,407,410,413,416,419],{"class":252,"line":401},10,[250,403,404],{"class":260},"indexes ",[250,406,283],{"class":256},[250,408,409],{"class":260}," [layer.fields().indexOf(name) ",[250,411,412],{"class":256},"for",[250,414,415],{"class":260}," name ",[250,417,418],{"class":256},"in",[250,420,421],{"class":260}," targets]\n",[250,423,425,428,430,433,435,438,440,443,446,448,451,454,457,460],{"class":252,"line":424},11,[250,426,427],{"class":260},"missing ",[250,429,283],{"class":256},[250,431,432],{"class":260}," [name ",[250,434,412],{"class":256},[250,436,437],{"class":260}," name, i ",[250,439,418],{"class":256},[250,441,442],{"class":296}," zip",[250,444,445],{"class":260},"(targets, indexes) ",[250,447,321],{"class":256},[250,449,450],{"class":260}," i ",[250,452,453],{"class":256},"==",[250,455,456],{"class":256}," -",[250,458,459],{"class":296},"1",[250,461,299],{"class":260},[250,463,465,467,469,472,475,477,479,481,484,486,488,491,493,495,498,502,504,507],{"class":252,"line":464},12,[250,466,404],{"class":260},[250,468,283],{"class":256},[250,470,471],{"class":296}," sorted",[250,473,474],{"class":260},"((i ",[250,476,412],{"class":256},[250,478,450],{"class":260},[250,480,418],{"class":256},[250,482,483],{"class":260}," indexes ",[250,485,321],{"class":256},[250,487,450],{"class":260},[250,489,490],{"class":256},"!=",[250,492,456],{"class":256},[250,494,459],{"class":296},[250,496,497],{"class":260},"), ",[250,499,501],{"class":500},"s9osk","reverse",[250,503,283],{"class":256},[250,505,506],{"class":296},"True",[250,508,366],{"class":260},[250,510,512],{"class":252,"line":511},13,[250,513,274],{"emptyLinePlaceholder":273},[250,515,517,519],{"class":252,"line":516},14,[250,518,321],{"class":256},[250,520,521],{"class":260}," missing:\n",[250,523,525,528,530,533,535,538],{"class":252,"line":524},15,[250,526,527],{"class":296},"    print",[250,529,345],{"class":260},[250,531,532],{"class":289},"\"not present, skipping:\"",[250,534,388],{"class":260},[250,536,537],{"class":289},"\", \"",[250,539,540],{"class":260},".join(missing))\n",[250,542,544],{"class":252,"line":543},16,[250,545,274],{"emptyLinePlaceholder":273},[250,547,549,551],{"class":252,"line":548},17,[250,550,321],{"class":256},[250,552,553],{"class":260}," indexes:\n",[250,555,557],{"class":252,"line":556},18,[250,558,559],{"class":260},"    provider.deleteAttributes(indexes)\n",[250,561,563],{"class":252,"line":562},19,[250,564,565],{"class":260},"    layer.updateFields()\n",[250,567,569,571,573,576],{"class":252,"line":568},20,[250,570,527],{"class":296},[250,572,345],{"class":260},[250,574,575],{"class":289},"\"remaining fields:\"",[250,577,578],{"class":260},", layer.fields().names())\n",[14,580,581,584,585,588,589,592,593,596,597,600,601,604],{},[218,582,583],{},"Breakdown:"," Resolving all the indexes ",[18,586,587],{},"before"," any deletion is what makes the descending sort valid — every index refers to the original schema. Sorting descending means each removal only shifts indexes that have already been handled. ",[247,590,591],{},"indexOf()"," returns ",[247,594,595],{},"-1"," for a missing field, and passing that to ",[247,598,599],{},"deleteAttributes()"," is silently ignored, so filtering it out and reporting it separately turns a hidden no-op into visible information. ",[247,602,603],{},"updateFields()"," refreshes the layer's cached schema, exactly as it does after adding.",[207,606,608],{"id":607},"keep-a-whitelist-instead","Keep a whitelist instead",[14,610,611,612,615],{},"Naming what to remove breaks as soon as an upstream dataset gains a column. Naming what to ",[18,613,614],{},"keep"," is stable, and is usually what a pipeline actually means.",[240,617,619],{"className":242,"code":618,"language":244,"meta":245,"style":245},"KEEP = {\"parcel_id\", \"owner\", \"zoning\", \"assessed_value\"}\n\nindexes = sorted(\n    (i for i, field in enumerate(layer.fields()) if field.name() not in KEEP),\n    reverse=True,\n)\nif indexes:\n    layer.dataProvider().deleteAttributes(indexes)\n    layer.updateFields()\n",[247,620,621,653,657,668,703,715,719,725,730],{"__ignoreMap":245},[250,622,623,626,629,632,635,637,640,642,645,647,650],{"class":252,"line":253},[250,624,625],{"class":296},"KEEP",[250,627,628],{"class":256}," =",[250,630,631],{"class":260}," {",[250,633,634],{"class":289},"\"parcel_id\"",[250,636,388],{"class":260},[250,638,639],{"class":289},"\"owner\"",[250,641,388],{"class":260},[250,643,644],{"class":289},"\"zoning\"",[250,646,388],{"class":260},[250,648,649],{"class":289},"\"assessed_value\"",[250,651,652],{"class":260},"}\n",[250,654,655],{"class":252,"line":270},[250,656,274],{"emptyLinePlaceholder":273},[250,658,659,661,663,665],{"class":252,"line":277},[250,660,404],{"class":260},[250,662,283],{"class":256},[250,664,471],{"class":296},[250,666,667],{"class":260},"(\n",[250,669,670,673,675,678,680,683,686,688,691,694,697,700],{"class":252,"line":302},[250,671,672],{"class":260},"    (i ",[250,674,412],{"class":256},[250,676,677],{"class":260}," i, field ",[250,679,418],{"class":256},[250,681,682],{"class":296}," enumerate",[250,684,685],{"class":260},"(layer.fields()) ",[250,687,321],{"class":256},[250,689,690],{"class":260}," field.name() ",[250,692,693],{"class":256},"not",[250,695,696],{"class":256}," in",[250,698,699],{"class":296}," KEEP",[250,701,702],{"class":260},"),\n",[250,704,705,708,710,712],{"class":252,"line":313},[250,706,707],{"class":500},"    reverse",[250,709,283],{"class":256},[250,711,506],{"class":296},[250,713,714],{"class":260},",\n",[250,716,717],{"class":252,"line":318},[250,718,366],{"class":260},[250,720,721,723],{"class":252,"line":336},[250,722,321],{"class":256},[250,724,553],{"class":260},[250,726,727],{"class":252,"line":369},[250,728,729],{"class":260},"    layer.dataProvider().deleteAttributes(indexes)\n",[250,731,732],{"class":252,"line":374},[250,733,565],{"class":260},[14,735,736,738,739,742],{},[218,737,583],{}," ",[247,740,741],{},"enumerate(layer.fields())"," gives index and field together, so the whitelist test and the index come from one pass. The descending sort is still required. This form is the right default for a script that consumes data you do not control — a new column appearing upstream is dropped automatically rather than silently propagating through your outputs.",[207,744,746],{"id":745},"rename-a-field","Rename a field",[14,748,749],{},"Renaming is a separate provider capability, and support is uneven: GeoPackage and PostGIS handle it, shapefile does not.",[240,751,753],{"className":242,"code":752,"language":244,"meta":245,"style":245},"from qgis.core import QgsProject, QgsVectorDataProvider\n\nlayer = QgsProject.instance().mapLayersByName(\"parcels\")[0]\nprovider = layer.dataProvider()\n\nif not provider.capabilities() & QgsVectorDataProvider.RenameAttributes:\n    raise RuntimeError(\"this provider cannot rename fields\")\n\nindex = layer.fields().indexOf(\"assessed_value\")\nif index == -1:\n    raise KeyError(\"field not found\")\n\nif provider.renameAttributes({index: \"value_assessed\"}):\n    layer.updateFields()\n    print(layer.fields().names())\n",[247,754,755,765,769,785,793,797,810,823,827,841,857,871,875,888,892],{"__ignoreMap":245},[250,756,757,759,761,763],{"class":252,"line":253},[250,758,257],{"class":256},[250,760,261],{"class":260},[250,762,264],{"class":256},[250,764,267],{"class":260},[250,766,767],{"class":252,"line":270},[250,768,274],{"emptyLinePlaceholder":273},[250,770,771,773,775,777,779,781,783],{"class":252,"line":277},[250,772,280],{"class":260},[250,774,283],{"class":256},[250,776,286],{"class":260},[250,778,290],{"class":289},[250,780,293],{"class":260},[250,782,51],{"class":296},[250,784,299],{"class":260},[250,786,787,789,791],{"class":252,"line":302},[250,788,305],{"class":260},[250,790,283],{"class":256},[250,792,310],{"class":260},[250,794,795],{"class":252,"line":313},[250,796,274],{"emptyLinePlaceholder":273},[250,798,799,801,803,805,807],{"class":252,"line":318},[250,800,321],{"class":256},[250,802,324],{"class":256},[250,804,327],{"class":260},[250,806,330],{"class":256},[250,808,809],{"class":260}," QgsVectorDataProvider.RenameAttributes:\n",[250,811,812,814,816,818,821],{"class":252,"line":336},[250,813,339],{"class":256},[250,815,342],{"class":296},[250,817,345],{"class":260},[250,819,820],{"class":289},"\"this provider cannot rename fields\"",[250,822,366],{"class":260},[250,824,825],{"class":252,"line":369},[250,826,274],{"emptyLinePlaceholder":273},[250,828,829,832,834,837,839],{"class":252,"line":374},[250,830,831],{"class":260},"index ",[250,833,283],{"class":256},[250,835,836],{"class":260}," layer.fields().indexOf(",[250,838,649],{"class":289},[250,840,366],{"class":260},[250,842,843,845,848,850,852,854],{"class":252,"line":401},[250,844,321],{"class":256},[250,846,847],{"class":260}," index ",[250,849,453],{"class":256},[250,851,456],{"class":256},[250,853,459],{"class":296},[250,855,856],{"class":260},":\n",[250,858,859,861,864,866,869],{"class":252,"line":424},[250,860,339],{"class":256},[250,862,863],{"class":296}," KeyError",[250,865,345],{"class":260},[250,867,868],{"class":289},"\"field not found\"",[250,870,366],{"class":260},[250,872,873],{"class":252,"line":464},[250,874,274],{"emptyLinePlaceholder":273},[250,876,877,879,882,885],{"class":252,"line":511},[250,878,321],{"class":256},[250,880,881],{"class":260}," provider.renameAttributes({index: ",[250,883,884],{"class":289},"\"value_assessed\"",[250,886,887],{"class":260},"}):\n",[250,889,890],{"class":252,"line":516},[250,891,565],{"class":260},[250,893,894,896],{"class":252,"line":524},[250,895,527],{"class":296},[250,897,898],{"class":260},"(layer.fields().names())\n",[14,900,901,738,903,906,907,910],{},[218,902,583],{},[247,904,905],{},"renameAttributes()"," takes a dictionary of index to new name, so several renames go in one call. It returns a bool — ",[247,908,909],{},"False"," when a name collides with an existing field or the provider refuses — and checking it is the only signal. Bear in mind that renaming breaks every expression, style rule and join that referenced the old name; those are stored in the project rather than the data source, so they do not follow the change.",[14,912,913],{},"When you only want a friendlier label in the interface, an alias is the non-destructive alternative and nothing downstream breaks:",[240,915,917],{"className":242,"code":916,"language":244,"meta":245,"style":245},"layer.setFieldAlias(index, \"Assessed value (£)\")\n",[247,918,919],{"__ignoreMap":245},[250,920,921,924,927],{"class":252,"line":253},[250,922,923],{"class":260},"layer.setFieldAlias(index, ",[250,925,926],{"class":289},"\"Assessed value (£)\"",[250,928,366],{"class":260},[14,930,931,933,934,937],{},[218,932,583],{}," The alias changes only the display label. Expressions, joins and styles continue to reference the underlying name, which is exactly what makes it safe. Aliases live in the QGIS project rather than the data source, so they travel with the ",[247,935,936],{},".qgz"," and not with the file.",[207,939,941],{"id":940},"the-non-destructive-alternative","The non-destructive alternative",[14,943,944],{},"If the source data is not yours to modify — or you want the operation to be re-runnable — write a trimmed copy instead of editing in place.",[14,946,947],{},[34,948,951,954,957,959,966,970,975,981,987,991,995,999,1002,1005,1010,1016,1019,1022,1026,1030,1033,1035,1038,1041,1045,1047,1051],{"viewBox":949,"role":37,"ariaLabel":950,"xmlns":39},"0 0 760 236","Two approaches contrasted: deleting fields in place mutates the source irreversibly, while the delete-column algorithm writes a trimmed copy leaving the original intact",[41,952,953],{},"In-place deletion versus a trimmed copy",[45,955,956],{},"On the left, deleteAttributes acts directly on the source file, which afterwards no longer contains the removed columns and cannot be recovered. On the right, native:deletecolumn reads the source and writes a separate output file containing only the kept columns, leaving the original file unchanged.",[49,958],{"x":51,"y":51,"width":52,"height":192,"fill":54},[56,960,961],{},[59,962,964],{"id":963,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"delCopyArrow",[68,965],{"d":70,"fill":71},[73,967,969],{"x":75,"y":968,"style":77,"fill":78,"textAnchor":79},"26","One of these you can undo by deleting a file",[49,971],{"x":137,"y":972,"width":973,"height":974,"rx":141,"fill":96,"stroke":108,"style":142},"46","356","176",[73,976,980],{"x":977,"y":978,"style":979,"fill":108,"textAnchor":79},"194","70","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","deleteAttributes() — in place",[49,982],{"x":983,"y":984,"width":94,"height":985,"rx":986,"fill":96,"stroke":97,"style":110},"56","92","80","6",[73,988,990],{"x":94,"y":989,"style":103,"fill":71,"textAnchor":79},"114","parcels.gpkg",[73,992,994],{"x":94,"y":993,"style":103,"fill":71,"textAnchor":79},"134","7 columns",[49,996],{"x":997,"y":984,"width":94,"height":985,"rx":986,"fill":108,"fillOpacity":998,"stroke":108,"style":110},"228",0.14,[73,1000,990],{"x":1001,"y":989,"style":103,"fill":71,"textAnchor":79},"284",[73,1003,1004],{"x":1001,"y":993,"style":103,"fill":71,"textAnchor":79},"4 columns",[73,1006,1009],{"x":1001,"y":1007,"style":1008,"fill":108,"textAnchor":79},"154","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","same file",[252,1011],{"x1":1012,"y1":1013,"x2":1014,"y2":1013,"stroke":108,"style":1015},"168","132","224","stroke-width:2.5;marker-end:url(#delCopyArrow)",[73,1017,1018],{"x":977,"y":183,"style":103,"fill":108,"textAnchor":79},"the original no longer exists",[49,1020],{"x":1021,"y":972,"width":973,"height":974,"rx":141,"fill":96,"stroke":180,"style":142},"388",[73,1023,1025],{"x":1024,"y":978,"style":979,"fill":180,"textAnchor":79},"566","native:deletecolumn — a copy",[49,1027],{"x":1028,"y":984,"width":94,"height":985,"rx":986,"fill":180,"fillOpacity":1029,"stroke":180,"style":110},"428",0.12,[73,1031,990],{"x":1032,"y":989,"style":103,"fill":71,"textAnchor":79},"484",[73,1034,994],{"x":1032,"y":993,"style":103,"fill":71,"textAnchor":79},[73,1036,1037],{"x":1032,"y":1007,"style":1008,"fill":180,"textAnchor":79},"untouched",[49,1039],{"x":1040,"y":984,"width":94,"height":985,"rx":986,"fill":96,"stroke":97,"style":110},"600",[73,1042,1044],{"x":1043,"y":989,"style":103,"fill":71,"textAnchor":79},"656","parcels_trim.gpkg",[73,1046,1004],{"x":1043,"y":993,"style":103,"fill":71,"textAnchor":79},[252,1048],{"x1":1049,"y1":1013,"x2":1050,"y2":1013,"stroke":180,"style":1015},"540","596",[73,1052,1053],{"x":1024,"y":183,"style":103,"fill":180,"textAnchor":79},"re-runnable, and reversible",[240,1055,1057],{"className":242,"code":1056,"language":244,"meta":245,"style":245},"import processing\n\nprocessing.run(\"native:deletecolumn\", {\n    \"INPUT\": \"\u002Fdata\u002Fparcels.gpkg|layername=parcels\",\n    \"COLUMN\": [\"tmp_a\", \"tmp_b\", \"scratch\"],\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fparcels_trim.gpkg\",\n})\n",[247,1058,1059,1066,1070,1081,1094,1115,1127],{"__ignoreMap":245},[250,1060,1061,1063],{"class":252,"line":253},[250,1062,264],{"class":256},[250,1064,1065],{"class":260}," processing\n",[250,1067,1068],{"class":252,"line":270},[250,1069,274],{"emptyLinePlaceholder":273},[250,1071,1072,1075,1078],{"class":252,"line":277},[250,1073,1074],{"class":260},"processing.run(",[250,1076,1077],{"class":289},"\"native:deletecolumn\"",[250,1079,1080],{"class":260},", {\n",[250,1082,1083,1086,1089,1092],{"class":252,"line":302},[250,1084,1085],{"class":289},"    \"INPUT\"",[250,1087,1088],{"class":260},": ",[250,1090,1091],{"class":289},"\"\u002Fdata\u002Fparcels.gpkg|layername=parcels\"",[250,1093,714],{"class":260},[250,1095,1096,1099,1102,1104,1106,1108,1110,1112],{"class":252,"line":313},[250,1097,1098],{"class":289},"    \"COLUMN\"",[250,1100,1101],{"class":260},": [",[250,1103,385],{"class":289},[250,1105,388],{"class":260},[250,1107,391],{"class":289},[250,1109,388],{"class":260},[250,1111,396],{"class":289},[250,1113,1114],{"class":260},"],\n",[250,1116,1117,1120,1122,1125],{"class":252,"line":318},[250,1118,1119],{"class":289},"    \"OUTPUT\"",[250,1121,1088],{"class":260},[250,1123,1124],{"class":289},"\"\u002Fdata\u002Foutput\u002Fparcels_trim.gpkg\"",[250,1126,714],{"class":260},[250,1128,1129],{"class":252,"line":336},[250,1130,1131],{"class":260},"})\n",[14,1133,1134,738,1136,1139,1140,1143,1144,1148],{},[218,1135,583],{},[247,1137,1138],{},"COLUMN"," takes a list of field ",[18,1141,1142],{},"names",", so there is no index arithmetic and no ordering hazard — the algorithm resolves them internally. A name that does not exist is ignored rather than raising, which makes the call safe against schema drift. Because it writes a new layer, the operation is re-runnable and the original stays available. This is the form to prefer inside a ",[26,1145,1147],{"href":1146},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002F","chained Processing pipeline",", where a destructive in-place edit would make the chain impossible to replay.",[207,1150,1152],{"id":1151},"check-what-the-field-is-used-by-first","Check what the field is used by first",[14,1154,1155],{},"Deleting a column that a style rule, a label expression or a join depends on leaves a project that opens with broken symbology and no obvious cause. A short audit before the delete finds those references.",[14,1157,1158],{},[34,1159,1162,1165,1168,1171,1178,1181,1188,1192,1195,1199,1205,1209,1212,1216,1220,1223,1227,1230,1232,1235,1238,1243,1247,1251],{"viewBox":1160,"role":37,"ariaLabel":1161,"xmlns":39},"0 0 760 254","A single field referenced by four different parts of a project: a renderer rule, a labelling expression, a virtual join and a data-defined property, all of which break if the field is removed",[41,1163,1164],{},"What else depends on this field",[45,1166,1167],{},"A field named zoning sits at the centre. Four dependants point at it: a rule-based renderer filter, a labelling rule expression, a virtual join key, and a data-defined fill colour property. Each is annotated with what happens if the field is deleted, ranging from features rendering with the fallback symbol to labels disappearing entirely.",[49,1169],{"x":51,"y":51,"width":52,"height":1170,"fill":54},"254",[56,1172,1173],{},[59,1174,1176],{"id":1175,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"delRefArrow",[68,1177],{"d":70,"fill":108},[73,1179,1180],{"x":75,"y":968,"style":77,"fill":78,"textAnchor":79},"These references live in the project, not the data source",[49,1182],{"x":1183,"y":1184,"width":1185,"height":983,"rx":141,"fill":1186,"stroke":1187,"style":142},"300","106","160","#26322d","#0f766e",[73,1189,644],{"x":75,"y":1013,"style":1190,"fill":1191,"textAnchor":79},"text-anchor:middle;font-size:12.5px;font-weight:bold;font-family:sans-serif","#d9f99d",[73,1193,1194],{"x":75,"y":101,"style":103,"fill":1191,"textAnchor":79},"about to be deleted",[49,1196],{"x":137,"y":972,"width":1197,"height":1198,"rx":63,"fill":96,"stroke":108,"style":110},"220","52",[73,1200,1204],{"x":1201,"y":1202,"style":1203,"fill":108,"textAnchor":79},"126","68","text-anchor:middle;font-size:11.5px;font-weight:bold;font-family:sans-serif","renderer rule filter",[73,1206,1208],{"x":1201,"y":1207,"style":103,"fill":71,"textAnchor":79},"86","falls back to the default symbol",[49,1210],{"x":137,"y":1211,"width":1197,"height":1198,"rx":63,"fill":96,"stroke":108,"style":110},"170",[73,1213,1215],{"x":1201,"y":1214,"style":1203,"fill":108,"textAnchor":79},"192","labelling expression",[73,1217,1219],{"x":1201,"y":1218,"style":103,"fill":71,"textAnchor":79},"210","labels stop drawing",[49,1221],{"x":1222,"y":972,"width":1197,"height":1198,"rx":63,"fill":96,"stroke":108,"style":110},"524",[73,1224,1226],{"x":1225,"y":1202,"style":1203,"fill":108,"textAnchor":79},"634","virtual join key",[73,1228,1229],{"x":1225,"y":1207,"style":103,"fill":71,"textAnchor":79},"joined columns go NULL",[49,1231],{"x":1222,"y":1211,"width":1197,"height":1198,"rx":63,"fill":96,"stroke":108,"style":110},[73,1233,1234],{"x":1225,"y":1214,"style":1203,"fill":108,"textAnchor":79},"data-defined property",[73,1236,1237],{"x":1225,"y":1218,"style":103,"fill":71,"textAnchor":79},"symbols revert to fixed values",[252,1239],{"x1":1183,"y1":1201,"x2":1240,"y2":1241,"stroke":108,"style":1242},"240","82","stroke-width:2;stroke-dasharray:5 4;marker-end:url(#delRefArrow)",[252,1244],{"x1":1183,"y1":1245,"x2":1240,"y2":1246,"stroke":108,"style":1242},"146","186",[252,1248],{"x1":1249,"y1":1201,"x2":1250,"y2":1241,"stroke":108,"style":1242},"460","520",[252,1252],{"x1":1249,"y1":1245,"x2":1250,"y2":1246,"stroke":108,"style":1242},[240,1254,1256],{"className":242,"code":1255,"language":244,"meta":245,"style":245},"from qgis.core import QgsProject\n\nFIELD = \"zoning\"\nlayer = QgsProject.instance().mapLayersByName(\"parcels\")[0]\n\nwarnings = []\n\nrenderer = layer.renderer()\nif FIELD in (renderer.dump() or \"\"):\n    warnings.append(\"referenced by the renderer\")\n\nlabeling = layer.labeling()\nif labeling is not None and FIELD in str(labeling.settings().fieldName):\n    warnings.append(\"referenced by a labelling rule\")\n\nfor join in layer.vectorJoins():\n    if FIELD in (join.targetFieldName(), join.joinFieldName()):\n        warnings.append(f\"used as a join key with {join.joinLayerId()}\")\n\nprint(f\"{FIELD}: \" + (\"; \".join(warnings) if warnings else \"no references found\"))\n",[247,1257,1258,1269,1273,1283,1299,1303,1313,1317,1327,1348,1358,1362,1372,1400,1409,1413,1425,1437,1458,1462],{"__ignoreMap":245},[250,1259,1260,1262,1264,1266],{"class":252,"line":253},[250,1261,257],{"class":256},[250,1263,261],{"class":260},[250,1265,264],{"class":256},[250,1267,1268],{"class":260}," QgsProject\n",[250,1270,1271],{"class":252,"line":270},[250,1272,274],{"emptyLinePlaceholder":273},[250,1274,1275,1278,1280],{"class":252,"line":277},[250,1276,1277],{"class":296},"FIELD",[250,1279,628],{"class":256},[250,1281,1282],{"class":289}," \"zoning\"\n",[250,1284,1285,1287,1289,1291,1293,1295,1297],{"class":252,"line":302},[250,1286,280],{"class":260},[250,1288,283],{"class":256},[250,1290,286],{"class":260},[250,1292,290],{"class":289},[250,1294,293],{"class":260},[250,1296,51],{"class":296},[250,1298,299],{"class":260},[250,1300,1301],{"class":252,"line":313},[250,1302,274],{"emptyLinePlaceholder":273},[250,1304,1305,1308,1310],{"class":252,"line":318},[250,1306,1307],{"class":260},"warnings ",[250,1309,283],{"class":256},[250,1311,1312],{"class":260}," []\n",[250,1314,1315],{"class":252,"line":336},[250,1316,274],{"emptyLinePlaceholder":273},[250,1318,1319,1322,1324],{"class":252,"line":369},[250,1320,1321],{"class":260},"renderer ",[250,1323,283],{"class":256},[250,1325,1326],{"class":260}," layer.renderer()\n",[250,1328,1329,1331,1334,1336,1339,1342,1345],{"class":252,"line":374},[250,1330,321],{"class":256},[250,1332,1333],{"class":296}," FIELD",[250,1335,696],{"class":256},[250,1337,1338],{"class":260}," (renderer.dump() ",[250,1340,1341],{"class":256},"or",[250,1343,1344],{"class":289}," \"\"",[250,1346,1347],{"class":260},"):\n",[250,1349,1350,1353,1356],{"class":252,"line":401},[250,1351,1352],{"class":260},"    warnings.append(",[250,1354,1355],{"class":289},"\"referenced by the renderer\"",[250,1357,366],{"class":260},[250,1359,1360],{"class":252,"line":424},[250,1361,274],{"emptyLinePlaceholder":273},[250,1363,1364,1367,1369],{"class":252,"line":464},[250,1365,1366],{"class":260},"labeling ",[250,1368,283],{"class":256},[250,1370,1371],{"class":260}," layer.labeling()\n",[250,1373,1374,1376,1379,1382,1384,1387,1390,1392,1394,1397],{"class":252,"line":511},[250,1375,321],{"class":256},[250,1377,1378],{"class":260}," labeling ",[250,1380,1381],{"class":256},"is",[250,1383,324],{"class":256},[250,1385,1386],{"class":296}," None",[250,1388,1389],{"class":256}," and",[250,1391,1333],{"class":296},[250,1393,696],{"class":256},[250,1395,1396],{"class":296}," str",[250,1398,1399],{"class":260},"(labeling.settings().fieldName):\n",[250,1401,1402,1404,1407],{"class":252,"line":516},[250,1403,1352],{"class":260},[250,1405,1406],{"class":289},"\"referenced by a labelling rule\"",[250,1408,366],{"class":260},[250,1410,1411],{"class":252,"line":524},[250,1412,274],{"emptyLinePlaceholder":273},[250,1414,1415,1417,1420,1422],{"class":252,"line":543},[250,1416,412],{"class":256},[250,1418,1419],{"class":260}," join ",[250,1421,418],{"class":256},[250,1423,1424],{"class":260}," layer.vectorJoins():\n",[250,1426,1427,1430,1432,1434],{"class":252,"line":548},[250,1428,1429],{"class":256},"    if",[250,1431,1333],{"class":296},[250,1433,696],{"class":256},[250,1435,1436],{"class":260}," (join.targetFieldName(), join.joinFieldName()):\n",[250,1438,1439,1442,1444,1447,1449,1452,1454,1456],{"class":252,"line":556},[250,1440,1441],{"class":260},"        warnings.append(",[250,1443,348],{"class":256},[250,1445,1446],{"class":289},"\"used as a join key with ",[250,1448,354],{"class":296},[250,1450,1451],{"class":260},"join.joinLayerId()",[250,1453,360],{"class":296},[250,1455,351],{"class":289},[250,1457,366],{"class":260},[250,1459,1460],{"class":252,"line":562},[250,1461,274],{"emptyLinePlaceholder":273},[250,1463,1464,1467,1469,1471,1473,1476,1479,1482,1485,1488,1491,1493,1496,1499,1502],{"class":252,"line":568},[250,1465,1466],{"class":296},"print",[250,1468,345],{"class":260},[250,1470,348],{"class":256},[250,1472,351],{"class":289},[250,1474,1475],{"class":296},"{FIELD}",[250,1477,1478],{"class":289},": \"",[250,1480,1481],{"class":256}," +",[250,1483,1484],{"class":260}," (",[250,1486,1487],{"class":289},"\"; \"",[250,1489,1490],{"class":260},".join(warnings) ",[250,1492,321],{"class":256},[250,1494,1495],{"class":260}," warnings ",[250,1497,1498],{"class":256},"else",[250,1500,1501],{"class":289}," \"no references found\"",[250,1503,1504],{"class":260},"))\n",[14,1506,1507,738,1509,1512,1513,1516],{},[218,1508,583],{},[247,1510,1511],{},"renderer.dump()"," returns a text description of the renderer including any expressions it uses, which makes a substring test a crude but effective first pass. ",[247,1514,1515],{},"layer.vectorJoins()"," lists the virtual joins configured on the layer, and a field used as a join key is the most damaging one to remove. None of these checks is exhaustive — a field can also appear in a layout item or another layer's expression — but together they catch the great majority, and a \"no references found\" result on a field you were unsure about is genuinely reassuring.",[207,1518,1520],{"id":1519},"qgis-version-compatibility","QGIS version compatibility",[14,1522,1523,1524,1526],{},"The examples target ",[218,1525,220],{}," (Python 3.12).",[1528,1529,1530,1546],"table",{},[1531,1532,1533],"thead",{},[1534,1535,1536,1540,1543],"tr",{},[1537,1538,1539],"th",{},"QGIS version",[1537,1541,1542],{},"Python",[1537,1544,1545],{},"Notes",[1547,1548,1549,1565,1576],"tbody",{},[1534,1550,1551,1555,1558],{},[1552,1553,1554],"td",{},"3.28 LTR",[1552,1556,1557],{},"3.9",[1552,1559,1560,1561,1564],{},"Identical API. ",[247,1562,1563],{},"RenameAttributes"," capability available since 3.0.",[1534,1566,1567,1570,1573],{},[1552,1568,1569],{},"3.34 LTR",[1552,1571,1572],{},"3.12",[1552,1574,1575],{},"Baseline for this page.",[1534,1577,1578,1581,1583],{},[1552,1579,1580],{},"3.40 \u002F 3.44",[1552,1582,1572],{},[1552,1584,1585,1588],{},[247,1586,1587],{},"native:retainfields"," provides the whitelist operation directly, without index arithmetic.",[14,1590,1591,388,1593,1595,1596,1599,1600,1602],{},[247,1592,599],{},[247,1594,905],{}," and ",[247,1597,1598],{},"native:deletecolumn"," are unchanged across 3.x. On 3.40 and newer, ",[247,1601,1587],{}," is the cleaner expression of the whitelist pattern.",[207,1604,1606],{"id":1605},"troubleshooting","Troubleshooting",[212,1608,1609,1615,1626,1632,1638,1644],{},[215,1610,1611,1614],{},[218,1612,1613],{},"The wrong columns disappeared."," Deletion ran in ascending index order. Always sort descending, and resolve every index before deleting any.",[215,1616,1617,1622,1623,1625],{},[218,1618,1619,1621],{},[247,1620,599],{}," had no effect."," One or more indexes were ",[247,1624,595],{},", or the provider lacks the capability. Check both explicitly.",[215,1627,1628,1631],{},[218,1629,1630],{},"A rename returned False."," The new name collides with an existing field, or the provider does not support renaming. Shapefiles do not.",[215,1633,1634,1637],{},[218,1635,1636],{},"Expressions broke after a rename."," Styles, labels and joins reference field names and are stored in the project, so they do not follow. Use an alias instead when only the display label matters.",[215,1639,1640,1643],{},[218,1641,1642],{},"Fields reappear after reopening the project."," The deletion was staged in an edit buffer that was never committed. Either commit it or use the provider route.",[215,1645,1646,738,1649,1651],{},[218,1647,1648],{},"The layer still lists the old fields.",[247,1650,603],{}," was not called after the deletion.",[207,1653,1655],{"id":1654},"conclusion","Conclusion",[14,1657,1658,1659,1661],{},"Delete by name, resolve to indexes in one pass, and remove them in descending order — that single discipline prevents the whole class of \"the wrong column vanished\" failures. Prefer a whitelist to a blacklist so upstream schema changes are handled automatically, use aliases rather than renames when only the label matters, and reach for ",[247,1660,1598],{}," whenever the operation should be re-runnable.",[207,1663,1665],{"id":1664},"frequently-asked-questions","Frequently Asked Questions",[14,1667,1668,1671],{},[218,1669,1670],{},"Why did deleting fields remove the wrong ones?","\nIndexes are positional and shift as soon as one field is removed. Resolve every index against the original schema first, then delete them in descending order so each removal only affects indexes already handled.",[14,1673,1674,1677,1678,1680],{},[218,1675,1676],{},"Can I delete a field by name instead of index?","\nNot through the provider API, which takes indexes. ",[247,1679,1598],{}," does take names and writes a new layer, which is why it is the safer option in a pipeline.",[14,1682,1683,1686,1687,1690],{},[218,1684,1685],{},"Why can I not rename a field in my shapefile?","\nThe shapefile driver does not support renaming attributes. Check ",[247,1688,1689],{},"capabilities() & QgsVectorDataProvider.RenameAttributes"," first, or convert the data to GeoPackage.",[14,1692,1693,1696],{},[218,1694,1695],{},"What is the difference between renaming a field and setting an alias?","\nA rename changes the underlying column name and breaks every expression, style and join referring to the old one. An alias changes only the display label in the interface and is stored in the project, so nothing downstream is affected.",[207,1698,1700],{"id":1699},"related","Related",[212,1702,1703,1708,1714,1720],{},[215,1704,1705,1707],{},[26,1706,29],{"href":28}," — the guide this recipe belongs to",[215,1709,1710],{},[26,1711,1713],{"href":1712},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fadd-field-to-layer-pyqgis\u002F","Add a Field to a Layer in PyQGIS",[215,1715,1716],{},[26,1717,1719],{"href":1718},"\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fupdate-attribute-values-pyqgis\u002F","Update Attribute Values in Bulk with PyQGIS",[215,1721,1722],{},[26,1723,1724],{"href":1146},"Chaining Processing Algorithms in PyQGIS",[1726,1727,1728],"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 pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}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);}",{"title":245,"searchDepth":270,"depth":270,"links":1730},[1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741],{"id":209,"depth":270,"text":210},{"id":234,"depth":270,"text":235},{"id":607,"depth":270,"text":608},{"id":745,"depth":270,"text":746},{"id":940,"depth":270,"text":941},{"id":1151,"depth":270,"text":1152},{"id":1519,"depth":270,"text":1520},{"id":1605,"depth":270,"text":1606},{"id":1654,"depth":270,"text":1655},{"id":1664,"depth":270,"text":1665},{"id":1699,"depth":270,"text":1700},"Remove and rename attribute fields in PyQGIS. Delete by descending index, check provider capabilities, rename safely, and use native:deletecolumn for a clean copy.","md",{"slug":1745,"type":1746,"breadcrumb":1747,"datePublished":1748,"dateModified":1748},"delete-fields-pyqgis","article","Delete & Rename Fields","2026-08-01","\u002Fspatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fdelete-fields-pyqgis",{"title":5,"description":1742},"spatial-data-processing-automation\u002Fattribute-tables-and-field-management\u002Fdelete-fields-pyqgis\u002Findex","liYby9C9XwCFgvQFLtF3pHcIUT7gCZtpJ1IeMaJVHXg",1785585990475]