import itertools from django import forms from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from AKModel.models import AK, AKOwner class AKForm(forms.ModelForm): required_css_class = 'required' class Meta: model = AK fields = ['name', 'short_name', 'link', 'owners', 'description', 'category', 'reso', 'present', 'requirements', 'conflicts', 'prerequisites', 'notes', 'event' ] widgets = { 'requirements': forms.CheckboxSelectMultiple, 'event': forms.HiddenInput, } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Use better multiple select input for owners, conflicts and prerequisites if "owners" in self.fields: self.fields["owners"].widget.attrs = {'class': 'chosen-select'} self.fields["conflicts"].widget.attrs = {'class': 'chosen-select'} self.fields["prerequisites"].widget.attrs = {'class': 'chosen-select'} help_tags_addition = _('Separate multiple tags with semicolon') # Add text fields for tags self.fields["tags_raw"] = forms.CharField( required=False, label=AK.tags.field.verbose_name, help_text=f"{AK.tags.field.help_text} ({help_tags_addition})") @staticmethod def _clean_duration(duration): # Handle different duration formats (h:mm and decimal comma instead of point) if ":" in duration: h, m = duration.split(":") duration = int(h) + int(m) / 60 if "," in str(duration): duration = float(duration.replace(",", ".")) try: float(duration) except ValueError: raise ValidationError( _('"%(duration)s" is not a valid duration'), code='invalid', params={'duration': duration}, ) return duration def clean(self): cleaned_data = super().clean() # Generate short name if not given short_name = self.cleaned_data["short_name"] if len(short_name) == 0: short_name = self.cleaned_data['name'] short_name = short_name.partition(':')[0] short_name = short_name.partition(' - ')[0] short_name = short_name.partition(' (')[0] for i in itertools.count(1): if not AK.objects.filter(short_name=short_name, event=self.cleaned_data["event"]).exists(): break print(short_name) digits = len(str(i)) print(digits) short_name = '{}-{}'.format(short_name[:-(digits + 1)], i) print(short_name) cleaned_data["short_name"] = short_name[:AK._meta.get_field('short_name').max_length] # Get tag names from raw tags cleaned_data["tag_names"] = [name.strip().lower() for name in cleaned_data["tags_raw"].split(";")] # Get durations from raw durations field if "durations" in cleaned_data: cleaned_data["durations"] = [self._clean_duration(d) for d in self.cleaned_data["durations"].split()] return cleaned_data class AKSubmissionForm(AKForm): class Meta(AKForm.Meta): exclude = ['link'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add field for durations self.fields["durations"] = forms.CharField( widget=forms.Textarea, label=_("Duration(s)"), help_text=_( "Enter at least one planned duration (in hours). If your AK should have multiple slots, use multiple lines") ) class AKEditForm(AKForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add existing tags to tag raw field self.fields["tags_raw"].initial = "; ".join(str(tag) for tag in self.instance.tags.all()) class AKWishForm(AKSubmissionForm): class Meta(AKForm.Meta): exclude = ['owners', 'link'] class AKOwnerForm(forms.ModelForm): required_css_class = 'required' class Meta: model = AKOwner fields = ['name', 'institution', 'link']