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'
2

1 Answer 1

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()
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.