I try to write a Python script with PyQGIS to update automatically a field when a feature is added or when a geometry is changed. It's work well with the geometryChanged
listener but not with the featureAdded
listener : For a new feature the QgsFeatureId
is negative before a commit (-2 for example) and it seems that changeAttribute does not like that :
Layer point: Feature -2 for attribute update not found.
How can I update a field automatically before a commit?
Here is my code :
#### variables ####
layerName = "point"
fieldName = "test"
## create layer object
layer = (QgsMapLayerRegistry.instance().mapLayersByName(layerName))[0]
## function updateField
def updateField(QgsFeatureId):
field = layer.fieldNameIndex(fieldName)
layer.dataProvider().changeAttributeValues({QgsFeatureId:{field:"updateTest"}})
## listeners
layer.geometryChanged.connect(updateField)
layer.featureAdded.connect(updateField)
I work with QGIS 2.14.4
-
By the way, unless you definitely need to implement this by yourself in a script, you could use the AutoFields plugin, which handles automatic vector field updates for you.Germán Carrillo– Germán Carrillo2017年07月21日 12:04:15 +00:00Commented Jul 21, 2017 at 12:04
-
Thanks, I tested your plugin, it works well but the attributes are not updated until you commit your edit change.Maxime Bescu– Maxime Bescu2017年07月24日 13:43:46 +00:00Commented Jul 24, 2017 at 13:43
-
Right, they're not saved until you save. That something we could adjust for a next version. :)Germán Carrillo– Germán Carrillo2017年07月24日 14:09:37 +00:00Commented Jul 24, 2017 at 14:09
1 Answer 1
Have a look at this post about listening to featureAdded
in a safe way.
In your case, this should work:
layerName = "point1"
fieldName = "test"
addedFeatures = []
layer = (QgsMapLayerRegistry.instance().mapLayersByName(layerName))[0]
field = layer.fieldNameIndex(fieldName)
def storeFeaturesIds(featId):
addedFeatures.append(featId)
def updateAttributesAfterAdding():
while addedFeatures:
featureId = addedFeatures.pop()
layer.beginEditCommand('Updating test field')
layer.changeAttributeValue(featureId, field, "updateTest")
layer.endEditCommand()
layer.featureAdded.connect(storeFeaturesIds)
layer.editCommandEnded.connect(updateAttributesAfterAdding)