diff --git a/compensation/filters.py b/compensation/filters.py index 8bf0c232..1595b985 100644 --- a/compensation/filters.py +++ b/compensation/filters.py @@ -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: diff --git a/intervention/filters.py b/intervention/filters.py index 205b35c6..1dad9d36 100644 --- a/intervention/filters.py +++ b/intervention/filters.py @@ -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 diff --git a/konova/filters.py b/konova/filters.py new file mode 100644 index 00000000..ace6b4e9 --- /dev/null +++ b/konova/filters.py @@ -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 diff --git a/konova/models/geometry.py b/konova/models/geometry.py index aad39d6f..0a380b48 100644 --- a/konova/models/geometry.py +++ b/konova/models/geometry.py @@ -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] diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 2edf9a00..65defeed 100644 Binary files a/locale/de/LC_MESSAGES/django.mo and b/locale/de/LC_MESSAGES/django.mo differ diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index a83b6aab..453d065d 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -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 \n" "Language-Team: LANGUAGE \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"