1

As a part of a PyQGIS script, I am trying to rearrange the order of the features in a temporary vector layer but keep the order of the attributes/values. The way I planned on doing this was to make a copy of the layer before rearranging, and then transfer back the original fields/values from the copy to the rearranged original. However, this means I need to duplicate the layer data source, not just create a new layer pointing to the same data source as that will get changed during the rearranging. How do I do that? Ideally, I only want to make a copy of the fields of interest, not the entire layer with geometry and everything else. Would it even be possible to just save the fields into list variables and then insert them back into the rearranged layer?

1 Answer 1

2

You can use a combination of QgsFeatureSource.materialize() with a QgsFeatureRequest that subsets the attributes with the .setSubsetOfAttributes method. The output is a new QgsVectorLayer with the abbreviated attribute table:

layer = iface.activeLayer()
field_names = ['field_1', 'field_3']
field_idxs = [layer.fields().indexFromName(field) for field in field_names]

request = QgsFeatureRequest().setSubsetOfAttributes(field_idxs)
subsetted_layer = layer.materialize(QgsFeatureRequest(request))

# add to project for debugging
subsetted_layer.setName('subsetted attributes')
QgsProject.instance().addMapLayer(subsetted_layer)
Before

enter image description here

After

enter image description here

3
  • Thank you, Matt. It works, but only if I keep QgsProject.instance().addMapLayer(subsetted_layer), otherwise I get the same result as if I hadn't backed up the fields. Unfortunately, this saves the layer to the project, and I would like it to be a temporary layer that gets discarded after the script is run. Is there a way to fix that?
    – Joel
    Commented Jan 16, 2023 at 17:23
  • You can omit the last two lines and just use the subsetted_layer variable, it is a QgsVectorLayer object in-memory. It should have only the fields that you specify in field_names = [...]. You can check with [x.name() for x in subsetted_layer.fields()] in the console.
    – Matt
    Commented Jan 17, 2023 at 15:36
  • So I thought too, but if I don't include QgsProject.instance().addMapLayer(subsetted_layer) the subsetted_layer will change attribute values when I do the rearranging, which is exactly what I want it not to do. Do you have any idea why?
    – Joel
    Commented Jan 17, 2023 at 20:48

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.