I've set up a .gpkg file with 10 fields, some of which I want to be entered by user and some to be generated automatically when creating a polygon (multipart) feature.
For example I've set up a "CREATED BY" field which is supposed to record the user name of the person who has created the feature. In the layer properties > Attributes form I have specified the "CREATED BY" field to be editable, not NULL, enforce not NULL constraint, default value = @user_full_name (which in preview correctly returns my name) and it's supposed to apply default value on update.
When I create a polygon in QGIS all of the default values get populated correctly. (There's some other ones like fid, date and time, polygon x centre, polygon y center and polygon centre). All work fine.
Now what I'm having problems with is that I'm creating a plugin which downloads data from a REST API call, loads the data into a vector layer and creates a polygon from a buffer (around points from the API call). Here only the fid value gets populated automatically and "CREATED BY", "DATE AND TIME" etc are left a empty / null. From what I know when using .setAttributes in python a "None" value should return the default value specified in the attributes form, but for some reason this doesn't happen.
# Begin editing the output layer
new_buffer_layer.startEditing()
# Select all features
new_buffer_layer.selectAll()
# Copy selected features
new_buffer_layer.dataProvider().addFeatures(new_buffer_layer.selectedFeatures())
# End editing the output layer
new_buffer_layer.commitChanges()
# Begin editing the "SLM SITES - MULTIPART" layer
slm_sites_layer = QgsProject.instance().mapLayersByName("SLM SITES - MULTIPART")[0]
slm_sites_layer.startEditing()
# Clear any existing features in the layer
# slm_sites_layer.dataProvider().deleteFeatures(slm_sites_layer.allFeatureIds())
# Paste features without attributes
for feature in new_buffer_layer.getFeatures():
new_feature = QgsFeature()
new_feature.setGeometry(feature.geometry())
# Set attributes
new_feature.setAttributes([
None, # FEATURE ID - Doesn't work
"F2 - SITE NAME", # SITE NAME - Works
"F3 - CLIENT", # CLIENT - Works
None, # CREATED BY - Doesn't work
"F5 - CREATED FOR", # CREATED FOR - Works
None, # DATE AND TIME - Doesn't work
None, # POLYGON X CENTRE - Doesn't work
None, # POLYGON Y CENTRE - Doesn't work
None, # POLYGON CENTRE COORDINATES
"737737" # JOB NUMBER - Works
]) # Adjust values as needed
slm_sites_layer.dataProvider().addFeature(new_feature)
# End editing the "SLM SITES - MULTIPART" layer
slm_sites_layer.commitChanges()
-
That shouldn't matter. I'm not transferring the data from fields of the source layer to the target layer. In essence I'm taking the geometries only from the source layer and then manually assigning attributes to the objects in the target layer via code.LiMoNiZeR– LiMoNiZeR2024年04月04日 21:57:11 +00:00Commented Apr 4, 2024 at 21:57
-
So I did some more digging around and turns out QDateTime.currentDateTime in python returns the same value as now() in QGIS as a defulat value (for example in my case both work and return 05/04/2024 09:32:22 (GMT Summer Time)).LiMoNiZeR– LiMoNiZeR2024年04月05日 08:46:55 +00:00Commented Apr 5, 2024 at 8:46
1 Answer 1
So it turns out (looking at it now it makes perfect sense) that the default code in QGIS is different than the code in python. I just needed to find the correct code for returning the values FOR PYTHON not QGIS. Below is the edited code that returns the values as needed:
# Paste features without attributes
for feature in new_buffer_layer.getFeatures():
new_feature = QgsFeature()
new_feature.setGeometry(feature.geometry())
# Set attributes
new_feature.setAttributes([
None, # FEATURE ID - Works
"F2 - SITE NAME", # SITE NAME - Works
"F3 - CLIENT", # CLIENT - Works
os.getlogin(), # CREATED BY - Works
"F5 - CREATED FOR", # CREATED FOR - Works
QDateTime.currentDateTime(), # DATE AND TIME - Works
new_feature.geometry().centroid().asPoint().x(), # POLYGON X CENTRE - Works
new_feature.geometry().centroid().asPoint().y(), # POLYGON Y CENTRE - Works
"{},{}".format(new_feature.geometry().centroid().asPoint().x(),new_feature.geometry().centroid().asPoint().y()), # Works
"737737" # JOB NUMBER - Works
])