2

I have an existing layout and I'm trying to export it to PDF from a standalone script after the data is updated automatically. If I open QGIS and export all is good but when I call it from Python I get the basemap and point overlay only. My polygon layer is missing.

I had to unlock/lock the layers then save the layout to get the points to display in the exported PDF but no joy for the polygons.

Both the point and polygon layer come from an Oracle database layer but only the polygon layer uses the authentication manager for the credentials (i.e. authcfg).

Code example:

#!/usr/bin/env python3
import os, time
from qgis.PyQt.QtCore import QSettings
from qgis.PyQt.QtSql import QSqlDatabase, QSqlQuery
from qgis.core import (QgsProject, QgsLayoutExporter, QgsApplication, QgsAuthManager, QgsFeedback)

QgsApplication.setPrefixPath("/usr", True)

gui_flag = False
app = QgsApplication([], gui_flag)

app.initQgis()

project_path = os.getcwd() + '/project.qgs'

project_instance = QgsProject.instance()
project_instance.setFileName(project_path)
project_instance.read()

authMgr = QgsApplication.authManager()
if authMgr.authenticationDatabasePath():
    print('INFO: Auth already initilised => we are inside a QGIS app.')
    msg = 'Inside QGIS'
else:
    print('WARNING: outside qgis, e.g. in a testing environment => setup env var before')
    # db init
    os.environ['QGIS_AUTH_DB_DIR_PATH'] = "profile/qgis-auth.db"
    msg = 'Master password could not be set'
    assert authMgr.setMasterPassword("password", True), msg
    authMgr.init( "profile/qgis-auth.db" )

if not QSqlDatabase.isDriverAvailable('QOCISPATIAL'):
    print("WARNING: Oracle not available")
else:
    db = QSqlDatabase.addDatabase("QOCISPATIAL")
    db.setDatabaseName("oracleDatabase:1521/dbName")
    db.setUserName("username")
    db.setPassword("password")
    
    if db.isValid():
        if not db.open():
            print("WARNING: Oracle not available")
        else:
            print("INFO: Oracle database available")
            
manager = QgsProject.instance().layoutManager()
timestr = time.strftime("%Y%m%d-%H%M%S")

feedback = QgsFeedback()

layout = manager.layoutByName("layoutName") # name of the layout
# or layout = manager.layouts()[0] # first layout

exportSettings = QgsLayoutExporter.PdfExportSettings()
exportSettings.flags = layout.renderContext().flags()
exportSettings.dpi = 150
exportSettings.forceVectorOutput = True
exportSettings.writeGeoPdf = True
exportSettings.includeGeoPdfFeatures = False

exporter = QgsLayoutExporter(layout)
exporter.exportToPdf(project_instance.absolutePath() + "/layoutName-" + timestr + ".pdf",
                     exportSettings)

app.exitQgis()

You can see that I have already put in a number of, largely unnecessary, checks to ensure that it is connecting to the Oracle database and those seem to be working. In addition it now draws the point layer which is also coming from the Oracle database.

My working hypothesis is that the authentication credentials are failing but I don't get an error so it is difficult to debug that. Since changing from QgsLayoutExporter.PdfExportSettings() to defining them manually I now get errors about the Dimensions of the inserted PDF page differing from the output PDF page but I'm not sure they are linked as the PDF is still created successfully; just without the polygon layer.

Update

I have now tried the script again using the username and password typed into the project and I can confirm the layer is always missing if I use an authcfg and works fine if the username and password are in the project file.

My question is therefore changed to; how can you use the authentication manager for a layer and still be able to export to PDF using a standalone python script?

4
  • Hi, I am facing a similar problem. But even if I store the db username and password inside my project file, I cannot export PostGIS layers (using a standalone script). Did you find a solution?
    – Roland
    May 7, 2021 at 11:58
  • Hi, I don't think so. I think I have just added the connection manually with the username and password. I'm having the trouble again at the moment whilst trying to save a project file standalone and I think it is linked. Despite trying to inform where qgis-auth.db is located it seems to always return as being in the python profile folder rather than looking at the QGIS profile. May 26, 2021 at 10:29
  • I've just checked and if I copy the qgis-auth.db and qgis.db files to the user profile for python (rather than QGIS) I am able to load a PostGIS layer using the authentication manager so it does appear to be to do with out the manager is loaded standalone. I have attempted to set the correct path in the .init() function but that doesn't seem to be working. May 26, 2021 at 10:41
  • It seems that I passed the wrong path when using QgsApplication.setPrefixPath(). After getting the correct path in the QGIS Python console (QgsApplication.prefixPath()) and using the result (in my case: /usr) in my script as argument for setPrefixPath, everything worked fine.
    – Roland
    May 27, 2021 at 11:07

1 Answer 1

1

I believe the solution is move the authentication manager section up in my code to be above the project.read() statement. It needs to be initiated prior to the project being read or any layers with config authentication will have issues.

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.