QGIS PyQGIS – Test Geometry Type from Layers and Perform Join

pyqgisqgis-3qgis-pluginsspatial-join

Summarizing my problem, I'm a beginner and I'm developing a plugin that will be able to do several spatial joins. For this, it will have to separate the spatial from the non-spatial layers and do the spatial join between them.
I've a list of layer names from this code:

layerList = QgsProject.instance().layerTreeRoot().findLayers()
nlist = []
for layer in layerList:
    nlist.append(layer.name())

hence I do the geometry test:

layer = iface.activeLayer()
features = layer.getFeatures()

for feature in features:
    # the geometry type can be of single or multi type
    geom = feature.geometry()

    if geom.type() == QgsWkbTypes.PointGeometry:
        print("point")
    elif geom.type() == QgsWkbTypes.LineGeometry:
        print("line")
    elif geom.type() == QgsWkbTypes.PolygonGeometry:
        print("area")
    elif geom.type() == QgsWkbTypes.UnknownGeometry:
        print("table")

and finally I do the spatial join:

root = QgsProject.instance().layerTreeRoot()
ids = root.findLayerIds()
target = QgsProject.instance().mapLayer(ids[1])
print('target: ', target.id())
layerToJoin = QgsProject.instance().mapLayer(ids[0])
print('layerToJoin: ', layerToJoin.id())
fieldToJoin = QgsProject.instance()
symb = QgsVectorLayerJoinInfo()
symb.setJoinFieldName('id_feature')
symb.setTargetFieldName('id')
symb.setJoinLayerId(layerToJoin.id())
symb.setUsingMemoryCache(True)
symb.setEditable(True)
symb.setDynamicFormEnabled(True)
symb.setUpsertOnEdit(True)
symb.setPrefix('')
symb.setJoinFieldNamesSubset('')
symb.setJoinLayer(layerToJoin)
target.addJoin(symb)

Separately, each code block works fine, but I need to put all together and I doesn't figure how. First issue the QgsProject doesn't have a geometry method, so I can't iterate in the layer list and test the geometry, that way I can't direct a vector layer and postgresql table to do the spatial join.
If anyone has an idea or a better way to do this please help!!!

Best Answer

After some tries I can handle using functions and working better in the loops.

def lyrdict(self):
    g_dict = {}
    t_dict = {}
    i = 0
    for layer_tree in self.layers_tree:
        layer = layer_tree.layer()

        if layer.type() == 0:
            layer_type = layer.geometryType()
            layer_name = layer.name()
            ids = self.root.findLayerIds()

            if layer_type == QgsWkbTypes.PointGeometry or layer_type == QgsWkbTypes.LineGeometry:
                g = layer_name
                gids = ids[i]
                g_dict[gids] = g_dict.setdefault(gids, g)
            elif layer_type == 4:
                t = layer_name
                tids = ids[i]
                t_dict[tids] = t_dict.setdefault(tids, t)
            i += 1
    return g_dict, t_dict

def lyrpair(self):
    g_dict, t_dict = self.lyrdict()
    d = {}
    for k, v in g_dict.items():
        for c, e in t_dict.items():
            if g_dict[k] == t_dict[c]:
                d[k] = d.setdefault(k, c)
    return d

def jointables(self):
    d = self.lyrpair()
    for k, v in d.items():
        target = QgsProject.instance().mapLayer(k)
        layerToJoin = QgsProject.instance().mapLayer(v)
        fieldToJoin = QgsProject.instance()
        symb = QgsVectorLayerJoinInfo()
        symb.setJoinFieldName('id_feature')
        symb.setTargetFieldName('id')
        symb.setJoinLayerId(layerToJoin.id())
        symb.setUsingMemoryCache(True)
        symb.setEditable(True)
        symb.setDynamicFormEnabled(True)
        symb.setUpsertOnEdit(True)
        symb.setPrefix('')
        symb.setJoinLayer(layerToJoin)
        target.addJoin(symb)
Related Question