PyQGIS Plugin – Setting Dropdown on Feature Attribute Form in QGIS

attribute-formpyqgisqgis-plugins

I have built a plugin (PyQGIS) where once user login, it will display the map with layer retrieved from database. Let say, layer named lot_k is enabled for editing then new polygon is added for this layer after I digitize, it will pop up the feature attribute form as image follows.

enter image description here

Initially, I need to manually insert the value without any value provided.

I understand this can be achieved by edit of value map to populate the value based on field as follows. But I need to set it every time I relogin (as using plugin).

enter image description here

Hence, I would like to make dropdown with Python code to edit the field value for this form. For example, as picture below.

enter image description here

Below is my code :

def configure_attribute_form(layer, field_name, field_values):
  # Check if the field already exists
  if layer.fields().indexFromName(field_name) == -1:
     # Add the drop-down field to the layer
     layer_provider = layer.dataProvider()
     layer_provider.addAttributes([QgsField(field_name, QVariant.String)])
     layer.updateFields()

     # Set the field values
     idx = layer.fields().indexFromName(field_name)
     unique_values = set([f[field_name] for f in layer.getFeatures()])
     for value in field_values:
         if value not in unique_values:
             unique_values.add(value)
             layer_provider.changeAttributeValues({f.id(): {idx: value} for f in layer.getFeatures()})

    layer.commitChanges()
    layer.updateFields()

def on_feature_added(feature):
  # Replace 'lot_k' with the actual name of your layer
  layer_name = 'lot_k'

  # Replace 'majlis' with the name you want for the drop-down field
  field_name = 'kategori'

  # Replace 'value1', 'value2', etc., with the values you want in the drop-down list
  field_values = ['Dewasa', 'Kanak-kanak']

  # Get the layer
  layer = QgsProject.instance().mapLayersByName(layer_name)[0]

  # Configure the attribute form and populate the drop-down field
  configure_attribute_form(layer, field_name, field_values)

  layer_name = 'lot_k'
  layers = QgsProject.instance().mapLayersByName(layer_name)
  if layers:
     layer = layers[0]
     layer.featureAdded.connect(on_feature_added)
     # Configure the attribute form and populate the drop-down field
     configure_attribute_form(layer, 'kategori', ['Dewasa', 'Kanak-kanak'])
  else:
     print(f"Layer '{layer_name}' not found.") 

Best Answer

You can set the value map on an existing field like so:

fields = layer.fields()
idx = fields.indexFromName(field_name)

field_values = ['Dewasa', 'Kanak-kanak']

# use dictionary comprehension to make the value map from the values list - could also create it explicitly: {'Dewasa': 'Dewasa', 'Kanak-kanak': 'Kanak-kanak'}
value_map = {'map': {value: value for value in field_values}}

# create a Value Map widget setup
setup = QgsEditorWidgetSetup('ValueMap', value_map)

# pass the widget setup to the layer using the field index
layer.setEditorWidgetSetup(idx, setup)

On adding a new feature via editing:

enter image description here