Update virtual field on demand (not permanently) (QGIS)

Make the field normal (non-derivative). Runing this piece of code in QGIS as a Python script defines a recomputation function which activates before saving changes to the layer. You can implement your own logic there with any expressions for any fields.

You can also connect this function to an action button if you want to recompute on demand.

def recomputeField(vlayer):
    #recomputes field for chosen layer
    #example case: there are fields a, b and c is the derivative field

    #put your virtual field expression here
    virtualFieldExpr = 'a + b'
    expression = QgsExpression(virtualFieldExpr)

    context = QgsExpressionContext()
    context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vlayer))

    for f in vlayer.getFeatures():
        context.setFeature(f)
        f['c'] = expression.evaluate(context)
        vlayer.updateFeature(f)


#connect the function to vlayer.beforeCommitChanges signal
layerName = 'YOUR_LAYER_NAME'
vlayer = QgsProject.instance().mapLayersByName(layerName)[0]
vlayer.beforeCommitChanges.connect(lambda: recomputeField(vlayer))

EDIT: Some advice on how to use this code. Paste it and run it in the editor (not directly in console cause it often causes syntax errors).

a, b, and c are your field names so replace them in code with the appropriate names for your fields. Change the layerName to your desired layer name. enter image description here


Virtual fields are great, but sometimes I think we get carried away with their usage within QGIS. (don't worry, im guilty too).

From a high level DB engineering perspective, ideally, calculated fields should occur either on database transactions when editing, or produce view tables, thus enabling the user to consume the view table instead. View tables would be suitable candidate replacements for virtual fields.

postGIS would be ideal, but you have mentioned your use of Geopackages. Geopackages are in essence a Sqlite database. Looks like some other users have attempted similar view table structures - see here Create view table with QGIS and Geopackage
(BTW, that link doesn't actually have a solution, it just seems to show that others have tried and that there are some limitations).

Implementing code in QGIS to trigger events may be ok, but this will tie the virtual field creation to the QGIS application itself. This may or may not meet your publishing needs - for example, if its just yourself or other QGIS users, then that is probably ok - but if you are wanting this dynamic capability in - say a web mapping application, then the QGIS solution is not abstract and dynamic.


QGIS supports this out of the box with "default values" and "apply on update"

See https://gis.stackexchange.com/a/211154/9839