def get_queryset(self, feature_type: FeatureType) -> QuerySet: """Generate the queryset for the specific feature type. This method can be overwritten in subclasses to define the returned data. However, consider overwriting :meth:`compile_query` instead of simple data. """ queryset = feature_type.get_queryset() # Apply filters compiler = self.compile_query(feature_type, using=queryset.db) if self.value_reference is not None: if feature_type.resolve_element( self.value_reference.xpath) is None: raise InvalidParameterValue( "valueReference", f"Field '{self.value_reference.xpath}' does not exist.", ) # For GetPropertyValue, adjust the query so only that value is requested. # This makes sure XPath attribute selectors are already handled by the # database query, instead of being a presentation-layer handling. field = compiler.add_value_reference(self.value_reference) queryset = compiler.filter_queryset(queryset, feature_type=feature_type) return queryset.values("pk", member=field) else: return compiler.filter_queryset(queryset, feature_type=feature_type)
def decorate_queryset(cls, feature_type: FeatureType, queryset, output_crs, **params): """Update the queryset to let the database render the GML output.""" value_reference = params["valueReference"] match = feature_type.resolve_element(value_reference.xpath) if match.child.is_geometry: # Add 'gml_member' to point to the pre-rendered GML version. return queryset.values( "pk", gml_member=AsGML(get_db_geometry_target(match, output_crs))) else: return queryset
def decorate_queryset(self, feature_type: FeatureType, queryset, output_crs, **params): """Update the queryset to let the database render the GML output. This is far more efficient then GeoDjango's logic, which performs a C-API call for every single coordinate of a geometry. """ queryset = super().decorate_queryset(feature_type, queryset, output_crs, **params) # If desired, the entire FeatureCollection could be rendered # in PostgreSQL as well: https://postgis.net/docs/ST_AsGeoJSON.html match = feature_type.resolve_element(feature_type.geometry_field_name) return queryset.defer(feature_type.geometry_field_name).annotate( _as_db_geojson=AsGeoJSON(get_db_geometry_target(match, output_crs), precision=16))