forms.py 14 KB
#-*- coding:utf-8 -*-

from django.forms import *
from django.contrib.auth.models import User
from common.forms import hidden_id
from dictionary.models import Lexeme, LexemeInflectionPattern, Ending, \
  InflectionCharacteristic, Pattern, PatternType, Classification, \
  ClassificationValue, Vocabulary, CrossReference, \
  Qualifier, QualifierExclusionClass, Variant

def disable_field(field):
  if type(field.widget) in (Textarea, TextInput):
    field.widget.attrs['readonly'] = 'readonly'
  else:
    field.widget.attrs['disabled'] = 'disabled'

# ze StackOverflow, http://stackoverflow.com/questions/3737116/
class QualifiersField(ModelMultipleChoiceField):
  def __init__(self, **kwargs):
    super(QualifiersField, self).__init__(Qualifier.objects.none(), **kwargs)
    self.to_field_name = None #?

  def set_qualifiers(self, vocabularies, qualified=None):
    qualifiers = Qualifier.objects.filter(
      vocabulary__in=vocabularies, deleted=False)
    if not qualifiers:
      disable_field(self)
      return
    self.queryset = queryset = qualifiers.order_by('vocabulary', 'label')
    if qualified and qualified.pk:
      initial_qualifiers = qualified.qualifiers.filter(
        vocabulary__in=vocabularies)
      self.initial = initial_qualifiers

    queryset = queryset.select_related()
    vocabulary = None
    self.choices = []
    q_list = []
    for qualifier in queryset:
      if not vocabulary:
        vocabulary = qualifier.vocabulary
      if vocabulary != qualifier.vocabulary:
        self.choices.append((vocabulary.id, q_list))
        vocabulary = qualifier.vocabulary
        q_list = []
      q_list.append((qualifier.pk, qualifier.label))
    self.choices.append((vocabulary.id, q_list))

class QualifierField(ModelChoiceField):
  def __init__(self, **kwargs):
    qualifiers = Qualifier.objects.filter(deleted=False).order_by(
      'vocabulary', 'label')
    super(QualifierField, self).__init__(qualifiers, **kwargs)
    if not qualifiers: # oznacza że w systemie nie ma żadnych kwalifikatorów
      disable_field(self)
      return

    qualifiers = qualifiers.select_related()
    vocabulary = None
    self.choices = []
    q_list = []
    for qualifier in qualifiers:
      if not vocabulary:
        vocabulary = qualifier.vocabulary
      if vocabulary != qualifier.vocabulary:
        self.choices.append((vocabulary.id, q_list))
        vocabulary = qualifier.vocabulary
        q_list = []
      q_list.append((qualifier.pk, qualifier.label))
    self.choices.append((vocabulary.id, q_list))

class LexemeEditForm(ModelForm):
  vocabularies = ModelMultipleChoiceField(
    queryset=Vocabulary.objects.none(), required=False)
  qualifiers = QualifiersField(required=False)
  new_owner = ModelChoiceField(
    queryset=Vocabulary.objects.none(), required=False)

  def __init__(self,  vocabularies, rw_vocabularies, all_rw_vocabularies,
               editable=True, containing=None, **kwargs):
    super(LexemeEditForm, self).__init__(**kwargs)
    instance = getattr(self, 'instance', None)
    self.fields['entry'].required = True
    self.fields['new_owner'].queryset = all_rw_vocabularies
    if vocabularies is not None:
      self.fields['vocabularies'].queryset = vocabularies
      self.fields['vocabularies'].initial = containing
      owner_choices = all_rw_vocabularies.values_list('pk', 'id')
      self.fields['new_owner'].choices = owner_choices
      if instance and instance.id:
        self.fields['new_owner'].initial = instance.owner_vocabulary
      if vocabularies.count() == 0:
        disable_field(self.fields['vocabularies'])
      self.fields['qualifiers'].set_qualifiers(rw_vocabularies, self.instance)
    if not editable:
      if instance and instance.id:
        for name, field in self.fields.iteritems():
          if name not in ('qualifiers', 'vocabularies'):
            disable_field(field)

  def clean_comment(self):
    data = self.cleaned_data['comment']
    return data.replace('\r', '')

  class Meta:
    model = Lexeme
    fields = (
      'part_of_speech',
      'entry',
      'entry_suffix',
      'status',
      'gloss',
      'comment',
    )
    widgets = {
      'comment': Textarea(attrs={'cols': 40, 'rows': 5}),
      'entry_suffix': TextInput(attrs={'size': 5}),
      'gloss': TextInput(attrs={'size': 40})
    }

