QGISのプラグイン作成 PostGISのテーブルをマップに表示する
はじめに
PyQGISでPostGISのテーブルをマップに追加する方法について書いています。
このページでは国土数値情報から、避難所と行政区域をPostGISに取り込んで使っています。
行政区域は県毎にレコードを結合しました。
テーブル丸ごと開く
uri = qgis.core.QgsDataSourceUri() uri.setConnection(サーバーアドレス, ポート, データベース名, ユーザーID, パスワード) uri.setDataSource("", "避難所", "geom") vlayer = QgsVectorLayer(uri.uri(),"避難所","postgres") if not vlayer.isValid(): QMessageBox.about(None, "エラー", "開けませんでした。") else: QgsProject.instance().addMapLayer(vlayer)
shp等のファイルと変わらず、マップに追加できます。
クエリを開く
行政区域_都道府県(国土数値情報の行政区域のオブジェクトを県毎に結合して加工したレイヤです)の千葉県に交差する避難所をレイヤとして追加します。
uri = qgis.core.QgsDataSourceUri() uri.setConnection(サーバーアドレス, ポート, データベース名, ユーザーID, パスワード) sql = "select 避難所.* from 避難所, 行政区域_都道府県 where 行政区域_都道府県."N03_001" = '千葉県' and st_intersects(避難所.geom, 行政区域_都道府県.geom)" uri.setDataSource("",f'({sql})',"geom", "", "id") vlayer = QgsVectorLayer(uri.uri(),"避難所","postgres") if not vlayer.isValid(): QMessageBox.about(None, "エラー", "開けませんでした。") else: QgsProject.instance().addMapLayer(vlayer)
このように、特定のレコードだけ抽出して開くことができます。ただ...
編集はできないようです。
Viewを開く
まずPostgreSQLで、千葉県に交差する避難所を抽出するViewを作成します。
CREATE VIEW 避難所ビュー AS SELECT 避難所.* FROM 避難所, 行政区域_都道府県 WHERE 行政区域_都道府県."N03_001" = '千葉県' AND st_intersects(避難所.geom, 行政区域_都道府県.geom);
Viewを作成できたら、実行します。
uri = qgis.core.QgsDataSourceUri() uri.setConnection(サーバーアドレス, ポート, データベース名, ユーザーID, パスワード) uri.setDataSource('public', '避難所ビュー', 'geom', '', 'id') vlayer = QgsVectorLayer(uri.uri(False),"避難所ビュー","postgres") if not vlayer.isValid(): QMessageBox.about(None, "エラー", "開けませんでした。")
この方法も千葉県に交差する避難所のレコードだけのレイヤが追加され...
一見編集も可能に見えますが...
編集を確定しようとすると「ジオメトリの値変更中のPostGISエラー」とエラー表示されてしまいます。編集可能なViewは、単一のテーブルから作らないといけないようなので、千葉県内の避難所をViewで抽出するには...
CREATE VIEW 避難所ビュー AS SELECT 避難所.* FROM 避難所 WHERE LEFT("p20_003", 3) = '千葉県';
避難所の「p20_003」フィールドには住所が入っているので、この値を使ってViewを作成します。このVIewであれば編集が可能です。
使い道
クエリやViewを使えば、手間をかけて県毎にわける必要が無くなり、プラグインを作りこめばボタン一発で必要箇所のレコードだけをレイヤとして追加できるようになります。
また、Viewなら複数人で一つのテーブルの編集作業をする際に、Aさんは千葉県、Bさんは埼玉県...という感じで分けられるので、同じレコードを編集してしまうことも無くなるのではと思います(まだ実際に複数人でビューの編集を試していないので不安ですが)。
最後までご覧いただき、ありがとうございました。