i want to change attributes values in a memory layer.
I already asked a similar question but i'm re-stuck on the problem and don't find any solution to this basic need.
Here is what i'm doing so far :
from PyQt4.QtCore import *
from PyQt4.QtGui import *
vl_r=QgsVectorLayer('Polygon?crs=epsg:2154','population','memory')
pro_r = vl_r.dataProvider()
pro_r.addAttributes([QgsField("name", QVariant.String)])
pro_r.addAttributes([QgsField("pop", QVariant.Int)])
vl_r.updateFields()
QgsMapLayerRegistry.instance().addMapLayer(vl_r)
fet = QgsFeature()
dummy=pro_r.addFeatures([fet])
print(pro_r.capabilitiesString())
attrib={0:'hell',1:666}
dummy=vl_r.dataProvider().changeAttributeValues({fet.id():attrib})
print('Change values : ' + str(dummy))
The value returned by 'dummy' is always True but i never see any change in the attributes table.
When i use a 'normal' layer (stored on disk) the change is made and is immediately visible without any additional command.
What could i be missing ? My code is so simple that i can't see what i forgot ...
Could anybody give me a working sample of attributes change in a memory Layer ?
2 Answers 2
There are basically two problems with the script you posted.
- The feature's attributes are not initialized. So the feature itself does not have any attributes (although the provider has). With other providers this would be less of a problem since when saved and retrieved, new features get created, but the memory provider saves the feature as they are.
- The feature which you are updating is the one you created and does not yet have an id. The id is generated in the provider when saved. So before changing anything you have to retrieve the feature again with the generated id.
Below the required changes to your script:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
vl_r=QgsVectorLayer('Polygon?crs=epsg:2154','population','memory')
pro_r = vl_r.dataProvider()
pro_r.addAttributes([QgsField("name", QVariant.String)])
pro_r.addAttributes([QgsField("pop", QVariant.Int)])
vl_r.updateFields()
QgsMapLayerRegistry.instance().addMapLayer(vl_r)
fet = QgsFeature(vl_r.fields())
# Initialize the feature with 2 attributes. You can make this more generic by using layer information instead of a hardcoded number.
dummy=pro_r.addFeatures([fet])
print(pro_r.capabilitiesString())
attrib={0:'hell',1:666}
# Get the (one and only) feature to have an id to work with
fet = vl_r.getFeatures().next()
dummy=vl_r.dataProvider().changeAttributeValues({fet.id():attrib})
print('Change values : ' + str(dummy))
-
Thanks for time spent in answering Matthias ... ! All this remain a bit subtle for me but i will make some other experiments ...Snaileater– Snaileater2015年12月01日 17:17:46 +00:00Commented Dec 1, 2015 at 17:17
Try with:
attrib={0:'hell',1:str(666)}
For me the second attribute passes only with the str(), even if the QgsField is integer... I think there is a bug with changeAttributeValues() with multiple attributes.
Explore related questions
See similar questions with these tags.
vl_r.changeAttributeValues()
( i.e. withoutdataProvider()
)? You need to callvl_r.startEditing()
first.vl_r.changeAttributeValue()
i suppose ? i never find the right syntax ... i triedvl_r.changeAttributeValue(fet.id(),0,'hell')
after avl_r.startEditing
(and avl_r.commitChanges()
) but i don't see any change ...fet.setAttributes(['xxx',888])
works for setting the attributes but when it comes to changing attributes values i never find the right solution ... And why wouldn't the first syntax (using the provider) work ?vl_r.updateFeature(fet)
if you have a changed feature.