Skip to content

Commit

Permalink
Resolves GeoNode#6925: New Thesaurus form generated dynamically based…
Browse files Browse the repository at this point in the history
… on thesaurus avaiable, fix test on thesaurus load, add migration file for updated thesaurus schema
  • Loading branch information
mattiagiupponi committed Feb 3, 2021
1 parent 9d40694 commit f603047
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 59 deletions.
77 changes: 57 additions & 20 deletions geonode/base/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,41 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
import re
import six
import html
import logging
import re

from tinymce.widgets import TinyMCE

from .fields import MultiThesauriField

import six
from bootstrap3_datetime.widgets import DateTimePicker
from dal import autocomplete
from taggit.forms import TagField

from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.core import validators
from django.db.models import Prefetch, Q
from django.forms import models
from django.forms import ModelForm
from django.forms import ModelForm, models
from django.forms.fields import ChoiceField
from django.forms.utils import flatatt
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _

from django.utils.encoding import (
force_text,
)

from bootstrap3_datetime.widgets import DateTimePicker
from modeltranslation.forms import TranslationModelForm
from taggit.forms import TagField
from tinymce.widgets import TinyMCE

from geonode.base.models import HierarchicalKeyword, TopicCategory, Region, License, CuratedThumbnail, \
ResourceBase
from geonode.base.models import ThesaurusKeyword, ThesaurusKeywordLabel
from geonode.documents.models import Document
from geonode.base.enumerations import ALL_LANGUAGES
from geonode.base.models import (CuratedThumbnail, HierarchicalKeyword,
License, Region, ResourceBase, Thesaurus,
ThesaurusKeyword, ThesaurusKeywordLabel, ThesaurusLabel,
TopicCategory)
from geonode.base.widgets import TaggitSelect2Custom
from geonode.documents.models import Document
from geonode.layers.models import Layer

from .fields import MultiThesauriField

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -321,6 +315,49 @@ class Meta:
)



class ThesaurusAvailableForm(forms.Form):
def __init__(self, *args, **kwargs):
super(ThesaurusAvailableForm, self).__init__(*args, **kwargs)
lang = settings.THESAURUS_DEFAULT_LANG if hasattr(settings, 'THESAURUS_DEFAULT_LANG') else 'en'
for item in Thesaurus.objects.all():
tname = ThesaurusLabel.objects.values_list('label', flat=True).filter(id=item.id).filter(lang=lang)
if item.card_max == 0:
continue
elif item.card_max == 1 and item.card_min==0:
print("1 single option optional")
self.fields['opt-' + str(item.id)] = self._define_choicefield(item, False, tname, lang)
elif item.card_max == 1 and item.card_min==1:
print("2 single option required")
self.fields['opt-' + str(item.id)] = self._define_choicefield(item, True, tname, lang)
elif item.card_max == -1 and item.card_min==0:
print("3 multi option optional")
self.fields['opt-' + str(item.id)] = self._define_multifield(item, False, tname, lang)
elif item.card_max == -1 and item.card_min==1:
print("4 multi option req")
self.fields['opt-' + str(item.id)] = self._define_multifield(item, True, tname, lang)

@staticmethod
def _define_multifield(item, required, tname, lang):
return MultiThesauriField(
ThesaurusKeyword.objects.prefetch_related(
Prefetch('keyword', queryset=ThesaurusKeywordLabel.objects.filter(keyword__thesaurus_id=item.id).filter(lang=lang)
)),
widget=autocomplete.ModelSelect2Multiple(
url=f'/base/thesaurus_available/?sysid={item.id}&lang={lang}'
),
label=_(f"{tname[0] if len(tname) > 0 else item.title}"),
required=required
)

@staticmethod
def _define_choicefield(item, required, tname, lang):
return models.ModelChoiceField(
label=f"{tname[0] if len(tname) > 0 else item.title}",
required=required,
queryset=ThesaurusKeywordLabel.objects.filter(keyword__thesaurus_id=item.id).filter(lang=lang)
)

class ResourceBaseDateTimePicker(DateTimePicker):

def build_attrs(self, base_attrs=None, extra_attrs=None, **kwargs):
Expand Down
28 changes: 28 additions & 0 deletions geonode/base/migrations/0051_auto_20210202_1656.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 2.2.16 on 2021-02-02 16:56

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('base', '0050_auto_20210201_1008'),
]

