specialised_fields.py 5.46 KB
from django import forms

from django.db.models import Q

from syntax.models_phrase import PhraseTypeModel

from semantics.models import (
    Frame, SemanticRole, RoleAttribute,
    PredefinedSelectionalPreference,
    Synset,
    RelationalSelectionalPreference,
    SelectionalPreferenceRelation,
)

from .generic_fields import (
    RadiosLayoutField,
    SingleRegexFilter,
    ModelChoiceFilter,
    ComboFilter,
)

from .query_managers import (
    QueryManager,
    DUMMY_LOOKUP,
)

from entries.polish_strings import PHRASE_TYPE

# TODO what else, apart from comprepnp, can’t be a lex?
class PhraseTypeFilter(ModelChoiceFilter):
    
    def __init__(self, lex=False, **kwargs):
        super().__init__(
            label=('Typ frazeologizmu' if lex else 'Typ frazy'),
            queryset=(PhraseTypeModel.objects.exclude(name__in=('lex', 'comprepnp')) if lex else PhraseTypeModel.objects.all()),
            key='name',
            #lookup='phrase_types__main_type',
            # this field is not used for filtering, only for choosing subform type
            lookup=DUMMY_LOOKUP,
            # we will want to identify the selected phrase type by name later
            to_field_name='name',
            empty_label='wybierz',
            **kwargs,
        )
    def label_from_instance(self, obj):
        pt = obj.name
        return '{} ({})'.format(pt, PHRASE_TYPE.get(pt, '...'))

class ArgumentFilter(ComboFilter):
    
    def __init__(self):
        super().__init__(
            label='Rola semantyczna',
            inner_class=Frame,
            outer_lookup='subentries__schema_hooks__argument_connections__argument__frame__in',
            fields=[
                ModelChoiceFilter(
                    label='Rola',
                    empty_label='Rola',
                    queryset=SemanticRole.objects.all(),
                    key='role',
                    lookup='argument__role__role',
                ),
                ModelChoiceFilter(
                    label='Atrybut roli',
                    empty_label='Atrybut roli',
                    queryset=RoleAttribute.objects.all(),
                    key='attribute',
                    lookup='argument__role__attribute',
                ),
            ],
            negation_field=True,
        )

class PredefinedPreferenceFilter(ComboFilter):
    def __init__(self):
        super().__init__(
            label='Predefiniowane',
            inner_class=Frame,
            outer_lookup='subentries__schema_hooks__argument_connections__argument__frame__in',
            fields=[
                ModelChoiceFilter(
                    label='Predefiniowane',
                    empty_label='Predefiniowane',
                    queryset=PredefinedSelectionalPreference.objects.all(),
                    key='key',
                    lookup='argument__predefined',
                ),
            ],
            negation_field=True,
        )

class RelationalPreferenceFilter(ComboFilter):
    def __init__(self):
        super().__init__(
            label='Relacja',
            inner_class=Frame,
            outer_lookup='subentries__schema_hooks__argument_connections__argument__frame__in',
            fields=[
                ModelChoiceFilter(
                    label='Relacja',
                    empty_label='Relacja',
                    queryset=SelectionalPreferenceRelation.objects.all(),
                    key='key',
                    lookup='argument__relations__relation',
                ),
                ModelChoiceFilter(
                    label='Do: rola',
                    empty_label='Do: rola',
                    queryset=SemanticRole.objects.all(),
                    key='role',
                    lookup='argument__relations__to__role__role',
                ),
                ModelChoiceFilter(
                    label='Do: atrybut',
                    empty_label='Do: atrybut',
                    queryset=RoleAttribute.objects.all(),
                    key='attribute',
                    lookup='argument__relations__to__role__attribute',
                ),
            ]
        )

'''
class SynsetPreferenceFilter(ComboFilter):
    
    def __init__(self):
        super().__init__(
            label='Synset',
            inner_class=Frame,
            outer_lookup='subentries__schema_hooks__argument_connections__argument__frame__in',
            fields=[
                SingleRegexFilter(
                    label='Synset',
                    lookup='argument__synsets__lexical_units__text_rep',
                ),
            ]
        )
'''
    
# TODO implementation without internal QueryManager subclass?
# TODO possibly refactor and check
class PhraseoFilter(forms.ChoiceField, RadiosLayoutField):
    
    class PhraseoQueryManager(QueryManager):
        def __init__(self):
            super().__init__(None, None)
        # Assumes this filter is used on either Entry or Schema and uses the
        # fact that both have the same related name for Subentry
        def _make_queries(self, _, value, op):
            if value == '1':
                return [Q(subentries__schemata__phraseologic=True)]
            if value == '0':
                return [~Q(subentries__schemata__phraseologic=True)]
            return []
    
    def __init__(self):
        super().__init__(
            label='Frazeologia',
            choices=(('2', 'dowolnie'), ('1', 'zawiera'), ('0', 'nie zawiera')),
            initial='2',
            required=False,
        )
        self.query_manager = PhraseoFilter.PhraseoQueryManager()