I got tired of forgetting whatever the inputs to the various tree layer methods are so I made a function to handle all that for me. It takes whatever thing (group name, layer id, QgsMapLayer, or QgsLayerTreeNode) you want moved and moves it to a group, creating the group as needed. You can also pass in a group object, too, in case you forget that the group API only allows strings.
def move_to_group(thing, group, pos=0, expanded=False):
"""Move a layer tree node into a layer tree group.
Parameter
---------
thing : group name (str), layer id (str), qgis.core.QgsMapLayer, qgis.core.QgsLayerTreeNode
Thing to move. Can be a tree node (i.e. a layer or a group) or
a map layer, the object or the string name/id.
group : group name (str) or qgis.core.QgsLayerTreeGroup
Group to move the thing to. If group does not already exist, it
will be created.
pos : int
Position to insert into group. Default is 0.
extended : bool
Collapse or expand the thing moved. Default is False.
Returns
-------
Tuple containing the moved thing and the group moved to.
Note
----
Moving destroys the original thing and creates a copy. It is the
copy which is returned.
"""
tree = qgis.core.QgsProject.instance().layerTreeRoot()
# thing
if isinstance(thing, str):
try: # group name
node_object = tree.findGroup(thing)
except: # layer id
node_object = tree.findLayer(thing)
elif isinstance(thing, qgis.core.QgsMapLayer):
node_object = tree.findLayer(thing)
elif isinstance(thing, qgis.core.QgsLayerTreeNode):
node_object = thing # tree layer or group
# group
if isinstance(group, qgis.core.QgsLayerTreeGroup):
group_name = group.name()
else: # group is str
group_name = group
group_object = tree.findGroup(group_name)
if not group_object:
group_object = tree.addGroup(group_name)
# do the move
node_object_clone = node_object.clone()
node_object_clone.setExpanded(expanded)
group_object.insertChildNode(pos, node_object_clone)
parent = node_object.parent()
parent.removeChildNode(node_object)
return (node_object_clone, group_object)