11

I would like to update one attribute of a feature. However, I don't know to update it using the feature object. I have to use data provider to update it.

layers = QgsMapLayerRegistry.instance().mapLayersByName('my_line') 
layer = layers[0]
dp = layer.dataProvider()
it = dp.getFeatures()

for i in range(0, dp.featureCount()):
  feat = it.next()
  attrs = { 2 : 30 }
  layer.dataProvider().changeAttributeValues({ feat.id() : attrs })

Can I change the value of an attribute using QgsFeature object?

Moreover, is it possible to loop using an iterator object?

  • how can I change values without using the index? I would like to change the values by naming their fieldname. That would be much more comfortable. Thank you very much! Greetings Robert – Robert B K Jan 5 '18 at 21:20
  • Simply use my_index = layer.fieldNameIndex("my_field_name") to get the index. – Germán Carrillo Jan 5 '18 at 22:18
  • in this case i cant add in the field the string how i can do? – Hamed Makian Mar 13 '18 at 13:24
  • If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review – Dan C Mar 13 '18 at 13:32
  • Hamed, Welcome to GIS Stack Exchange! Since this question has already been answered, please ask your question as a new, separate question here gis.stackexchange.com/questions/ask. – cm1 Mar 13 '18 at 13:49
16

Answering your two questions:

  1. You can change your feature values from the layer object, no need to access the dataProvider().

  2. Yes, you can use the iterator in a for loop.

Check the code below:

layers = QgsMapLayerRegistry.instance().mapLayersByName('my_line') 
layer = layers[0]
it = layer.getFeatures()

layer.startEditing()
for feat in it:
  layer.changeAttributeValue(feat.id(), 2, 30)

layer.commitChanges()

This updates the third (index 2) field value to 30 for all layer features.


Note: As you pointed out, for some reason the QgsFeature object cannot update feature values, although the API says it can.

5

Yes, but you have to know the index of the field:

QgsFeature::setAttribute(int field,const QVariant & attr )  

You can get the fields using QgsFeature::fields and then iterate through them until you find the one you want or QgsFeature::attribute(const QString & name ) to find the field index by name.

The reason for QVariant is that the setAttribute can take Integer, Float, Date and Text types. QgsFeature.attribute(name) returns a variant also of type int if the attribute is found and something else if it can't be found.. be aware of this in your code. A try..except block would be warranted, try to convert to int and except if type is not int.

It is possible that your feature doesn't support this method. Another method that I have employed is QgsVectorLayer::changeAttributeValue:

self.canvas.currentLayer().changeAttributeValue(UpdateFeatureID,FieldToUpdate,self.CurrentWidget.text(),True)

This tells the layer to update a specific feature and specific attribute. In the example case the value comes from a widget.

  • I tried feat.setAttribute(1, QVariant(20)) but the system said TypeError: PyQt4.QtCore.QVariant represents a mapped type and cannot be instantiated – wannik Jun 16 '14 at 3:09
  • feat.setAttribute(1, 20) is how I've done it before. That is put the value '20' into attribute 1. – Michael Stimson Jun 16 '14 at 3:11
  • I tried feat.setAttribute(1, 20) but the values don't change. However, I can print(feat.attributes()[1]) – wannik Jun 16 '14 at 3:28
  • See edits, perhaps you have to call the QgsVectorLayer.changeAttributeValue which should use the driver to make the changes. – Michael Stimson Jun 16 '14 at 3:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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