3

I'm trying to load big WFS layers to my project by mean of a Python script but since I only need to display features located in the south west of France I thought I could easily add a bbox filter in the request url like this:

https://wxs.ign.fr/administratif/geoportail/wfs?VERSION=2.0.0&TYPENAMES=ADMINEXPRESS-COG-CARTO.LATEST:arrondissement&COUNT=1000&SRSNAME=EPSG::4326&BBOX=42.374778,-2.109375,47.115000,2.856445&request=GetFeature&

However, despite the bbox filter, the WFS layer is loaded nationwide every time I add it to the QGIS project.

How should I proceed to load only the features I want ?

I already had a look there:

1 Answer 1

4

You can use the SQL Query Composer in the WFS Server Connection Dialog when adding the data. There you can create a spatial filter. enter image description here

EDIT: For using WFS via GeoServer in python and setting a bounding-box GeoServer requires a POST rather than a GET request as statet here:

https://docs.geoserver.org/latest/en/user/services/wfs/reference.html

"While there are limited options available in a GET request for spatial queries (more are available in POST requests using filters), filtering by bounding box (BBOX) is supported."

So one approach would be to query the data in your script beforehand making a post request and from the result create the layer on the fly:

That's how your query would look like in curl:

curl --location --request POST 'https://wxs.ign.fr/administratif/geoportail/wfs?VERSION=2.0.0&TYPENAMES=ADMINEXPRESS-COG-CARTO.LATEST:arrondissement&COUNT=1000&SRSNAME=EPSG:4326&BBOX=47.0,2.7,47.1,2.8&request=GetFeature&outputFormat=json'

In QGIS you could load the data using urllib like:

from urllib import request, parse
import json

# Query Data
url = 'https://wxs.ign.fr/administratif/geoportail/wfs?VERSION=2.0.0&TYPENAMES=ADMINEXPRESS-COG-CARTO.LATEST:arrondissement&COUNT=1000&SRSNAME=EPSG:4326&BBOX=47.0,2.7,47.1,2.8&request=GetFeature&outputFormat=json'
req = request.Request(url, method="POST")
r = request.urlopen(req)
content = r.read().decode('utf-8')
print(content)

# Add Layer
vlayer = QgsVectorLayer(content,"Some Data","ogr")
QgsProject.instance().addMapLayer(vlayer)

Note: I changed your initial bounding box in the sample to a smaller value - your initial bounding box result has around 8MB of data.

enter image description here

6
  • Thanks for your answer @bloigge but unfortunately I'm looking for an automated way to do that since my goal is to add this function within a qgis plugin Commented Apr 4, 2022 at 14:11
  • I updated the answer Commented Apr 4, 2022 at 15:35
  • 1
    Btw.: I just re-read the Geo-Server manual - you can use a GET Request as well in the python code req = request.Request(url) Commented Apr 5, 2022 at 8:44
  • There is one downside: the use of ogr which makes the loading of layers far slower than with WFS. That's weird that we can't add a spatial filter with a WFS provider instead of ogr ! Do you know why ? Commented Apr 5, 2022 at 10:01
  • 1
    If you enable the debugging / development tools you can see that QGIS automatically appends a BBOX to every WFS request based on the current view (if it changes because of panning the map). So appending a BBOX to the URL of the WFS wouldn't work because QGIS overrules this every time you move the map. A solution would be to change the BBOX / query on the server - if you are not responsible use a proxy in between like mapproxy. Commented Apr 6, 2022 at 5:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.