[GIS] Adding new features with attributes to an existing layer in PyQGIS

pyqgispythonqgis

I have a vector layer, populated with points, and I want to programmatically add to this layer.

The part related to the geometry works just out of the box, but I was having trouble with adding attribute values to the new features.
The problem is, when I add a new feature to the layer, I do not manage to specify fields. The feature would complain on exceptions.KeyError.

        featureList = []
        ## now add the computed points to the layer
        for p in [p for p in points.values() if p['computed']]:
            x, y = p['coordinates']
            feature = QgsFeature()
            layerPoint = transf.transform(QgsPoint(x, y))
            feature.setGeometry(QgsGeometry.fromPoint(layerPoint))
            feature['id'] = p['id']
            featureList.append(feature)

        layer.dataProvider().addFeatures(featureList)
        layer.commitChanges()

And before you ask, obviously I'm sure it's the feature['id'] which is giving trouble, not the p['id'].

So the short version of the question was "how do I specify fields of a feature before it was ever part of a layer?"

Best Answer

The first answer I found amounted to copying the fields from an existing feature from the same layer, and feed them to the new feature. It works fine for me, because the code needs at least 3 features to do anything useful, and because earlier in the code I was looping over the features in the layer:

for feature in layer.getFeatures():
    # this is a loop I needed anyway
    .
    .
    .
    pass
# copy the fields definition from an existing feature
fields = feature.fields()

I am very new to programming in QGIS so I had not yet even seen the page that underdark is linking to in her answer. And even if her answer does not hit the point, the link does help.

I don't need to copy the fields from an existing feature, I can grab them directly from the layer.

fields = layer.fields()
featureList = []
for p in [p for p in points.values() if p['computed']]:
    x, y = p['coordinates']
    feature = QgsFeature()
    # inform the feature of its fields
    feature.setFields(fields)
    layerPoint = transf.transform(QgsPoint(x, y))
    feature.setGeometry(QgsGeometry.fromPoint(layerPoint))
    feature['id'] = p['id']  # this now works
    featureList.append(feature)