* enhances rendering of tables * enhances rendering of filter section * reorganizes table filter codes into konova/filters/ folder and splits into mixins and table_filters
407 lines
11 KiB
Python
407 lines
11 KiB
Python
"""
|
|
Author: Michel Peltriaux
|
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
Created on: 12.01.22
|
|
|
|
"""
|
|
import django_filters
|
|
from django import forms
|
|
from django.db.models import QuerySet, Q
|
|
from django.utils.translation import gettext_lazy as _
|
|
from dal_select2.widgets import ModelSelect2
|
|
|
|
from codelist.models import KonovaCode
|
|
from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_REGISTRATION_OFFICE_ID
|
|
from intervention.inputs import DummyFilterInput
|
|
from konova.models import Parcel, District
|
|
|
|
|
|
class KeywordTableFilterMixin(django_filters.FilterSet):
|
|
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 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 FileNumberTableFilterMixin(django_filters.FilterSet):
|
|
rf = django_filters.CharFilter(
|
|
method="filter_file_number",
|
|
label=_(""),
|
|
label_suffix=_(""),
|
|
widget=forms.TextInput(
|
|
attrs={
|
|
"placeholder": _("File number"),
|
|
"title": _("Search for file number"),
|
|
"class": "form-control",
|
|
}
|
|
),
|
|
)
|
|
|
|
def filter_file_number(self, queryset, name, value) -> QuerySet:
|
|
queryset = queryset.filter(
|
|
Q(responsible__registration_file_number__icontains=value) |
|
|
Q(responsible__conservation_file_number__icontains=value)
|
|
)
|
|
return queryset
|
|
|
|
|
|
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"),
|
|
"class": "form-control",
|
|
}
|
|
),
|
|
)
|
|
# Parcel gmrkng
|
|
pg = django_filters.CharFilter(
|
|
method="filter_gmrkng",
|
|
label=_(""),
|
|
label_suffix=_(""),
|
|
widget=forms.TextInput(
|
|
attrs={
|
|
"placeholder": _("Parcel gmrkng"),
|
|
"title": _("Search for parcel gmrkng"),
|
|
"class": "form-control",
|
|
}
|
|
),
|
|
)
|
|
# Parcel
|
|
p = django_filters.CharFilter(
|
|
method="filter_parcel",
|
|
label=_(""),
|
|
label_suffix=_(""),
|
|
widget=forms.TextInput(
|
|
attrs={
|
|
"placeholder": _("Parcel"),
|
|
"title": _("Search for parcel"),
|
|
"class": "form-control",
|
|
}
|
|
),
|
|
)
|
|
# 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"),
|
|
"class": "form-control",
|
|
}
|
|
),
|
|
)
|
|
|
|
# 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": "form-control",
|
|
}
|
|
),
|
|
)
|
|
|
|
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(
|
|
attrs={
|
|
"class": "form-check-input",
|
|
}
|
|
)
|
|
)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.user = kwargs.pop("user", None)
|
|
if self.user is None:
|
|
raise AttributeError("User must be set for further filtering!")
|
|
super().__init__(*args, **kwargs)
|
|
|
|
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(
|
|
attrs={
|
|
"class": "form-check-input",
|
|
}
|
|
)
|
|
)
|
|
|
|
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
|
|
|
|
|
|
class RegistrationOfficeTableFilterMixin(django_filters.FilterSet):
|
|
""" A mixin for AbstractTableFilter
|
|
|
|
Specialized on filtering for related registration offices
|
|
|
|
"""
|
|
ro = django_filters.ModelChoiceFilter(
|
|
method="filter_reg_office",
|
|
label=_(""),
|
|
label_suffix=_(""),
|
|
queryset=KonovaCode.objects.filter(
|
|
is_archived=False,
|
|
is_leaf=True,
|
|
code_lists__in=[CODELIST_REGISTRATION_OFFICE_ID],
|
|
),
|
|
widget=ModelSelect2(
|
|
url="codes-registration-office-autocomplete",
|
|
attrs={
|
|
"data-placeholder": _("Registration office"),
|
|
"title": _("Search for registration office"),
|
|
"class": "",
|
|
}
|
|
),
|
|
)
|
|
|
|
def filter_reg_office(self, queryset, name, value):
|
|
qs = queryset.filter(
|
|
responsible__registration_office=value
|
|
)
|
|
return qs
|
|
|
|
|
|
class ConservationOfficeTableFilterMixin(django_filters.FilterSet):
|
|
""" A mixin for AbstractTableFilter
|
|
|
|
Specialized on filtering for related conservation offices
|
|
|
|
"""
|
|
co = django_filters.ModelChoiceFilter(
|
|
method="filter_cons_office",
|
|
label=_(""),
|
|
label_suffix=_(""),
|
|
queryset=KonovaCode.objects.filter(
|
|
is_archived=False,
|
|
is_leaf=True,
|
|
code_lists__in=[CODELIST_CONSERVATION_OFFICE_ID],
|
|
),
|
|
widget=ModelSelect2(
|
|
url="codes-conservation-office-autocomplete",
|
|
attrs={
|
|
"data-placeholder": _("Conservation office"),
|
|
"title": _("Search for conservation office"),
|
|
"class": "",
|
|
}
|
|
),
|
|
)
|
|
|
|
def filter_cons_office(self, queryset, name, value):
|
|
qs = queryset.filter(
|
|
responsible__conservation_office=value
|
|
)
|
|
return qs
|