14

I have this piece of code which I would like to use for inserting values into a column. It does not throw an error, the changes are not written to the source (shapefile).

from qgis.utils import iface
from PyQt4.QtCore import *

layers = iface.legendInterface().layers()

for layer in layers:
    name = layer.name()
    if name.endswith('x'):
        provider = layer.dataProvider()   
        features = provider.getFeatures()
        for feature in features:
            feature.setAttribute('attr', 'a')

I understood there are two ways of editing data sources: directly with dataProvider or with edit buffer. If I got it right, it shouldn't be necessary to call commit action when using dataProvider.

I'm using QGIS 2.2 Valmiera.

1 Answer 1

12

You are right, that you don't need to call commit if you work on the dataProvider directly. However, this will also commit every update immediately, leading to more I/O overhead (often decreased performance) and poor transaction handling. This is to say, the method works, but use it carefully. I have added another method below which is better suited in most cases.

The problem in the code is, that you are only setting the attribute on the feature in memory and don't tell the provider, that this feature changed. Instead, try the following code. It buffers all updates in the updateMap and then executes it in one go at the end, therefore allowing batch updates (useful e.g. on slow networks). Another possibility would be to issue updateAttributeValue directly in the loop.

from qgis.utils import iface
from PyQt4.QtCore import *

layers = iface.legendInterface().layers()

for layer in layers:
    name = layer.name()
    if name.endswith('x'):
        provider = layer.dataProvider()
        updateMap = {}
        fieldIdx = provider.fields().indexFromName( 'attr' )
        features = provider.getFeatures()
        for feature in features:
            updateMap[feature.id()] = { fieldIdx: 'a' }

        provider.changeAttributeValues( updateMap )

The generally recommended way:

with edit(layer):
    for feature in layer.getFeatures():
        feature['fieldName'] = newValue
        layer.updateFeature(feature)

http://qgis.org/api/2.2/classQgsVectorDataProvider.html#a99a5d01c33c1cadb7ae9209b68cd8743

2
  • what is the the value of 'p' here? So the above , is it going to change the attribute name of the table? Like for eg. old_field_name is going to be replaced with new_field_name? Commented Nov 12, 2019 at 9:58
  • 1
    It was a typo, corrected. It's going to change attribute values (It calls provider.changeAttributeValues), not field names. Commented Nov 13, 2019 at 7:21

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.