Before I run my code, I need to move the focus to a group in my layer tree. I managed to do it with a layer:

registry = QgsProject.instance()
layer = registry.mapLayersByName("LayerName")[0]

but there doesn't seem to be a similar method for groups, like

group = root.findGroup ('groupName')

How is this accomplished?


I have tried to use this code:

#Moving the 4 layers generated by the model to the group "QS"
ModelTuple = ("Cirlces", "Border 1", "Border 2", "Trees")
for itm in ModelTuple:
        layer = QgsProject.instance().mapLayersByName(itm)[0]
        root = QgsProject.instance().layerTreeRoot()
        mylayer = root.findLayer(layer.id())
        myClone = mylayer.clone()
        parent = mylayer.parent()
        group = root.findGroup("QS")
        group.insertChildNode(0, myClone)
        print("Error: "+ itm)

it works perfectly fine in a new blank project. But when the code is executed in my already created project with several groups and layers, 2 of the layers from the model can't be cloned, for some reason, error message:

AttributeError: 'NoneType' object has no attribute 'clone'

so I decided to go a different way: not move the 4 layers to the group "QS", but instead choose the right place in the layer tree before hand and leave the layers right there.

  • 3
    What is the purpose of activating a group?
    – Fran Raga
    Jul 23, 2019 at 16:49
  • The python script is executing a model and the 4 layers it is generating get added above the layer or group that the user has activated at the time. In my case, the best place for the new layers is above an existing group.
    – GISme
    Jul 23, 2019 at 20:19

2 Answers 2


You can insert a layer above an existing group without having to activate it like this:

new_layer = QgsVectorLayer('C:\\Users\\Ben\\Desktop\\TEMP\\AT_shp.shp', 'Test_Layer', 'ogr')
# get legend items and store their names in a list
_children = QgsProject().instance().layerTreeRoot().children()
_names = [x.name() for x in _children]
# get the index of your group item using its name
node_index = _names.index('Your Group Name')
# access the root group of the layer tree model
_root = iface.layerTreeView().model().rootGroup()
# add the new layer to the project without adding it to the legend by passing False as 2nd arg
QgsProject().instance().addMapLayer(new_layer, False)
# now insert layer to legend in desired position using index of group node
_root.insertLayer(node_index, new_layer)

Above is tested in QGIS 3.4

If you are adding multiple layers and you had the layer objects stored in a list like:

_layers = [....]

You should be able to do something like:

QgsProject().instance().addMapLayers(_layers, False)
for l in _layers:
    _root.insertLayer(node_index, l)
  • Thank you Ben, please review my edited question.
    – GISme
    Jul 24, 2019 at 7:08
  • I found a way: I added a dummy layer to the project at the position I wanted, then set the layer to active, and after running the model, I removed the dummy layer.
    – GISme
    Jul 24, 2019 at 11:01
  • 2
    If this answer solves your initial problem, accept this answer as valid @GISme
    – Fran Raga
    Jul 24, 2019 at 12:37
  • Good one. Glad you have a working solution.
    – Ben W
    Jul 24, 2019 at 12:40

I found a way: I added a dummy layer to the project at the position I wanted, then set the layer to active, and after running the model, I removed the dummy layer.

root = QgsProject.instance().layerTreeRoot()

#Insert dummyLayer 
dummyLayer = QgsVectorLayer("Point?crs=EPSG:4326", "dummyLayer", "memory")
QgsProject.instance().addMapLayer(dummyLayer, False)
node_dummyLayer = root.insertLayer(0, dummyLayer)

#Set dummyLayer active

#Launching the model
#the layers are added "above" the dummyLayer

#remove dummyLayer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.