4

I want to delete specific columns in the attribute table of my layer: except for the "LAYER" Column.

This is my code:

clip = processing.runAndLoadResults("native:clip",
                            { 'INPUT': union['OUTPUT'],
                              'OVERLAY': dissolved['OUTPUT'],
                              'OUTPUT': 'TEMPORARY_OUTPUT',
                            })

field names to be deleted

fields = ['fid_2', 'fid', 'Phasenr_2', 'fid_3', 'Phasename', 'layer', 'path']

get field ids from field names

field_ids = [clip.field().indexFromName(f) for f in fields]

delete the attribute using their index

clip.dataProvider().deleteAttributes(field_ids)

clip.updateFields()

Error:

Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS32~1.0\apps\Python39\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 69, in <module>
  File "<string>", line 69, in <listcomp>
AttributeError: 'dict' object has no attribute 'field'
Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
charliey
  • 163
  • 7

1 Answers1

6
  • clip.field must be clip.fields

  • processing.runAndLoadResult method returns a dictionary like {"OUTPUT": 'result/file/temporary/path'}. So clip is a dictionary. fields is a QgsVectorLayer method. This is why you get the error.

  • In your case, using processing.run is more appropriate. It again returns a dictionary, but, containing a QgsVectorLayer. In this case, you have to add the layer manually using QgsProject.instance().addMapLayer().

So, the script you need:

clip = processing.run("native:clip",
                      { 'INPUT': union['OUTPUT'],
                        'OVERLAY': dissolved['OUTPUT'],
                        'OUTPUT': 'TEMPORARY_OUTPUT',
                      })["OUTPUT"] ###

QgsProject.instance().addMapLayer(clip)

field names to be deleted

fields = ['fid_2', 'fid', 'Phasenr_2', 'fid_3', 'Phasename', 'layer', 'path']

get field ids from field names

field_ids = [clip.fields().indexFromName(f) for f in fields]

delete the attribute using their index

clip.dataProvider().deleteAttributes(field_ids)

clip.updateFields()

You can also construct the field names to be deleted using the field names not to be deleted as follows:

dont_delete = ["LAYER", "otherfield"]
all_fields = clip.fields().names()

field_ids = [clip.fields().indexFromName(f) for f in all_fields if f not in dont_delete]


Old answer:

You didn't define inlayDir_provider. You also have to get the field index to pass it to deleteAttributes method. It takes field indices as argument, not field names.

Deleting single attribute:

inlayDir = iface.activeLayer()

get field index

field_index = inlayDir.fields().indexFromName('fid_2')

delete the attribute using its index

inlayDir.dataProvider().deleteAttributes([field_index])

inlayDir.updateFields()

Deleting specific attributes:

inlayDir = iface.activeLayer()

field names to be deleted

fields = ["field1", "field2", "field3"]

get field ids from field names

field_ids = [inlayDir.fields().indexFromName(f) for f in fields]

delete the attribute using their index

inlayDir.dataProvider().deleteAttributes(field_ids)

inlayDir.updateFields()

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389