class LIPEditForm(ModelForm):
  pattern_name = CharField(widget=TextInput(
    attrs={'class': 'pattern', 'size': '10'}), label=u'Wzór')
  qualifiers = QualifiersField(
    required=False, label=u'Kwal.',
    widget = SelectMultiple(attrs={'class':'lip-qualifiers'}))

  def __init__(self, part_of_speech, rw_vocabularies, editable=True, index=None,
               **kwargs):
    super(LIPEditForm, self).__init__(**kwargs)
    ic_choices = InflectionCharacteristic.objects.filter(
      part_of_speech=part_of_speech).values_list('pk', 'entry')
    self.fields['inflection_characteristic'].choices = ic_choices
    instance = getattr(self, 'instance', None)
    self.fields['qualifiers'].set_qualifiers(rw_vocabularies, instance)
    if instance and instance.id:
      self.fields['pattern_name'].initial = instance.pattern.name
      if not editable:
        for name, field in self.fields.iteritems():
          if name != 'qualifiers':
            disable_field(field)
    self.index = index

  def clean_pattern_name(self):
    cleaned_data = self.cleaned_data
    try:
      pattern = Pattern.objects.get(name=cleaned_data['pattern_name'])
    except Pattern.DoesNotExist:
      raise ValidationError(u'Niepoprawna nazwa wzoru.')
    ic = cleaned_data['inflection_characteristic']
    if pattern.type.lexical_class != ic.part_of_speech.lexical_class:
      raise ValidationError(u'Wzór nie pasuje do części mowy.')
    cleaned_data['pattern'] = pattern
    return cleaned_data['pattern_name']

  def save(self, *args, **kwargs):
    lip = self.instance
    lip.pattern = self.cleaned_data['pattern']
    if self.index:
      lip.index = self.index
    super(LIPEditForm, self).save(*args, **kwargs)
    lip.save()
    return lip

  class Meta:
    model = LexemeInflectionPattern
    fields = ['inflection_characteristic']
    widgets = {
      'inflection_characteristic': Select(
        attrs={'class': 'inflection-characteristic'}),
    }

class ClassificationForm(Form):
  values = TypedMultipleChoiceField(
    choices=[], empty_value=None, coerce=int,
    widget = SelectMultiple(attrs={'class': 'classification-values'}))

  def __init__(self, classification, editable=True, values=None,
               **kwargs):
    super(ClassificationForm, self).__init__(**kwargs)
    self.fields['values'].label = classification.name
    self.fields['values'].choices = classification.make_choices()
    if values:
      self.fields['values'].initial = [value.pk for value in values]
    if not editable:
      for _name, field in self.fields.iteritems():
        disable_field(field)

class AddClassificationForm(ModelForm):
  det = hidden_id('classification_form')

  class Meta:
    model = Classification

class AddClassificationValueForm(ModelForm):
  det = hidden_id('value_form')

  def __init__(self, classification=None, **kwargs):
    super(AddClassificationValueForm, self).__init__(**kwargs)
    if classification is not None:
      parent_choices = [('', u'<brak>')] + classification.make_choices()
      self.fields['parent_node'].choices = parent_choices
      self.fields['classification'].initial = classification.pk

  class Meta:
    model = ClassificationValue
    fields = ['label', 'parent_node', 'classification']
    widgets = {
      'classification': HiddenInput(),
    }

class AddExclusionClassForm(ModelForm):
  det = hidden_id('add_exclusion_class')

  def __init__(self, vocabulary=None, **kwargs):
    super(AddExclusionClassForm, self).__init__(**kwargs)
    self.fields['vocabulary'].initial = vocabulary

  class Meta:
    model = QualifierExclusionClass
    widgets = {
      'vocabulary': HiddenInput(),
    }

class ExclusionClassForm(Form):
  det = hidden_id('remove_exclusion_class')
  ec = ModelChoiceField(
    queryset=QualifierExclusionClass.objects.all(), label=u'') # dziura

  def __init__(self, queryset=None, **kwargs):
    super(ExclusionClassForm, self).__init__(**kwargs)
    if queryset:
      self.fields['ec'].queryset = queryset

class AddQualifierForm(ModelForm):
  det = hidden_id('add_qualifier')

  def __init__(self, vocabulary=None, **kwargs):
    super(AddQualifierForm, self).__init__(**kwargs)
    self.fields['vocabulary'].initial = vocabulary
    if vocabulary:
      self.fields['exclusion_class'].queryset = (QualifierExclusionClass.objects
        .filter(vocabulary=vocabulary).distinct())

  def clean(self):
    cleaned_data = self.cleaned_data
    ec = cleaned_data['exclusion_class']
    if ec:
      ec_vocab = ec.vocabulary
      if ec_vocab and ec_vocab != cleaned_data['vocabulary']:
        raise ValidationError(u'Klasa wykluczania niezgodna ze słownikiem.')
    return cleaned_data

  class Meta:
    model = Qualifier
    fields = ['label', 'exclusion_class', 'vocabulary']
    widgets = {
      'vocabulary': HiddenInput(),
    }

class ChangeClassForm(ModelForm):
  def __init__(self, **kwargs):
    super(ChangeClassForm, self).__init__(**kwargs)
    exclusion_classes = (
      self.instance.vocabulary.qualifierexclusionclass_set.all())
    self.fields['exclusion_class'].queryset = exclusion_classes

  def clean(self):
    ec = self.cleaned_data['exclusion_class']
    q = self.instance
    if ec:
      ec_qualifiers = ec.qualifier_set.all()
      if Lexeme.objects.filter(deleted=False, qualifiers=q).filter(
           qualifiers__in=ec_qualifiers):
        raise ValidationError(u'Kolizja w klasie wykluczania')
      if LexemeInflectionPattern.objects.filter(
           deleted=False, qualifiers=q).filter(qualifiers__in=ec_qualifiers):
        raise ValidationError(u'Kolizja w klasie wykluczania')
      if Ending.objects.filter(qualifiers=q).filter(
           qualifiers__in=ec_qualifiers):
        raise ValidationError(u'Kolizja w klasie wykluczania')
    return self.cleaned_data

  class Meta:
    model = Qualifier
    fields = ['exclusion_class']

