4

I have a vector layer to which I want to apply some constraints using a script with PyQGIS (a NOT NULL constraint on some fields).

I checked the docs of PyQGIS and found setConstraintExpression (int index, const QString &expression, const QString &description=QString()) which as I understand it from the docs it applies to a QgsVectorLayer I used it in my code like this:

my_layer = QgsVectorLayer('./path/to/my_layer.shp', 'my_layer', 'ogr')
field_index = my_layer.fieldNameIndex('ID')
my_layer.setConstraintExpression(field_index, 'NOT NULL')

I get an error that the function does not exist :

> AttributeError: 'QgsVectorLayer' object has no attribute
> 'setConstraintExpression'

I also tried setFieldConstraint and I get the same error. How can I add a constraint on a field using PyQGIS? (QGIS 2.18 Las Palmas)


I've just noticed that these 2 methods I tried are in the QGIS API 2.99.0-Master which is still not released.

3 Answers 3

3

In QGIS v2.18.x you can use the QgsEditFormConfig class.

Set a Not Null constraint:

formConfig = layer.editFormConfig()
formConfig.setNotNull( fieldIndex, True )

Set a constraint expression:

formConfig.setExpression( fieldIndex, myExpression )

Not Null constraint in edit form:

enter image description here

0
1

Since the setters for field constraints won't be available until QGIS 3 on 29th September 2017, I couldn't wait that much to get this problem solved, so I worked around it by catching the event of featureAdded from the active layer in the qgis interface:

First I define a function to check the constraints :

def check_constraints(self, fid):
    feature_iterator = self.iface.activeLayer().getFeatures(QgsFeatureRequest(fid))
    feature = next(feature_iterator)
    code = feature.attributes()[0]
    if not code:
        self.iface.messageBar().pushMessage("Error", "the code of the entity is null !t", level=QgsMessageBar.CRITICAL)

and then I bind it the active layer of the QgsInterface

 self.iface.activeLayer().featureAdded.connect(self.check_constraints)

PS: I'm using it inside a class of a plugin that's why I use self.iface and not directly qgis.utils.iface

1
  • Constraints are already available in QGIS 2.18 Commented Sep 8, 2017 at 10:10
0
# Get the layer by its name
topo_details_layer_name = 'Topo_Details'
details_layer = QgsProject.instance().mapLayersByName(
            topo_details_layer_name)[0]
name_field_index = details_layer.fields().indexFromName('Name')
details_layer.setFieldConstraint(
            name_field_index, QgsFieldConstraints.ConstraintNotNull)

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.