3

I have a table with three attributes [field1, field2, field3].

I'm trying to insert a new feature to this table by defining field2 and field3 only.

lyr = QgsMapLayerRegistry.instance().mapLayer('layer')

new_feat = QgsFeature()

new_feat.setAttribute(1,"text1")
new_feat.setAttribute(2,"text2")

lyr.dataProvider().addFeatures([new_feat])
lyr.commitChanges()

It seems that I have a problem with the index in the setAttribute. What am I missing?

2
  • What is the error message? Commented Feb 27, 2018 at 10:54
  • error_message:new_feat.setAttribute(1,"text1") KeyError: '1'
    – var29
    Commented Feb 27, 2018 at 10:58

2 Answers 2

5

You must declare the feature's fields before being able to use them:

lyr = QgsMapLayerRegistry.instance().mapLayer('layer')
fields = lyr.pendingFields()   
new_feat = QgsFeature(fields)

new_feat.setAttribute(1,"text1")
new_feat.setAttribute(2,"text2")

lyr.dataProvider().addFeatures([new_feat])
lyr.commitChanges()
2
  • Thank you JGH, I didn't know that. But now I get a new error message: Traceback (most recent call last): File "...", line 34, in addrelation relation_lyr.dataprovider().addFeature([new_feat]) AttributeError: 'QgsVectorLayer' object has no attribute 'dataprovider'
    – var29
    Commented Feb 27, 2018 at 13:21
  • 2
    it is dataProvider. Also, using dataProvider is really discouraged as it by-passes undo actions (and other signals) in QGIS. It is recommended to use the edit buffer of the layer. See QgsVectorLayerEditBuffer and QgsVectorLayer.startEditing. Commented Feb 27, 2018 at 13:27
3

I will provide an additional answer since using the data provider is discouraged in QGIS (it will by-pass the undo stack and possibly some other features in QGIS, like transactions).

There is some nice Pythonic tools in QGIS API which allow to write synthetic code.

What you can do (from JGH answer) is:

layer = QgsMapLayerRegistry.instance().mapLayer('layer')
with edit(layer):
  fields = layer.pendingFields()   
  new_feat = QgsFeature(fields)

  new_feat[1] = "text1"
  new_feat[2] = "text2"

  layer.addFeature(new_feat)
2
  • It works well. Question: is it the same as writing: if was_editing is False:layer.startEditing() / if was_editing is False: layer.commitChanges() at the end and beginning of the code? (because it works too)
    – var29
    Commented Feb 28, 2018 at 7:20
  • yes, exactly, edit is actually a context manager in Python. Its definition in QGIS can be found here Commented Mar 1, 2018 at 16:37

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.