I am writing a custom function in PyQGIS to use in expression editor: the aim of the function is to retrieve the first feature that contains the current feature from a polygon layer.

def get_containing_feature(value1, feature, parent):
    cont_feature = None
    cont_layer = QgsMapLayerRegistry.instance().mapLayersByName(value1)[0]
    crsSrc = QgsCoordinateReferenceSystem(4326)    # WGS 84
    crsDest = cont_layer.crs()
    xform = QgsCoordinateTransform(crsSrc, crsDest)
    curr_geom = feature.geometry()
    curr_geom2 = xform.transform(curr_geom.asPoint())
    features = cont_layer.getFeatures()
    for feat in features:
        if feat.geometry().contains(curr_geom2):
            cont_feature = feat
    return cont_feature

The layers aren't in the same crs so I need a transformation The polygon layer is accessed by name and I can get its crs using .crs() method, but I don't know how to get the feature's layer and crs (currently EPSG: 4326)


2 Answers 2


I'm pretty new to QGIS thing (API especialy), but it seems that there is no easy way how to obtain reference to layer from feature. Maybe you should pass layer name (or ID) as another argument to function. Then you can get CRS the same way as for polygon layer. In expression editor, you can then pass @layer_name (or @layer_id) variable as parameter to your function. These variables holds name or ID of currently evaluated layer. It is not so clean, but is enough generic (at least for me).


It is currently not well documented but you can add another "magic" parameter to your function and that allows access to such information.

The Python expression function template says

 : param context: If there is an argument called ``context`` found at the last
                   position, this variable will contain a ``QgsExpressionContext``
                   object, that gives access to various additional information like
                   expression variables. E.g. ``context.variable( 'layer_id' )``

So for example:

@qgsfunction(args="auto", group='Custom')
def foo(feature, parent, context):
    layer_id = context.variable("layer_id")

The layer would also be available but that is a C++ pointer and I am not sure if there is any way you could use it here.

You can find the available variables if you open the "Variables" tree in the expression editor dialog.

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