使用 QGIS,如何正确 link 一个 postgis sql 层?

Using QGIS, how to properly link a postgis sql layer?

我在 QGIS 2.18 中使用 DB Manager 没有问题,但是如果我尝试添加一个基于长 运行 查询(1 分钟以上)的图层,QGIS 将变得完全无法使用。似乎每次地图平移、每次鼠标单击等都会触发某种图层刷新。

这对一个人来说似乎很愚蠢,尤其是考虑到您可以右键单击图层并请求刷新。更重要的是,它会使应用程序无法使用。我在这里做错了什么?是否无法创建图层并且仅在请求时更新它?

显然我可以在 postgres 中为所有空间查询创建物化视图,但这似乎无法在 QGIS 中做到这一点

我写了一个名为 postgisQueryBuilder that helps in db view creation, even with materialized, directive and allows, browsing the db connection available layers, to refresh the materialized views from QGIS. Check if you can be helpful 的插件。

不幸的是,repaintRequested() 信号没有触发刷新 canvas 所以我写了一个小 python 函数,您可以将其粘贴到 QGIS python 控制台编辑器中以生成物化视图从查询中添加到地图canvas 作为动态层 向图例菜单添加一个操作以按需刷新和重新加载视图

from qgis.core import QgsVectorLayer, QgsDataSourceURI, QgsMapLayerRegistry
from PyQt4.QtSql import QSqlDatabase
from PyQt4.QtGui import QAction

PSQLHost = "your_db_host"
PSQLPort = 5432
PSQLDatabase = "your_db"
PSQLUsername = "your_db_user"
PSQLPassword = "your_db_password"

LAYERNAME = "my materialized_view_layer"
QUERY = "select * from your_table"

class materialized_layer:

    def __init__(self):
        #setup connection
        geom_field = "geom"
        pkey_field = "id"
        self.db = QSqlDatabase.addDatabase("QPSQL")
        self.db.setHostName(PSQLHost)
        self.db.setPort(PSQLPort)
        self.db.setDatabaseName(PSQLDatabase)
        self.db.setUserName(PSQLUsername)
        self.db.setPassword(PSQLPassword)
        self.db.open()
        # generate materialized view
        create_query = 'CREATE MATERIALIZED VIEW "%s" AS %s' % (LAYERNAME,QUERY)
        self.db.exec_(create_query)
        # add to canvas
        qgis_uri = QgsDataSourceURI()
        qgis_uri.setConnection(PSQLHost,str(PSQLPort),PSQLDatabase,PSQLUsername,PSQLPassword)
        qgis_uri.setDataSource("",LAYERNAME,geom_field,"",pkey_field)
        self.materialized_layer = QgsVectorLayer(qgis_uri.uri(), LAYERNAME, "postgres")
        if self.materialized_layer.isValid():
            #register new qgis layer and add action to layer contextual menu
            QgsMapLayerRegistry.instance().addMapLayer(self.materialized_layer,True)
            refresh_materialized_action = QAction( "Refresh materialized view and reload", iface.legendInterface() )
            iface.legendInterface().addLegendLayerAction(refresh_materialized_action, "","", QgsMapLayer.VectorLayer,False)
            iface.legendInterface().addLegendLayerActionForLayer(refresh_materialized_action, self.materialized_layer)
            refresh_materialized_action.triggered.connect(self.refresh_layer)
        else:
            print "invalid layer"

    def reload_layer(self):
        print "RELOADING MATERIALIZED VIEW"
        self.materialized_layer.reload()

    def refresh_layer(self):
        print "REFRESHING MATERIALIZED VIEW"
        refresh_query = 'REFRESH MATERIALIZED VIEW "%s"' % LAYERNAME
        self.db.exec_(refresh_query)
        self.reload_layer()

l = materialized_layer ()