【问题标题】:Using QGIS, how to properly link a postgis sql layer?使用 QGIS,如何正确链接 postgis sql 层?
【发布时间】:2017-05-01 18:19:12
【问题描述】:

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

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

显然我可以在 postgres 中为所有空间查询创建物化视图,但这似乎违背了在 QGIS 中能够做到这一点的意义

【问题讨论】:

  • 我应该澄清一下这个问题有点错误,因为“右键单击图层并请求刷新”在技术上设置为更改底层查询,而不仅仅是刷新数据。

标签: postgis qgis


【解决方案1】:

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

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 ()

【讨论】:

    【解决方案2】:

    我编写了一个名为postgisQueryBuilder 的插件,它有助于创建数据库视图,即使使用物化、指令和允许,浏览数据库连接可用层,以从 QGIS 刷新物化视图。 Check if you can be helpful.

    【讨论】:

    • 这看起来确实很有用,但我不确定它是否能解决我的问题。你是说如果我使用你的插件创建一个链接层,结果将被缓存在 qgis 中,现在 qgis 将再次保持可用?
    • 您可以在QGIS中加载物化层视图,然后,从插件中(右键单击连接槽下的项目)您可以在需要时触发视图的刷新。这是在数据库级别而不是 QGIS 级别完成的,因此您也必须刷新地图图层。
    • 对,理想情况下,我想做的是不必每次将查询结果加载到 qgis 时都创建物化视图
    猜你喜欢
    • 1970-01-01
    • 2022-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2021-11-24
    相关资源
    最近更新 更多