class CrossReferenceForm(ModelForm):
  def __init__(self, lexeme=None, pos=None, **kwargs):
    super(CrossReferenceForm, self).__init__(**kwargs)
    if lexeme is not None:
      crtypes = lexeme.part_of_speech.crtype_to.all()
      type_choices = crtypes.values_list('pk', 'desc')
      self.fields['type'].widget.choices = type_choices
      self.fields['from_lexeme'].initial = lexeme.pk

  def clean(self):
    cleaned_data = self.cleaned_data
    from_lexeme = cleaned_data.get('from_lexeme')
    to_lexeme = cleaned_data.get('to_lexeme')
    cr_type = cleaned_data.get('type')
    if from_lexeme and to_lexeme and cr_type:
      from_pos = from_lexeme.part_of_speech
      to_pos = to_lexeme.part_of_speech
      if cr_type.from_pos != from_pos or cr_type.to_pos != to_pos:
        raise ValidationError(u'Nieprawidłowa część mowy w odsyłaczu.')
    return cleaned_data

  class Meta:
    model = CrossReference
    fields = ['type', 'from_lexeme', 'to_lexeme']
    widgets = {
      'type': Select(),
      'from_lexeme': HiddenInput(),
      'to_lexeme': TextInput(attrs={'size': 8}),
    }

class VocabularyForm(Form):
  det = hidden_id('vocabulary_form')
  vocabulary = ModelChoiceField(
    label=u"dodaj słownik", queryset=Vocabulary.objects.none())
  classification = ModelChoiceField(
    widget=HiddenInput(), queryset=Classification.objects.all())

  def __init__(self, queryset, classification=None, **kwargs):
    super(VocabularyForm, self).__init__(**kwargs)
    self.fields['vocabulary'].queryset = queryset
    if classification:
      self.fields['classification'].initial = classification

class PatternEditForm(ModelForm):
  def __init__(self, editable=True, **kwargs):
    super(PatternEditForm, self).__init__(**kwargs)
    if not editable:
      instance = getattr(self, 'instance', None)
      if instance and instance.id:
        for _name, field in self.fields.iteritems():
          disable_field(field)

  class Meta:
    model = Pattern
    fields = ('name', 'example', 'basic_form_ending', 'status', 'comment')

class PatternTypeForm(ModelForm):
  def __init__(self, editable=True, **kwargs):
    super(PatternTypeForm, self).__init__(**kwargs)
    if not editable:
      instance = getattr(self, 'instance', None)
      if instance and instance.id:
        for _name, field in self.fields.iteritems():
          disable_field(field)

  class Meta:
    model = PatternType
    fields = ('lexical_class', 'entry')

class QualifierForm(Form):
  qualifiers = QualifiersField(
    required=False, label=u'Kwalifikatory',
    widget = SelectMultiple(attrs={'class':'qualifiers'}))

  def __init__(self, rw_vocabularies, qualified=None, editable=True,
               **kwargs):
    super(QualifierForm, self).__init__(**kwargs)
    self.fields['qualifiers'].set_qualifiers(rw_vocabularies, qualified)
    if not editable:
      disable_field(self.fields['qualifiers'])

class UserFilterForm(Form):
  user = ModelChoiceField(
    queryset=User.objects.order_by('username'), label=u'Użytkownik')

class TimeFromForm(Form):
  time_from = DateField(input_formats=['%d.%m.%Y'], label=u'Od',
                        widget=DateInput(attrs={'class': 'datepicker'}))

class TimeToForm(Form):
  time_to = DateField(input_formats=['%d.%m.%Y'], label=u'Do',
                      widget=DateInput(attrs={'class': 'datepicker'}))

class ExportForm(Form):
  vocabs = ModelMultipleChoiceField(
    queryset=Vocabulary.objects.all(), label=u'słowniki')
  antivocabs = ModelMultipleChoiceField(
    queryset=Vocabulary.objects.all(), label=u'antysłowniki', required=False)
  variant = ModelChoiceField(queryset=Variant.objects.all(), label=u'wariant')
  refl = BooleanField(label=u'tagi z "refl"', required=False)
  #excluding_qualifiers = QualifiersField(
  #  required=False, label=u'kwal. wykluczające')

  def __init__(self, **kwargs):
    super(ExportForm, self).__init__(**kwargs)
    #self.fields['excluding_qualifiers'].set_qualifiers(Vocabulary.objects.all())

class MagicQualifierForm(Form):
  qualifier = QualifierField(label=u'kwal. leksemu')
  regex = CharField(label=u'wzorzec tagu', required=False)