operations = [
migrations.AddField(
model_name='thesaurus',
name='card_max',
field=models.IntegerField(default=True),
),
migrations.AddField(
model_name='thesaurus',
name='card_min',
field=models.IntegerField(default=True),
),
migrations.AddField(
model_name='thesaurus',
name='facet',
field=models.BooleanField(default=True),
),
]
4 changes: 4 additions & 0 deletions geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ class Thesaurus(models.Model):

about = models.CharField(max_length=255, null=True, blank=True)

card_min = models.IntegerField(default=True)
card_max = models.IntegerField(default=True)
facet = models.BooleanField(default=True)

def __str__(self):
return "{0}".format(self.identifier)

Expand Down
7 changes: 6 additions & 1 deletion geonode/base/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from .views import (
ResourceBaseAutocomplete, RegionAutocomplete,
HierarchicalKeywordAutocomplete, ThesaurusKeywordLabelAutocomplete, OwnerRightsRequestView)
HierarchicalKeywordAutocomplete, ThesaurusKeywordLabelAutocomplete, OwnerRightsRequestView, ThesaurusAvailable)


urlpatterns = [
Expand All @@ -43,6 +43,11 @@
name='autocomplete_hierachical_keyword',
),

url(
r'^thesaurus_available',
ThesaurusAvailable.as_view(),
name='thesaurus_available',
),
url(
r'^thesaurus_autocomplete/$',
ThesaurusKeywordLabelAutocomplete.as_view(),
Expand Down
20 changes: 19 additions & 1 deletion geonode/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
from geonode.base.models import (
Region,
ResourceBase,
HierarchicalKeyword,
HierarchicalKeyword, Thesaurus,
ThesaurusKeywordLabel
)

Expand Down Expand Up @@ -318,6 +318,24 @@ def get_results(self, context):
} for result in context['object_list']
]


class ThesaurusAvailable(autocomplete.Select2QuerySetView):
def get_queryset(self):
tid = self.request.GET.get("sysid")
lang = self.request.GET.get("lang")

qs = ThesaurusKeywordLabel.objects.filter(keyword__thesaurus__id=tid).filter(lang=lang).order_by('id')
print(qs.query)
return qs

def get_results(self, context):
return [
{
'id': self.get_result_value(result.keyword),
'text': self.get_result_label(result),
'selected_text': self.get_selected_result_label(result),
} for result in context['object_list']
]

class OwnerRightsRequestView(LoginRequiredMixin, FormView):
template_name = 'owner_rights_request.html'
Expand Down
6 changes: 3 additions & 3 deletions geonode/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
from django.contrib.sites.models import Site

from geonode.notifications_helper import has_notifications
from geonode.base.models import Configuration
from geonode.base.models import Configuration, Thesaurus


def resource_urls(request):
"""Global values to pass to templates"""
site = Site.objects.get_current()

thesaurus = Thesaurus.objects.all().exists()
defaults = dict(
STATIC_URL=settings.STATIC_URL,
CATALOGUE_BASE_URL=default_catalogue_backend()['URL'],
Expand Down Expand Up @@ -170,7 +170,7 @@ def resource_urls(request):
False
),
THESAURI_FILTERS=[t['name'] for t in [settings.THESAURUS, ] if
t.get('filter')] if hasattr(settings, 'THESAURUS') else None,
t.get('filter')] if hasattr(settings, 'THESAURUS') else [thesaurus],
MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS=getattr(
settings, 'MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS', False
),
Expand Down
18 changes: 9 additions & 9 deletions geonode/layers/templates/layouts/panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,6 @@
</div>
</div>
<div class="col-lg-5">
<div class="col-lg-12">
<span><label for="{{ layer_form.date_type|id }}">{{ layer_form.keywords.label }}</label></span>
{{ layer_form.keywords }}
</div>
{% if THESAURI_FILTERS %}
<div class="col-lg-12 thesauri_keywords">
{{ tkeywords_form }}
</div>
{% endif %}
<div class="col-lg-6 col-xs-12">
<span><label for="{{ layer_form.date_type|id }}">{{ layer_form.date_type.label }}</label></span>
<!--<p class="xxs-font-size">(Identification of when a given event occurred)</p>-->
Expand Down Expand Up @@ -362,6 +353,15 @@
{% endfor %}
</select>
</div>
<div class="col-lg-12">
<span><label for="{{ layer_form.date_type|id }}">{{ layer_form.keywords.label }}</label></span>
{{ layer_form.keywords }}
</div>
{% if THESAURI_FILTERS %}
<div class="col-lg-12 thesauri_keywords">
{{tkeywords_form.as_p}}
</div>
{% endif %}
</div>
</div>
</div>
Expand Down
61 changes: 37 additions & 24 deletions geonode/layers/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
import base64
import traceback
from types import TracebackType
import warnings
import decimal
import pickle
from django.forms.fields import ChoiceField
import six
from django.db.models import Q
from urllib.parse import quote
Expand Down Expand Up @@ -62,10 +64,10 @@
from django.forms.utils import ErrorList

