I'm building an Atlas generator based on the QGIS Layout engine. I want to fetch extra data from database based on some attributes of the current feature.
In PyQGIS 2, that was possible with
for i in range(0, atlas.numFeatures()):
atlas.prepareForFeature(i)
feat = atlas.feature() # here I can access any attribute of the current feature
I can't find a way to get the same in PyQGIS 3...
atlas = self.layout.atlas()
atlas.setEnabled(True)
atlas.setCoverageLayer(self.loaded_layers_registry['campaign_parcel'])
atlas.setFilterFeatures(True)
atlas.setFilterExpression('Some expression')
atlas.beginRender()
for i in range(0, atlas.count()):
feature = atlas.?????? # How to get the current feature here????
current_client = results(GET_CLIENT, [feature['client_id']])
# Here I want to update the text of a label or whatever....
exporter = QgsLayoutExporter(atlas.layout())
exporter.exportToPdf(os.path.join(export_directory, atlas.currentFilename() + '.pdf'), QgsLayoutExporter.PdfExportSettings())
atlas.next()
atlas.endRender()
Does anyone know a way?
-- EDIT --
As @J.Monticolo says in comments there is a way but it seems very ugly to me...
The idea is to use the featureChanged
signal of QgsLayoutAtlas
to catch the actual feature. It seems to works pretty well but you need to manually starts the iteration to force the signal to be fired for the first feature.
Then you need to come back to the start. This is the part that seems bad to me...
This is what I use for the moment:
def on_atlas_feature_changed(self, feat):
self.atlas_feature = feat
def export_cr(self):
atlas = self.layout.atlas()
atlas.featureChanged.connect(self.on_atlas_feature_changed)
atlas.beginRender()
for i in range(0, atlas.count()):
if not self.atlas_feature: # self.atlas_feature is initialize to None
atlas.next()
atlas.first() # this step is necessary to fire the featureChanged() signal that give the actual QgsFeature
epandage_html = self.get_epandage_html(self.atlas_feature['id'])
txt_epandage = self.layout.itemById('epandage')
txt_epandage.setText(self.get_epandage_html(self.atlas_feature['id']))
exporter = QgsLayoutExporter(atlas.layout())
exporter.exportToPdf(os.path.join(export_directory, atlas.currentFilename() + '.pdf'), QgsLayoutExporter.PdfExportSettings())
atlas.next()
atlas.endRender()
atlas.featureChanged.disconnect(self.on_atlas_feature_changed)
self.atlas_feature = None
atlas.coverageLayer().getFeature(atlas.currentFeatureNumber())
?currentFeatureNumber()
returns the feature number in the atlas (0, then 1, then 2,...) but the not the feature id.featureChanged
and catch the current feature, I've no other idea.