Skip to content

Commit

Permalink
Add backend filter for "Value Relation" widget type (key-value fields) (
Browse files Browse the repository at this point in the history
#577)

* Add to FieldFilterBackend the management of field with ValueRelation QGIS editing widget.

* Add project and data for tests.

* Ad tests.

---------

Co-authored-by: wlorenzetti <[email protected]>
  • Loading branch information
wlorenzetti and wlorenzetti authored Aug 17, 2023
1 parent 7b90fbb commit 8dd3b4e
Show file tree
Hide file tree
Showing 6 changed files with 1,388 additions and 4 deletions.
48 changes: 45 additions & 3 deletions g3w-admin/core/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)
from rest_framework.exceptions import ParseError
from urllib.parse import unquote
from core.utils.qgisapi import get_qgis_layer, get_qgis_features
from qdjango.models import Layer

class BaseFilterBackend():
Expand Down Expand Up @@ -246,7 +247,8 @@ class FieldFilterBackend(BaseFilterBackend):
'gte': '>=',
'lte': '<=',
'like': 'LIKE',
'ilike': 'ILIKE'
'ilike': 'ILIKE',
'in': 'IN'
}

def apply_filter(self, request, metadata_layer, qgis_feature_request, view):
Expand Down Expand Up @@ -296,11 +298,51 @@ def apply_filter(self, request, metadata_layer, qgis_feature_request, view):

pre_post_operator = '%' if field_operator in (
'like', 'ilike') else ''

if "formatter" in request.query_params:
formatter = request.query_params.get("formatter")
if (
formatter.isnumeric()
and int(formatter) == 1
and view.layer.has_value_relation_widget(field_name)
):
config = qgis_layer.editorWidgetSetup(
qgis_layer.fields().indexFromName(field_name)
).config()
relation_qgs_layer = get_qgis_layer(
view.layer.project.layer_set.get(qgs_layer_id=config["Layer"])
)

qfr = QgsFeatureRequest()
pre_post_operator = "%" if field_operator in ("like", "ilike") else ""
vr_single_search_expression = (
"{field_name} {field_operator} {field_value}".format(
field_name=self._quote_identifier(config["Value"]),
field_operator=self.COMPARATORS_MAP[field_operator],
field_value=self._quote_value(
f"{pre_post_operator}{unquote(field_value)}{pre_post_operator}"
),
)
)
qfr.combineFilterExpression(vr_single_search_expression)
features = get_qgis_features(relation_qgs_layer, qfr)

if len(features) > 0:
field_operator = "in"
in_content = ",".join(["'" + str(f[config["Key"]]) + "'" for f in features])
field_value = f"({in_content})"

pre_post_operator = "%" if field_operator in ("like", "ilike") else ""
if field_operator != 'in':
quoted_field_value = self._quote_value(
f'{pre_post_operator}{unquote(field_value)}{pre_post_operator}')
else:
quoted_field_value = field_value

single_search_expression = '{field_name} {field_operator} {field_value}'.format(
field_name=self._quote_identifier(field_name),
field_operator=self.COMPARATORS_MAP[field_operator],
field_value=self._quote_value(
f'{pre_post_operator}{unquote(field_value)}{pre_post_operator}')
field_value=quoted_field_value
)

search_expression = f'{search_expression} {single_search_expression}'
Expand Down
8 changes: 8 additions & 0 deletions g3w-admin/qdjango/models/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,14 @@ def add_style(self, style, qml):

return result

def has_value_relation_widget(self, field_name: str) -> bool:
"""
Check if a field_name has a QGIS Form ValueRelation Widget
"""

edittypes = eval(self.edittypes)
return edittypes[field_name]["widgetv2type"] == "ValueRelation"

@property
def extent_rect(self):
"""Return dict of coordinates extension string
Expand Down
1 change: 1 addition & 0 deletions g3w-admin/qdjango/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
QGS328_FILE = 'gruppo-1_un-progetto_qgis328.qgs'
QGS322_INITEXTENT_GEOCONSTRAINT_FILE = 'test_initextent_by_geoconstraint.qgs'
QGS322_FORMATTING_DATE = 'Testing_Date_and_Datetime_formatting_322.qgs'
QGS328_VALUE_RELATION = 'value_relation_qgis328.qgs'


@override_settings(
Expand Down
Binary file not shown.
Loading

0 comments on commit 8dd3b4e

Please sign in to comment.