from geonode.base.auth import get_or_create_token
from geonode.base.forms import CategoryForm, TKeywordForm, BatchPermissionsForm
from geonode.base.forms import CategoryForm, TKeywordForm, BatchPermissionsForm, ThesaurusAvailableForm
from geonode.base.views import batch_modify
from geonode.base.models import (
Thesaurus,
Thesaurus, ThesaurusKeyword,
TopicCategory)
from geonode.base.enumerations import CHARSETS
from geonode.decorators import check_keyword_write_perms
Expand Down Expand Up @@ -1035,29 +1037,40 @@ def layer_metadata(
prefix="category_choice_field",
initial=topic_category.id if topic_category else None)


# Create THESAURUS widgets
lang = settings.THESAURUS_DEFAULT_LANG if hasattr(settings, 'THESAURUS_DEFAULT_LANG') else 'en'
tkeywords_form = []
if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
warnings.warn('The settings for Thesaurus has been moved to Model, this feature will be removed in next releases', DeprecationWarning)
tkeywords_form = [TKeywordForm(instance=layer)]
else:
tkeywords_form = ThesaurusAvailableForm()

# Keywords from THESAURUS management
layer_tkeywords = layer.tkeywords.all()
tkeywords_list = ''
lang = 'en' # TODO: use user's language
if layer_tkeywords and len(layer_tkeywords) > 0:
tkeywords_ids = layer_tkeywords.values_list('id', flat=True)
if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
el = settings.THESAURUS
thesaurus_name = el['name']
try:
t = Thesaurus.objects.get(identifier=thesaurus_name)
for tk in t.thesaurus.filter(pk__in=tkeywords_ids):
tkl = tk.keyword.filter(lang=lang)
if len(tkl) > 0:
tkl_ids = ",".join(
map(str, tkl.values_list('id', flat=True)))
tkeywords_list += "," + \
tkl_ids if len(
tkeywords_list) > 0 else tkl_ids
except Exception:
tb = traceback.format_exc()
logger.error(tb)
tkeywords_form = TKeywordForm(instance=layer)
#layer_tkeywords = layer.tkeywords.all()
#tkeywords_list = ''
#lang = 'en' # TODO: use user's language
#if layer_tkeywords and len(layer_tkeywords) > 0:
# tkeywords_ids = layer_tkeywords.values_list('id', flat=True)
# if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
# el = settings.THESAURUS
# thesaurus_name = el['name']
# try:
# t = Thesaurus.objects.get(identifier=thesaurus_name)
# for tk in t.thesaurus.filter(pk__in=tkeywords_ids):
# tkl = tk.keyword.filter(lang=lang)
# if len(tkl) > 0:
# tkl_ids = ",".join(
# map(str, tkl.values_list('id', flat=True)))
# tkeywords_list += "," + \
# tkl_ids if len(
# tkeywords_list) > 0 else tkl_ids
# except Exception:
# tb = traceback.format_exc()
# logger.error(tb)
#tkeywords_form = TKeywordForm(instance=layer)

if request.method == "POST" and layer_form.is_valid() and attribute_form.is_valid(
) and category_form.is_valid():
new_poc = layer_form.cleaned_data['poc']
Expand Down
2 changes: 1 addition & 1 deletion geonode/tests/test_load_thesaurus.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def setUpTestData(cls):
stdout="out",
)

def setUp(self) -> None:
def setUp(self):
self.rdf_path = f"{os.path.dirname(os.path.abspath(__file__))}/data/thesaurus.rdf"
self.Thesaurus = Thesaurus(
identifier="foo_name",
Expand Down

0 comments on commit f603047

Please sign in to comment.