import operator import time from collections import defaultdict from functools import reduce from itertools import chain, product import simplejson from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from django.db.models import Prefetch, Q from django.http import JsonResponse, QueryDict from django.shortcuts import render from django.template.context_processors import csrf from django.utils.translation import gettext as _ from crispy_forms.utils import render_crispy_form from connections.models import Entry, Subentry, ArgumentConnection, RealisationDescription from meanings.models import LexicalUnit from syntax.models import NaturalLanguageDescription, Schema from semantics.models import Frame, PredefinedSelectionalPreference, SelectivePreferenceRelations, SemanticRole, \ RoleAttribute, RoleSubAttribute from common.decorators import ajax_required, ajax from unifier.models import UnifiedFrame from django.conf import settings from .forms import ( EntryForm, SchemaFormFactory, FrameFormFactory, PositionFormFactory, PhraseAttributesFormFactory, LexFormFactory, LemmaFormFactory, ArgumentFormFactory, PredefinedPreferenceFormFactory, RelationalPreferenceFormFactory, SynsetPreferenceFormFactory, UnifiedFrameFormFactory, FrameOpinionFormFactory, UnifiedArgumentFormFactory, ) from .polish_strings import STATUS, POS, SCHEMA_OPINION, FRAME_OPINION, EXAMPLE_SOURCE, EXAMPLE_OPINION, RELATION from .phrase_descriptions.descriptions import position_prop_description MAX_LAST_VISITED = 10 @login_required def entries(request): # TODO make this automatic by subclassing/configuring session object if 'last_visited' not in request.session: request.session['last_visited'] = [] if 'show_reals_desc' not in request.session: request.session['show_reals_desc'] = True if 'show_linked_entries' not in request.session: request.session['show_linked_entries'] = True user = request.user # TODO retrieve the form from the request session – keep forms between page refreshes, # keep search history, allow saving searches? # if so, don’t delete local forms on main form submit in send_form return render( request, 'entries.html', { 'is_vue_app': True, 'entries_form' : EntryForm(), 'frames_form' : FrameFormFactory.get_form(as_subform=False), 'schemata_form' : SchemaFormFactory.get_form(as_subform=False), 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), 'is_superlexicograf': user.groups.filter(name=settings.SUPER_LEXICOGRAPHS_GROUP_NAME).exists() }) @login_required def unification(request): user = request.user return render( request, 'unification.html', { 'is_vue_app': True, 'unified_frame_id': request.GET.get("unified_frame_id"), 'entries_form' : EntryForm(), 'frames_form': FrameFormFactory.get_form(as_subform=False), 'schemata_form': SchemaFormFactory.get_form(as_subform=False), 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), 'is_superlexicograf': user.groups.filter(name=settings.SUPER_LEXICOGRAPHS_GROUP_NAME).exists() }, ) @login_required def hierarchy(request): unified_frame_id = None if "unified_frame_id" in request.GET: unified_frame_id = request.GET.get("unified_frame_id") return render( request, 'hierarchy.html', { 'is_vue_app': True, 'unified_frame_id': unified_frame_id, 'entries_form': EntryForm(), 'frames_form': FrameFormFactory.get_form(as_subform=False), 'schemata_form': SchemaFormFactory.get_form(as_subform=False), 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), }, ) FORM_TYPES = { 'entry' : EntryForm, } FORM_FACTORY_TYPES = { 'schema' : SchemaFormFactory, 'position' : PositionFormFactory, 'phrase_lex' : LexFormFactory, 'lemma' : LemmaFormFactory, 'frame' : FrameFormFactory, 'unifiedframe' : UnifiedFrameFormFactory, 'FrameOpinion' : FrameOpinionFormFactory, 'argument' : ArgumentFormFactory, 'UnifiedArgument' : UnifiedArgumentFormFactory, 'predefined' : PredefinedPreferenceFormFactory, 'relational' : RelationalPreferenceFormFactory, 'synset' : SynsetPreferenceFormFactory, } def make_form(form_type, data=None, unique_number=None): if form_type in FORM_FACTORY_TYPES: return FORM_FACTORY_TYPES[form_type].get_form(data=data, unique_number=unique_number) if form_type in FORM_TYPES: return FORM_TYPES[form_type](data=data) elif form_type.startswith('phrase_'): phrase_type = form_type[7:] return PhraseAttributesFormFactory.get_form(phrase_type, data=data, unique_number=unique_number) return None @ajax_required def get_subform(request): if request.method == 'GET': ctx = {} ctx.update(csrf(request)) form_type = request.GET['subform_type'] form = make_form(form_type) try: form_html = render_crispy_form(form, context=ctx) except: print('******************', form_type) raise return JsonResponse({'form_html' : form_html}) #TODO clean this code bordello up def filter_objects(objects, queries, tab=''): #print(tab + '===================================================================') for query in queries: #print(tab + '***', query) objects = objects.filter(query).distinct() #print(tab + '---------------------------------------------------------------') #print(tab, objects) #print('\n') #print(tab + '===================================================================') return objects.distinct() def collect_forms(forms_json, errors_collector_dict, tab=' '): data = simplejson.loads(forms_json) form_type = data['formtype'] form_number = data.get('formnumber', 0) if form_type in ('or', 'other'): return form_type else: #print(tab, 'FORM:', data['form']) #print(tab, 'TYPE:', form_type, 'NUMBER:', form_number) #print(tab, 'DATA:', data) query_params = QueryDict(data['form']) #print(tab, 'PARAMS:', query_params) form = make_form(form_type, data=query_params, unique_number=form_number) #print(tab, 'FORM TYPE:', type(form)) if not form.is_valid(): errors_collector_dict.update(form.errors) #print(tab, '{} CHILDREN GROUP(S)'.format(len(data['children']))) # a form may have one or more children forms, organised into and-or # (e.g. an entry form has child schema forms, frame forms etc.) subform_groups = [] for subforms_json in data['children']: subform_group = simplejson.loads(subforms_json) subform_type, subforms = subform_group['formtype'], subform_group['subforms'] children = [[]] conjunctions = set() for child in subforms: child_form = collect_forms(child, errors_collector_dict, tab + ' ') if child_form in ('or', 'other'): children.append([]) conjunctions.add(child_form) else: children[-1].append(child_form) assert(len(conjunctions) <= 1) conjunction = 'or' if not conjunctions else conjunctions.pop() subforms = list(filter(None, children)) if subforms: subform_groups.append((subform_type, conjunction, subforms)) return (form, data['negated'], subform_groups) def reduce_ids_and(ids): # sum the negated ids ids[False] = reduce(lambda x, y: x.union(y), ids[False], set()) if ids[True]: # intersect the non-negated and subtract the sum of negated return (True, reduce(lambda x, y: x.intersection(y), ids[True]) - ids[False]) else: # negate the sum of negated return (False, ids[False]) def other_operator(tab, form, children_group, parent_objects): name, conjunction, children = children_group print(tab, '==============', name, conjunction) print(tab, 'PARENT OBJECTS:', parent_objects) prefixes = set() # matches[id][j] -> set of child ids of ‹id› parent satisfying ‹j›th specification matches = defaultdict(lambda: defaultdict(set)) for i, conj_children in enumerate(children): print(tab, ' ', conjunction) child_ids_and = { True: [], False: [] } for child in conj_children: child_form = child[0] child_objects = get_filtered_objects(child, tab=tab + ' ') prefix = form.get_child_form_prefix(child_form) prefixes.add(prefix) child_ids = set(co.id for co in child_objects) child_ids_and[not child_form.is_negated()].append(child_ids) child_ids_and = reduce_ids_and(child_ids_and) print(tab, ' ===>', '[]'.format(i), child_ids_and[0], len(child_ids_and[1]), sorted(child_ids_and[1])[:10]) # TODO enable negations? assert(child_ids_and[0] == True) for child_id in child_ids_and[1]: assert(prefix.endswith('__in')) for parent in parent_objects.filter(Q((prefix, [child_id]))): matches[parent.id][i].add(child_id) assert(len(prefixes) == 1) N = len(children) matching_parent_ids = set() for parent_id, mtchs in matches.items(): print(tab, parent_id, mtchs) if len(mtchs) < len(children): print(tab, 'not all matched') continue for x in product(*mtchs.values()): if len(x) == len(set(x)): # found N different children objects, each satisfying different specification matching_parent_ids.add(parent_id) print(tab, 'MATCH:', x) continue if parent_id not in matching_parent_ids: print(tab, 'no match') return parent_objects.filter(id__in=matching_parent_ids) def get_filtered_objects(forms, initial_objects=None, tab=' '): form, negated_attrs, children = forms objects = form.model_class.objects.all() if initial_objects is None else initial_objects.all() queries = form.get_queries(negated_attrs) #print(tab, type(form), 'FOR FILTERING:', form.model_class) #print(tab, queries) objects = filter_objects(objects, queries, tab=tab) #print(tab, 'OK') for children_group in children: if children_group[1] == 'other': objects = other_operator(tab, form, children_group, objects) continue #print(tab, 'CHILD FORMS') object_ids_or = [] prefixes = set() for or_children in children_group[2]: objects_and = form.model_class.objects.all() if initial_objects is None else initial_objects.all() for child in or_children: child_form = child[0] child_objects = get_filtered_objects(child, tab=tab + ' ') prefix = form.get_child_form_prefix(child_form) prefixes.add(prefix) child_ids = [co.id for co in child_objects] q = Q((prefix, child_ids)) if child_form.is_negated(): objects_and = objects_and.exclude(q) else: objects_and = objects_and.filter(q) object_ids_or.append({o.id for o in objects_and}) assert(len(prefixes) == 1) object_ids = reduce(operator.or_, object_ids_or) objects = objects.filter(id__in=object_ids) objects = objects.distinct() #print(tab, 'FILTERED:', form.model_class) return objects # forms – an ‘or’ list of ‘and’ lists of forms, the forms are flattened and treated as one ‘or’ list. # The function is used for filtering out schemata/frames. E.g. if the user chooses entries with a schema # safisfying X AND a schema satisfying Y, schemata satisfying X OR Y should be displayed (and all other # schemata should be hidden). def get_filtered_objects2(forms, objects): #print(forms) filtered_ids = [{ schema.id for schema in get_filtered_objects(form, initial_objects=objects) } for form in chain.from_iterable(forms)] filtered_ids = reduce(operator.or_, filtered_ids) return objects.filter(id__in=filtered_ids) @ajax_required def send_form(request): if request.method == 'POST': errors_dict = dict() forms = collect_forms(request.POST['forms[]'], errors_dict) if errors_dict: del request.session['forms'] return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) else: request.session['forms'] = request.POST['forms[]'] if 'schema_form' in request.session: del request.session['schema_form'] if 'frame_form' in request.session: del request.session['frame_form'] return JsonResponse({ 'success' : 1 }) return JsonResponse({}) @ajax_required def send_schemata_form(request): if request.method == 'POST': errors_dict = dict() forms = collect_forms(request.POST['forms[]'], errors_dict) eid = request.POST['entry'] if errors_dict: del request.session['schema_form'] return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) else: request.session['schema_form'] = request.POST['forms[]'] return JsonResponse({ 'success' : 1 }) return JsonResponse({}) @ajax_required def send_frames_form(request): if request.method == 'POST': errors_dict = dict() forms = collect_forms(request.POST['forms[]'], errors_dict) eid = request.POST['entry'] if errors_dict: del request.session['frame_form'] return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) else: request.session['frame_form'] = request.POST['forms[]'] return JsonResponse({ 'success' : 1 }) return JsonResponse({}) @ajax_required def send_unified_frames_form(request): if request.method == 'POST': errors_dict = dict() forms = collect_forms(request.POST['forms[]'], errors_dict) eid = request.POST['entry'] if errors_dict: del request.session['unified_frame_form'] return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) else: request.session['unified_frame_form'] = request.POST['forms[]'] return JsonResponse({ 'success' : 1 }) return JsonResponse({}) def get_scroller_params(POST_data): order = (int(POST_data['order[0][column]']), POST_data['order[0][dir]']) return { 'draw' : int(POST_data['draw']), 'start' : int(POST_data['start']), 'length' : int(POST_data['length']), 'order' : order, 'filter' : POST_data['search[value]'] } # TODO restriction to >1 subentries for testing css – remove!!! #from django.db.models import Count @ajax_required @login_required def get_entries(request): if request.method == 'POST': errors_dict = dict() forms = collect_forms(request.session['forms'], errors_dict) # form should already be validated if it passed through send_form assert(not errors_dict) scroller_params = get_scroller_params(request.POST) with_lexical_units = request.GET.get('with_lexical_units') == 'true' exclude_status = request.GET.get('exclude_status') restrict_to_user = request.GET.get('restrict_to_user') has_unified_frame = request.GET.get('has_unified_frame') entries = get_filtered_objects(forms).filter(import_error=False) # TODO restrictions for testing – remove!!! #entries = entries.annotate(nsub=Count('subentries')).filter(nsub__gt=1) #entries = entries.filter(subentries__schemata__opinion__key__in=('vul', 'col')).filter(status__key__in=('(S) gotowe', '(S) sprawdzone')) #entries = entries.filter(subentries__schema_hooks__alternation=2) total = entries.count() if scroller_params['filter']: entries = entries.filter(name__startswith=scroller_params['filter']) local_frame_form = None if 'frame_form' in request.session: errors_dict = dict() local_frame_form = collect_forms(request.session['frame_form'], errors_dict) assert(not errors_dict) linked_ids = set() if request.session['show_linked_entries'] and not with_lexical_units: entries_linked = Entry.objects.filter(pk__in=( Entry.objects .filter(subentries__schema_hooks__argument_connections__schema_connections__subentry__entry__in=entries) .exclude(id__in=entries) )).distinct() entries = entries | entries_linked linked_ids = set(entries_linked.values_list('id', flat=True)) first_index, last_index = scroller_params['start'], scroller_params['start'] + scroller_params['length'] order_field, order_dir = scroller_params['order'] if order_field == 0: order_field = 'name' elif order_field == 1: order_field = 'status__key' elif order_field == 2: order_field = 'pos__tag' if order_dir == 'desc': order_field = '-' + order_field if restrict_to_user: # pre-filtering entries for performance reasons entries = entries.filter(lexical_units__frames__assignments__user=User.objects.get(username=restrict_to_user)) entries = ( entries .order_by(order_field) .select_related('status', 'pos') .prefetch_related(Prefetch("assignments", to_attr="_assignments")) ) if with_lexical_units: frameQueryset = Frame.objects.prefetch_related(Prefetch("assignments", to_attr="_assignments")) entries = entries.prefetch_related( Prefetch( "lexical_units", LexicalUnit.objects.prefetch_related( Prefetch( "frames", queryset=get_filtered_objects(local_frame_form, frameQueryset) if local_frame_form is not None else frameQueryset, to_attr="_frames", ) ) ) ) if exclude_status is not None: entries = entries.filter(lexical_units__frames__status__iexact=exclude_status) entries = entries.filter(lexical_units__frames__isnull=False) if has_unified_frame == 'true': entries = entries.filter(lexical_units__frames__slowal_frame_2_unified_frame__isnull=False) filtered = entries.count() status_names = STATUS() POS_names = POS() def iter_lexical_units(e): for lu in e.lexical_units.all(): lu._frame = lu._frames[0] if lu._frames and len(lu._frames) > 0 else None if lu._frame is None or not hasattr(lu._frame, 'slowal_frame_2_unified_frame'): continue else: yield lu result = { 'draw' : scroller_params['draw'], 'recordsTotal': total, 'recordsFiltered': filtered, 'data': [ { 'id' : e.id, 'lemma' : e.name, 'status' : status_names[e.status.key], 'POS' : POS_names[e.pos.tag], 'related' : e.id in linked_ids, 'assignee_username': e._assignments[0].user.username if e._assignments else None, **( { 'lexical_units': [ { 'pk': lu.pk, 'display': str(lu), 'assignee_username': ( lu._frame._assignments[0].user.username if lu._frame and lu._frame._assignments else None ), 'status': lu._frame.status if lu._frame else "", 'unified_frame_id': lu._frame.slowal_frame_2_unified_frame.unified_frame_id if lu._frame and hasattr(lu._frame, 'slowal_frame_2_unified_frame') else -1, } for lu in iter_lexical_units(e) ] } if with_lexical_units else {} ), } for e in entries[first_index:last_index] ], } return JsonResponse(result) return JsonResponse({}) def subentry2str(subentry): ret = subentry.entry.name if subentry.inherent_sie.name == 'true': ret += ' się' elems = [] if subentry.aspect: elems.append(subentry.aspect.name) if subentry.negativity: elems.append(subentry.negativity.name) if elems: ret += ' ({})'.format(', '.join(elems)) if subentry.predicativity.name == 'true': ret += ' pred.' return ret def position_prop2dict(prop): return { 'str' : prop.name, 'desc' : position_prop_description(prop.name), } if prop else { 'str' : '', 'desc' : '', } def get_phrase_desc(phrase, position, negativity, lang): return NaturalLanguageDescription.objects.get( phrase_str=phrase.text_rep, function=position.function, control=position.control, pred_control=position.pred_control, negativity=negativity, lang=lang).description def schema2dict(schema, negativity, lang): return { 'opinion' : SCHEMA_OPINION()[schema.opinion.key], 'opinion_key' : schema.opinion.key, 'id' : str(schema.id), 'positions' : [ { 'func' : position_prop2dict(p.function), 'control' : position_prop2dict(p.control), 'p_control' : position_prop2dict(p.pred_control), 'id' : '{}-{}'.format(schema.id, p.id), 'phrases' : [ { 'str' : str(pt), 'id' : '{}-{}-{}'.format(schema.id, p.id, pt.id), 'desc' : get_phrase_desc(pt, p, negativity, lang), } for pt in p.sorted_phrase_types() ], } for p in schema.sorted_positions() ], } def get_rel_pref_desc(pref): relation = pref.relation.key if relation == 'RELAT': desc = _('Realizacja tego argumentu w zdaniu powinna być powiązana jakąkolwiek relacją') else: desc = _('Realizacja tego argumentu w zdaniu powinna być powiązana relacją <i>{}</i>').format(RELATION()[relation]) return desc + ' ' + _('z realizacją argumentu <i>{}</i>.').format(pref.to) def make_ul(items): return '<ul>{}</ul>'.format(''.join(map('<li>{}</li>'.format, items))) def get_synset_def(synset): ret = [] if synset.definition: ret.append(_('definicja:') + make_ul([synset.definition])) #ret.append(_('jednostki leksykalne: ') + ', '.join(map(str, synset.lexical_units.all()))) hypernyms = list(synset.hypernyms.all()) if hypernyms: ret.append(_('hiperonimy:') + make_ul(map(str, hypernyms))) return ' '.join(ret) def get_prefs_list(argument): return sorted( ({ 'id' : p.pk, 'type' : p._meta.label, 'str' : str(p), 'info' : str(p.info), } for p in argument.predefined.all()), key=lambda x: x['str'] ) + sorted( ({ 'id' : s.pk, 'type' : s._meta.label, 'str' : str(s), # can be a new synset 'url' : None if s.id < 0 else 'http://plwordnet21.clarin-pl.eu/synset/{}'.format(s.id), 'info' : s.lexical_units.all()[0].gloss if s.id < 0 else get_synset_def(s), } for s in argument.synsets.all()), key=lambda x: x['str'] ) + sorted( ({ 'id' : r.pk, 'type' : r._meta.label, 'str' : str(r), 'info' : get_rel_pref_desc(r), } for r in argument.relations.all()), key=lambda x: x['str'] ) def frame2dict(frame, entry_meanings): return { 'opinion' : FRAME_OPINION()[frame.opinion.key], 'opinion_key' : frame.opinion.key, 'id' : frame.id, 'status' : frame.status, 'lexical_units' : [ { 'str' : lu.text_rep, 'id' : lu.id, 'entry_meaning' : lu in entry_meanings, 'definition' : lu.definition, 'gloss' : lu.gloss, 'url' : None if lu.luid is None else 'http://plwordnet21.clarin-pl.eu/lemma/{}/{}'.format(lu.base, lu.sense) } for lu in frame.lexical_units.all() ], 'arguments' : [ { 'str' : str(a), 'argument_id' : a.id, 'id' : '{}-{}'.format(frame.id, a.id), 'role' : '{}{}'.format(a.role.role.role.lower(), ' ' + a.role.attribute.attribute.lower() if a.role.attribute else ''), 'preferences' : get_prefs_list(a), } for a in sorted(frame.arguments.all(), key=lambda a: a.role.role.priority + (a.role.attribute.priority if a.role.attribute else 2)) ], } # returns two dicts: # (1) { # frame_id_1 : { # schema_id_1 : { [alt_1*, ..., alt_l] }, # schema_id_k : {...} # } # ... # frame_id_n : {...} # } # *alternation is a dict: { # key: extended argument id (frame_id-arg_id) # val: list of extended phrase ids (schema_id-position_id-phr_id) # (2) { # extended_arg_id_1 : { # alt_1 : { # extended_phr_id_1 : psedo_natural_language_phrase_1_1_1, # extended_phr_id_l : psedo_natural_language_phrase_1_1_l, # } # ... # alt_k : {...} # } # ... # extended_arg_idn : {...} # } def get_alternations(schemata, frames): # TODO czy alternacja może być podpięta do całej pozycji, bez konkretnej frazy? alternations = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(list)))) phrases = defaultdict(lambda: defaultdict(dict)) realisation_descriptions = defaultdict(lambda: defaultdict(lambda: defaultdict(dict))) for schema in schemata: for hook in schema.schema_hooks.all(): arg_conns = hook.argument_connections.all() assert (len(arg_conns) < 2) if (arg_conns): argument = arg_conns[0].argument frame = argument.frame if frame not in frames: continue phr_id = '{}-{}-{}'.format(schema.id, hook.position.id, hook.phrase_type.id) arg_id = '{}-{}'.format(frame.id, argument.id) alternations[frame.id][schema.id][hook.alternation][arg_id].append(phr_id) phrases[arg_id][hook.alternation - 1][phr_id] = hook.description alt_dict = defaultdict(lambda: defaultdict(list)) for frame_id, frame_schema_alternations in alternations.items(): for schema_id, schema_alternations in frame_schema_alternations.items(): for alt_no in sorted(schema_alternations.keys()): alt_dict[frame_id][schema_id].append(schema_alternations[alt_no]) realisation_descriptions[frame_id][schema_id][alt_no - 1] = RealisationDescription.objects.get(frame__id=frame_id, schema__id=schema_id, alternation=alt_no).description return alt_dict, phrases, realisation_descriptions def get_examples(entry): examples = [] for example in entry.examples.all(): frame_ids, argument_ids, lu_ids, schema_ids, phrases, phrases_syntax, positions = set(), set(), set(), set(), set(), set(), set() for connection in example.example_connections.all(): for argument in connection.arguments.all(): frame_ids.add(argument.frame.id) argument_ids.add('{}-{}'.format(argument.frame.id, argument.id)) if connection.lexical_unit: lu_ids.add(connection.lexical_unit.id) for hook in connection.schema_connections.all(): schema_ids.add(hook.schema.id); phrases.add('{}-{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id, hook.alternation - 1)) phrases_syntax.add('{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id)) positions.add('{}-{}'.format(hook.schema.id, hook.position.id)) examples.append({ 'id' : str(example.id), 'sentence' : example.sentence, 'source' : EXAMPLE_SOURCE()[example.source.key], 'opinion' : EXAMPLE_OPINION()[example.opinion.key], 'note' : example.note, 'frame_ids' : sorted(frame_ids), 'argument_ids' : sorted(argument_ids), 'lu_ids' : sorted(lu_ids), 'schema_ids' : sorted(schema_ids), 'phrases' : sorted(phrases), 'phrases_syntax' : sorted(phrases_syntax), 'positions' : sorted(positions), }) return sorted(examples, key=lambda x: x['sentence']) # [[POS1], [POS2, POS3]] # => # [ # [ # (<SchemaForm>, [], [('position', 'or', [[POS1]])]) # ], # [ # (<SchemaForm>, [], [('position', 'or', [[POS2]])]), # (<SchemaForm>, [], [('position', 'or', [[POS3]])]) # ] # ] def position_forms2schema_forms(forms): dummy_schema_form = make_form('schema', data={}) # validate the dummy to ensure access to cleaned_data assert(dummy_schema_form.is_valid()) return [ [(dummy_schema_form, [], [('position', 'or', [[posf]])]) for posf in posfs] for posfs in forms ] # [[ATR1, ATR2], [ATR3]] # => # [ # [ # (<SchemaForm>, [], [('position', 'or', [[(<PositionForm>, [], [('switch', 'or', [[ATR]])])]])]), # (<SchemaForm>, [], [('position', 'or', [[(<PositionForm>, [], [('switch', 'or', [[ATR]])])]])]) # ], # [ # (<SchemaForm>, [], [('position', 'or', [[(<PositionForm>, [], [('switch', 'or', [[ATR]])])]])]) # ] # ] def phrase_forms2schema_forms(forms): dummy_schema_form = make_form('schema', data={}) dummy_position_form = make_form('position', data={}) # validate the dummies to ensure access to cleaned_data assert(dummy_schema_form.is_valid()) assert(dummy_position_form.is_valid()) return [ [(dummy_schema_form, [], [('position', 'or', [[(dummy_position_form, [], [('switch', 'or', [[phrf]])])]])]) for phrf in phrfs] for phrfs in forms ] # [[ARG1, ARG2], [ARG3]] # => # [ # [ # (<FrameForm>, [], [('argument', 'or', [[ARG1]])]), # (<FrameForm>, [], [('argument', 'or', [[ARG2]])]) # ], # [ # (<FrameForm>, [], [('argument', 'or', [[ARG3]])]) # ] # ] def argument_forms2frame_forms(forms): dummy_frame_form = make_form('frame', data={}) # validate the dummy to ensure access to cleaned_data assert(dummy_frame_form.is_valid()) return [ [(dummy_frame_form, [], [('argument', 'or', [[argf]])]) for argf in argfs] for argfs in forms ] #TODO test (*) changes @ajax_required def get_entry(request): if request.method == 'POST': #TODO (*) #form = EntryForm(request.POST) eid = request.POST['entry'] #TODO (*) if eid.isdigit():# and form.is_valid(): eid = int(eid) # TODO check that Entry has no import errors entry = Entry.objects.get(id=eid) errors_dict = dict() #TODO (*) #entry_form, _, children_forms = collect_forms(request.POST['forms[]'], errors_dict) entry_form, _, children_forms = collect_forms(request.session['forms'], errors_dict) # form should already be validated if it passed through send_form assert(not errors_dict) # dont’ do schema/frame filtering for related entries apply_filters = not simplejson.loads(request.POST['no_filters']) filter_schemata = apply_filters and entry_form.cleaned_data['filter_schemata'] filter_frames = apply_filters and entry_form.cleaned_data['filter_frames'] lexical_unit = LexicalUnit.objects.get(pk=lu_id) if (lu_id := request.POST.get("lexical_unit_id")) else None if filter_schemata: schema_forms = [] # e.g. entry has schema that satisfies X & entry has schema that satisfies Y # => filtering schemata shows only schemata that contributed to the match # => leave schemata that satisfies X or satisfy Y schema_forms1 = [frms[2] for frms in children_forms if frms[0] == 'schema'] assert (len(schema_forms1) <= 1) if schema_forms1: schema_forms = schema_forms1[0] # e.g. entry has position that satisfies X & entry has position that satisfies Y # => entry has schema that has position that satisfies X # & entry has schema that has position that satisfies Y # => leave schemata that have position that satisfies X or have position that satisfies Y position_forms = [frms[2] for frms in children_forms if frms[0] == 'position'] assert (len(position_forms) <= 1) if position_forms: position_forms = position_forms[0] schema_forms += position_forms2schema_forms(position_forms) phrase_forms = [frms[2] for frms in children_forms if frms[0] == 'switch'] assert (len(phrase_forms) <= 1) if phrase_forms: phrase_forms = phrase_forms[0] schema_forms += phrase_forms2schema_forms(phrase_forms) filter_schemata = len(schema_forms) > 0 if filter_frames: frame_forms = [] frame_forms1 = [frms[2] for frms in children_forms if frms[0] == 'frame'] assert (len(frame_forms1) <= 1) if frame_forms1: frame_forms = frame_forms1[0] argument_forms = [frms[2] for frms in children_forms if frms[0] == 'argument'] assert (len(argument_forms) <= 1) if argument_forms: argument_forms = argument_forms[0] frame_forms += argument_forms2frame_forms(argument_forms) filter_frames = len(frame_forms) > 0 local_schema_filter_form = get_local_schema_filter_form(apply_filters, request) local_frame_filter_form = get_local_frame_filter_form(apply_filters, request) subentries = [] all_schema_objects = [] for subentry in entry.subentries.all(): schemata = [] schema_objects = subentry.schemata.all() # filter out schemata by schema properties if filter_schemata: schema_objects = get_filtered_objects2(schema_forms, schema_objects) if local_schema_filter_form: schema_objects = get_filtered_objects(local_schema_filter_form, schema_objects) for schema in schema_objects: schemata.append(schema2dict(schema, subentry.negativity, request.LANGUAGE_CODE)) if schemata: all_schema_objects += list(schema_objects) subentries.append({ 'str' : subentry2str(subentry), 'schemata' : schemata }) frame_objects = Frame.objects.filter(arguments__argument_connections__schema_connections__subentry__entry=entry).distinct() # filter out frames by frame properties if filter_frames: frame_objects = get_filtered_objects2(frame_forms, frame_objects) if lexical_unit: frame_objects = frame_objects.filter(lexical_units=lexical_unit) if local_frame_filter_form: frame_objects = get_filtered_objects(local_frame_filter_form, frame_objects) frames = [frame2dict(frame, entry.lexical_units.all()) for frame in frame_objects] alternations, realisation_phrases, realisation_descriptions = get_alternations(all_schema_objects, frame_objects) examples = get_examples(entry) unified_frame = None if lexical_unit and (unified_frame := UnifiedFrame.objects.all().for_lexical_unit(lexical_unit).first()): unified_frame = { 'pk': unified_frame.pk, 'status': unified_frame.status, 'assignee_username' : assignment.user.username if (assignment := unified_frame.assignments.first()) else None, } # https://docs.djangoproject.com/en/2.2/topics/http/sessions/#when-sessions-are-saved if [entry.name, entry.id] in request.session['last_visited']: request.session['last_visited'].remove([entry.name, entry.id]) request.session['last_visited'].insert(0, (entry.name, entry.id)) request.session['last_visited'] = request.session['last_visited'][:(MAX_LAST_VISITED + 1)] request.session.modified = True return JsonResponse({ 'subentries' : subentries, 'frames' : frames, 'alternations' : alternations, 'realisation_phrases' : realisation_phrases, 'realisation_descriptions' : realisation_descriptions, 'examples' : examples, 'unified_frame': unified_frame, 'last_visited' : request.session['last_visited'] }) return JsonResponse({}) def get_local_frame_filter_form(apply_filters, request): local_frame_form = None if apply_filters and 'frame_form' in request.session: errors_dict = dict() local_frame_form = collect_forms(request.session['frame_form'], errors_dict) assert (not errors_dict) return local_frame_form def get_local_schema_filter_form(apply_filters, request): local_schema_form = None if apply_filters and 'schema_form' in request.session: errors_dict = dict() local_schema_form = collect_forms(request.session['schema_form'], errors_dict) assert (not errors_dict) return local_schema_form ''' @ajax_required def filter_schemata(request): if request.method == 'POST': print(request.POST['forms[]']) errors_dict = dict() forms = collect_forms(request.POST['forms[]'], errors_dict) eid = request.POST['entry'] print(eid) print(forms) if errors_dict: return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) # TODO check that Entry has no import errors entry = Entry.objects.get(id=eid) schema_ids = [] for subentry in entry.subentries.all(): for schema in get_filtered_objects(forms, subentry.schemata.all()): schema_ids.append(schema.id) return JsonResponse({ 'success' : 1, 'schema_ids' : schema_ids }) return JsonResponse({}) ''' @ajax_required def change_show_reals_desc(request): if request.method == 'POST': val = simplejson.loads(request.POST['val']) request.session['show_reals_desc'] = val return JsonResponse({ 'success' : 1 }) return JsonResponse({}) @ajax_required def change_show_linked_entries(request): if request.method == 'POST': val = simplejson.loads(request.POST['val']) request.session['show_linked_entries'] = val return JsonResponse({ 'success' : 1 }) return JsonResponse({}) @ajax(method='get', encode_result=True) def ajax_plWN_context_lookup(request, term): results = [] # term = term.encode('utf8') if len(term) > 0: obj_results = LexicalUnit.objects.filter(base__startswith=term) results = get_ordered_lexical_units_bases(obj_results) return {'result': results} def get_ordered_lexical_units_bases(lexical_units_query): last_unit_base = '' lexical_unit_bases = [] ordered_lexical_units = lexical_units_query.order_by('base') for lexical_unit in ordered_lexical_units: if lexical_unit.base != last_unit_base: lexical_unit_bases.append(lexical_unit.base) last_unit_base = lexical_unit.base return lexical_unit_bases @ajax(method='get', encode_result=True) def ajax_predefined_preferences(request): predefined = [] for preference in PredefinedSelectionalPreference.objects.order_by('name'): if preference.members: members = [member.name for member in preference.members.generals.order_by('name')] members.extend([str(synset) for synset in preference.members.synsets.all()]) content = '%s: (%s)' % (preference.name, ', '.join(members)) else: content = '%s' % (preference.name) predefined.append({"id": preference.id, "content": content}) context = { 'predefined': predefined, } return context @ajax(method='get', encode_result=True) def ajax_roles(request): roles = [] for role in SemanticRole.objects.order_by('priority'): if role.role != 'Lemma': roles.append({"id": role.id, "role": role.role, "priority": role.priority, "color": role.color}) context = { 'roles': roles, } return context @ajax(method='get', encode_result=True) def ajax_role_attributes(request): roleAttributes = [] for roleAttribute in RoleAttribute.objects.order_by('priority'): roleAttributes.append({"id": roleAttribute.id, "attribute": roleAttribute.attribute, "priority": roleAttribute.priority, "gradient": roleAttribute.gradient}) context = { 'role_attributes': roleAttributes, } return context @ajax(method='get', encode_result=True) def ajax_role_sub_attributes(request): role_sub_attributes = [] for roleSubAttribute in RoleSubAttribute.objects.order_by('priority'): role_sub_attributes.append({"id": roleSubAttribute.id, "sub_attribute": roleSubAttribute.sub_attribute, "priority": roleSubAttribute.priority}) context = { 'role_sub_attributes': role_sub_attributes, } return context # @render('relations.json') @ajax(method='get', encode_result=True) def ajax_relations(request): relations = [{"id": relation.plwn_id, "content": relation.name} for relation in SelectivePreferenceRelations.objects.all()] context = { 'relations': relations, } return context @ajax(method='get', encode_result=True) def ajax_synsets(request, base, pos): if pos == '_': lexical_units = LexicalUnit.objects.filter(base=base).order_by('pos', 'base', 'sense') else: lexical_units = LexicalUnit.objects.filter(base=base, pos=pos).order_by('pos', 'base', 'sense') synsets = [] for representative in lexical_units: synset = [{"id": lu.id, "luid": lu.luid, "base": lu.base, "sense": lu.sense, "pos": lu.pos, "glossa": lu.definition} for lu in LexicalUnit.objects.filter(synset=representative.synset)] synsets.append({"id": representative.synset.id, "content": synset}) context = { 'synsets': synsets, } return context def lexical_units_without_empty_frames(obj_results): for lu in obj_results.all(): lu._frames = lu._frames[0] if lu._frames and len(lu._frames) > 0 else None if lu._frames is None: continue else: yield lu @ajax(method='get', encode_result=True) def ajax_free_slowal_frame_lookup(request, term): if len(term) > 0: obj_results = LexicalUnit.objects.filter(base__startswith=term)\ .filter(frames__assignments=None).order_by('base', 'sense') obj_results = obj_results.prefetch_related( Prefetch( "frames", to_attr="_frames", ) ) lexical_unit_str = [] for lexical_unit in lexical_units_without_empty_frames(obj_results): lexical_unit_str.append(str(lexical_unit)) return {'result': lexical_unit_str}