# 61 Filter backend

* refactors table filters by introducing AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin and RecordableTableFilterMixin
* adds full filter functionality
* refactors TableFilter inheritances for all objects
pull/64/head
mpeltriaux 3 years ago
parent 552559c118
commit 524b5c340f

@ -10,10 +10,11 @@ from django.utils.translation import gettext_lazy as _
from django import forms
from django.db.models import QuerySet
from intervention.filters import InterventionTableFilter
from konova.filters import AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin, \
RecordableTableFilterMixin
class CompensationTableFilter(InterventionTableFilter):
class CompensationTableFilter(AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin, RecordableTableFilterMixin):
""" TableFilter for compensations
Based widely on InterventionTableFilter.
@ -21,7 +22,7 @@ class CompensationTableFilter(InterventionTableFilter):
"""
def _filter_show_all(self, queryset, name, value) -> QuerySet:
def filter_show_all(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_all' setting
Args:
@ -39,7 +40,7 @@ class CompensationTableFilter(InterventionTableFilter):
else:
return queryset
def _filter_show_recorded(self, queryset, name, value) -> QuerySet:
def filter_show_recorded(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_recorded' setting
Args:
@ -58,21 +59,20 @@ class CompensationTableFilter(InterventionTableFilter):
return queryset
class EcoAccountTableFilter(InterventionTableFilter):
class EcoAccountTableFilter(AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin, RecordableTableFilterMixin):
""" TableFilter for eco accounts
Based widely on InterventionTableFilter.
Just some minor changes for EcoAccount model.
"""
sr = django_filters.BooleanFilter(
method='_filter_only_show_unrecorded',
method='filter_only_show_unrecorded',
label=_("Show only unrecorded"),
label_suffix=_(""),
widget=forms.CheckboxInput()
)
def _filter_show_all(self, queryset, name, value) -> QuerySet:
def filter_show_all(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_all' setting
Args:
@ -90,7 +90,7 @@ class EcoAccountTableFilter(InterventionTableFilter):
else:
return queryset
def _filter_only_show_unrecorded(self, queryset, name, value) -> QuerySet:
def filter_only_show_unrecorded(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_recorded' setting
Args:

@ -5,119 +5,20 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 22.07.21
"""
import django_filters
from django import forms
from django.contrib.auth.models import User
from django.db.models import QuerySet, Q
from django.utils.translation import gettext_lazy as _
from intervention.inputs import DummyFilterInput
from intervention.models import Intervention
from konova.filters import AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin, \
RecordableTableFilterMixin
class InterventionTableFilter(django_filters.FilterSet):
class InterventionTableFilter(AbstractTableFilter, GeoReferencedTableFilterMixin, ShareableTableFilterMixin, RecordableTableFilterMixin):
""" TableFilter for Intervention model
"""
sa = django_filters.BooleanFilter(
method='_filter_show_all',
label=_("Show unshared"),
label_suffix=_(""),
widget=forms.CheckboxInput()
)
q = django_filters.Filter(
method='_filter_by_keyword',
# Since we use a custom search bar in the template, we need to 'render' this filter
# as 'anonymous' HiddenInput (no id, no name). This way our custom search bar's id and name won't be
# overwritten with these id and name (which would be equal)
# This way we can use the simple filter method mapping for a parameter without using a predefined widget!
widget=DummyFilterInput(),
)
sr = django_filters.BooleanFilter(
method='_filter_show_recorded',
label=_("Show recorded"),
label_suffix=_(""),
widget=forms.CheckboxInput()
)
# Gemarkung ##ToDo
g = django_filters.CharFilter(
field_name="name",
lookup_expr="icontains",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("District"),
"title": _("Search for district")
}
),
)
# Kreis
## ToDo
# Flur
## ToDo
# Zähler
## ToDo
# Nenner
## ToDo
class Meta:
model = Intervention
fields = []
def __init__(self, user: User, *args, **kwargs):
self.user = user
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _filter_by_keyword(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of search bar input
Args:
queryset ():
name ():
value ():
Returns:
"""
value = value.strip()
# build filter expression
q = Q(title__icontains=value) | Q(identifier__icontains=value)
return queryset.filter(q)
def _filter_show_all(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_all' setting
Args:
queryset ():
name ():
value ():
Returns:
"""
if not value:
return queryset.filter(
users__in=[self.user], # requesting user has access
)
else:
return queryset
def _filter_show_recorded(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_recorded' setting
Args:
queryset ():
name ():
value ():
Returns:
"""
if not value:
return queryset.filter(
recorded=None,
)
else:
return queryset

@ -0,0 +1,311 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 11.01.22
"""
import django_filters
from django import forms
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User
from django.db.models import QuerySet, Q
from intervention.inputs import DummyFilterInput
from konova.models import Parcel, District
class AbstractTableFilter(django_filters.FilterSet):
""" TableFilter for Intervention model
"""
q = django_filters.Filter(
method='_filter_by_keyword',
# Since we use a custom search bar in the template, we need to 'render' this filter
# as 'anonymous' HiddenInput (no id, no name). This way our custom search bar's id and name won't be
# overwritten with these id and name (which would be equal)
# This way we can use the simple filter method mapping for a parameter without using a predefined widget!
widget=DummyFilterInput(),
)
class Meta:
abstract = True
def __init__(self, user: User, *args, **kwargs):
self.user = user
super().__init__(*args, **kwargs)
def _filter_by_keyword(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of search bar input
Args:
queryset ():
name ():
value ():
Returns:
"""
value = value.strip()
# build filter expression
q = Q(title__icontains=value) | Q(identifier__icontains=value)
return queryset.filter(q)
class GeoReferencedTableFilterMixin(django_filters.FilterSet):
""" A mixin for AbstractTableFilter
Specialized on filtering GeoReferenced model types
"""
# Parcel gmrkng
di = django_filters.CharFilter(
method="filter_district",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("District"),
"title": _("Search for district")
}
),
)
# Parcel gmrkng
pg = django_filters.CharFilter(
method="filter_gmrkng",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("Parcel gmrkng"),
"title": _("Search for parcel gmrkng")
}
),
)
# Parcel
p = django_filters.CharFilter(
method="filter_parcel",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("Parcel"),
"title": _("Search for parcel")
}
),
)
# Parcel counter
pc = django_filters.CharFilter(
method="filter_parcel_counter",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("Parcel counter"),
"title": _("Search for parcel counter")
}
),
)
# Parcel counter
pn = django_filters.CharFilter(
method="filter_parcel_number",
label=_(""),
label_suffix=_(""),
widget=forms.TextInput(
attrs={
"placeholder": _("Parcel number"),
"title": _("Search for parcel number")
}
),
)
class Meta:
abstract = True
def _filter_parcel_reference(self, queryset, name, value, filter_value) -> QuerySet:
""" Filters the parcel entries by a given filter_value.
filter_value may already include further filter annotations like 'xy__icontains'
Args:
queryset ():
name ():
value ():
filter_value ():
Returns:
"""
_filter = {
filter_value: value
}
matching_parcels = Parcel.objects.filter(
**_filter
)
related_geoms = matching_parcels.values(
"geometries"
).distinct()
queryset = queryset.filter(
geometry__id__in=related_geoms
)
return queryset
def filter_district(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Gemarkung'
Args:
queryset ():
name ():
value ():
Returns:
"""
matching_districts = District.objects.filter(
krs=value
)
matching_parcels = Parcel.objects.filter(
district__in=matching_districts
)
related_geoms = matching_parcels.values(
"geometries"
).distinct()
queryset = queryset.filter(
geometry__id__in=related_geoms
)
return queryset
def filter_gmrkng(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Gemarkung'
Args:
queryset ():
name ():
value ():
Returns:
"""
queryset = self._filter_parcel_reference(queryset, name, value, "gmrkng__istartswith")
return queryset
def filter_parcel(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Parcel'
Args:
queryset ():
name ():
value ():
Returns:
"""
value = value.replace("-", "")
queryset = self._filter_parcel_reference(queryset, name, value, "flr")
return queryset
def filter_parcel_counter(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Parcel'
Args:
queryset ():
name ():
value ():
Returns:
"""
value = value.replace("-", "")
queryset = self._filter_parcel_reference(queryset, name, value, "flrstck_zhlr")
return queryset
def filter_parcel_number(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Parcel'
Args:
queryset ():
name ():
value ():
Returns:
"""
value = value.replace("-", "")
queryset = self._filter_parcel_reference(queryset, name, value, "flrstck_nnr")
return queryset
class ShareableTableFilterMixin(django_filters.FilterSet):
""" A mixin for AbstractTableFilter
Specialized on filtering shareable model types
"""
sa = django_filters.BooleanFilter(
method='filter_show_all',
label=_("Show unshared"),
label_suffix=_(""),
widget=forms.CheckboxInput()
)
class Meta:
abstract = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.user is None:
raise AttributeError("User must be set for further filtering!")
def filter_show_all(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_all' setting
Args:
queryset ():
name ():
value ():
Returns:
"""
if not value:
return queryset.filter(
users__in=[self.user], # requesting user has access
)
else:
return queryset
class RecordableTableFilterMixin(django_filters.FilterSet):
""" A mixin for AbstractTableFilter
Specialized on filtering recordable model types
"""
sr = django_filters.BooleanFilter(
method='filter_show_recorded',
label=_("Show recorded"),
label_suffix=_(""),
widget=forms.CheckboxInput()
)
class Meta:
abstract = True
def filter_show_recorded(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'show_recorded' setting
Args:
queryset ():
name ():
value ():
Returns:
"""
if not value:
return queryset.filter(
recorded=None,
)
else:
return queryset

@ -110,9 +110,13 @@ class Geometry(BaseResource):
underlying_parcels = []
for result in fetched_parcels:
fetched_parcel = result[typename]
# There could be parcels which include the word 'Flur',
# which needs to be deleted and just keep the numerical values
## THIS CAN BE REMOVED IN THE FUTURE, WHEN 'Flur' WON'T OCCUR ANYMORE!
flr_val = fetched_parcel["ave:flur"].replace("Flur ", "")
parcel_obj = Parcel.objects.get_or_create(
gmrkng=fetched_parcel["ave:gemarkung"],
flr=fetched_parcel["ave:flur"],
flr=flr_val,
flrstck_nnr=fetched_parcel['ave:flstnrnen'],
flrstck_zhlr=fetched_parcel['ave:flstnrzae'],
)[0]

Binary file not shown.

@ -6,20 +6,22 @@
#: compensation/filters.py:71 compensation/forms/modalForms.py:34
#: compensation/forms/modalForms.py:45 compensation/forms/modalForms.py:61
#: compensation/forms/modalForms.py:238 compensation/forms/modalForms.py:316
#: intervention/filters.py:26 intervention/filters.py:40
#: intervention/filters.py:47 intervention/filters.py:48
#: intervention/filters.py:25 intervention/filters.py:31
#: intervention/forms/forms.py:52 intervention/forms/forms.py:154
#: intervention/forms/forms.py:166 intervention/forms/modalForms.py:125
#: intervention/forms/modalForms.py:138 intervention/forms/modalForms.py:151
#: konova/forms.py:140 konova/forms.py:241 konova/forms.py:312
#: konova/forms.py:339 konova/forms.py:349 konova/forms.py:362
#: konova/forms.py:374 konova/forms.py:392 user/forms.py:38
#: konova/filters.py:64 konova/filters.py:65 konova/filters.py:76
#: konova/filters.py:77 konova/filters.py:88 konova/filters.py:89
#: konova/filters.py:100 konova/filters.py:101 konova/filters.py:113
#: konova/filters.py:114 konova/forms.py:140 konova/forms.py:241
#: konova/forms.py:312 konova/forms.py:339 konova/forms.py:349
#: konova/forms.py:362 konova/forms.py:374 konova/forms.py:392 user/forms.py:38
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-07 15:32+0100\n"
"POT-Creation-Date: 2022-01-11 09:31+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -1197,22 +1199,14 @@ msgstr "EMA {} bearbeitet"
msgid "EMA removed"
msgstr "EMA entfernt"
#: intervention/filters.py:25
#: intervention/filters.py:24
msgid "Show unshared"
msgstr "Nicht freigegebene anzeigen"
#: intervention/filters.py:39
#: intervention/filters.py:30
msgid "Show recorded"
msgstr "Verzeichnete anzeigen"
#: intervention/filters.py:51
msgid "District"
msgstr "Gemarkung"
#: intervention/filters.py:52
msgid "Search for district"
msgstr "Nach Gemarkung suchen"
#: intervention/forms/forms.py:44
msgid "Construction XY; Location ABC"
msgstr "Bauvorhaben XY; Flur ABC"
@ -1521,6 +1515,46 @@ msgstr ""
"somit nichts eingeben, bearbeiten oder sonstige Aktionen ausführen. "
"Kontaktieren Sie bitte einen Administrator. +++"
#: konova/filters.py:68
msgid "District"
msgstr "Kreis"
#: konova/filters.py:69
msgid "Search for district"
msgstr "Nach Kreis suchen"
#: konova/filters.py:80
msgid "Parcel gmrkng"
msgstr "Gemarkung"
#: konova/filters.py:81
msgid "Search for parcel gmrkng"
msgstr "Nach Gemarkung suchen"
#: konova/filters.py:92 konova/templates/konova/includes/parcels.html:18
msgid "Parcel"
msgstr "Flur"
#: konova/filters.py:93
msgid "Search for parcel"
msgstr "Nach Flur suchen"
#: konova/filters.py:104 konova/templates/konova/includes/parcels.html:19
msgid "Parcel counter"
msgstr "Flurstückzähler"
#: konova/filters.py:105
msgid "Search for parcel counter"
msgstr "Nach Flurstückzähler suchen"
#: konova/filters.py:117 konova/templates/konova/includes/parcels.html:20
msgid "Parcel number"
msgstr "Flurstücknenner"
#: konova/filters.py:118
msgid "Search for parcel number"
msgstr "Nach Flurstücknenner suchen"
#: konova/forms.py:37 templates/form/collapsable/form.html:62
msgid "Save"
msgstr "Speichern"
@ -1687,18 +1721,6 @@ msgstr "Kreis"
msgid "Gemarkung"
msgstr "Gemarkung"
#: konova/templates/konova/includes/parcels.html:18
msgid "Parcel"
msgstr "Flur"
#: konova/templates/konova/includes/parcels.html:19
msgid "Parcel counter"
msgstr "Flurstückzähler"
#: konova/templates/konova/includes/parcels.html:20
msgid "Parcel number"
msgstr "Flurstücknenner"
#: konova/templates/konova/widgets/generate-content-input.html:6
msgid "Generate new"
msgstr "Neu generieren"

Loading…
Cancel
Save