2

I'm working on a plugin for QGIS 3 and I'm fighting with the QgsFieldExpressionWidget widget.

I don't know how how to evaluate the expression added in the box and get the corresponding features as a Python list.

Within the plugin I would like to write a function to call that is able to know if in the QgsFieldExpressionWidget is a simple field (without expression) or a expression that has to be evaluated.

No problem for the first part, but API changed for the QgsFieldExpression and I'm not able to follow the instruction of the PyQGIS cookbook.

This is the function I'm trying to write:

 def getFields(lay, exp):

    # vector layer from the combobox
    vl = lay.currentLayer()
    # vector field (or expression)
    field = exp.currentText()

    data = []

    # get the data from the layer
    # no expression
    if not exp.currentField()[1]:
        for i in vl.getFeatures():
            data.append(i[field])

    # if expression is selected

    # this is the piece of code that is not working for QGIS 3

    else:
        # expression name
        fil = exp.currentField()[0]
        # expr = QgsExpression(fil)
        # for i in vl.getFeatures():
            # data.append(expr.evaluate(i, vl.pendingFields()))
    
    return data

and this is the error I get:

TypeError: QgsExpression.evaluate(): arguments did not match any overloaded call: overload 1: too many arguments overload 2: argument 1 has unexpected type 'QgsFeature'

7
  • Which is the returned error?
    – mgri
    May 11, 2017 at 9:37
  • This is the error: TypeError: QgsExpression.evaluate(): arguments did not match any overloaded call: overload 1: too many arguments overload 2: argument 1 has unexpected type 'QgsFeature'
    – matteo
    May 11, 2017 at 10:00
  • After a quick test, it seems to work using evaluate() without any argument inside. Can you confirm it?
    – mgri
    May 11, 2017 at 10:57
  • I can confirm I don't have any error, but the data list is a list of None after the evaluation of the expression. BTW: exp.isValid() returns True
    – matteo
    May 11, 2017 at 12:19
  • It is still unclear to me which operation you are doing. However, I reproduced your issue by creating a new field storing some simple expressions. Then, I looped over the features and used expr = QgsExpression(str(i['field_name'])) and then value = expr.evaluate() (both inside the loop) and it printed the proper result (when there was an expression in the field). Maybe you need to convert the expression to a string before passing it?
    – mgri
    May 11, 2017 at 12:51

1 Answer 1

2

Perhaps try the method posted in your other question using the QgsExpressionContext and QgsExpressionContextScope classes:

def getFields(lay, exp):
    vl = lay.currentLayer()
    field = exp.currentText()

    context = QgsExpressionContext()
    scope = QgsExpressionContextScope()
    data = []

    if not exp.currentField()[1]:
        for i in vl.getFeatures():
            data.append(i[field])
    else:
        fil = exp.currentField()[0]
        for i in vl.getFeatures():
            scope.setFeature(i)
            context.appendScope(scope)
            exp = QgsExpression(fil)
            data.append(exp.evaluate(context))

    return data

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.