diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-18 17:49:57 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-18 17:51:30 +0200 |
commit | 7d2aa560ba859ebb593d34b062bf1faf09c8724c (patch) | |
tree | 4136673563f802d6de992512e3c4adde86ef2a4e /ishtar_common/forms.py | |
parent | 615457617e65019e0ce39b585f4eeb41b17ba61a (diff) | |
download | Ishtar-7d2aa560ba859ebb593d34b062bf1faf09c8724c.tar.bz2 Ishtar-7d2aa560ba859ebb593d34b062bf1faf09c8724c.zip |
Djangoization - Major refactoring (step 1)
Diffstat (limited to 'ishtar_common/forms.py')
-rw-r--r-- | ishtar_common/forms.py | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py new file mode 100644 index 000000000..62f51fa08 --- /dev/null +++ b/ishtar_common/forms.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +""" +Forms definition +""" +import datetime +import re +from itertools import groupby + +from django import forms +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.sites.models import Site +from django.core.urlresolvers import reverse +from django.core import validators +from django.core.exceptions import ObjectDoesNotExist +from django.core.mail import send_mail +from django.db.models import Max +from django.forms.formsets import formset_factory, BaseFormSet, \ + DELETION_FIELD_NAME +from django.shortcuts import render_to_response +from django.template import Context, RequestContext, loader +from django.utils import formats +from django.utils.functional import lazy +from django.utils.translation import ugettext_lazy as _ + +# from formwizard.forms import NamedUrlSessionFormWizard + +class NamedUrlSessionFormWizard(forms.Form): + def __init__(self, form_list, condition_list={}, url_name=''): + self.form_list = dict(form_list) + self.condition_list = condition_list + self.url_name = url_name + super(NamedUrlSessionFormWizard, self).__init__(self) + + + def rindex(self, idx): + return self.url_name.rindex(idx) + +import models +import widgets + +reverse_lazy = lazy(reverse, unicode) + +regexp_name = re.compile(r'^[\w\- ]+$', re.UNICODE) +name_validator = validators.RegexValidator(regexp_name, +_(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid') + +class FloatField(forms.FloatField): + """ + Allow the use of comma for separating float fields + """ + def clean(self, value): + if value: + value = value.replace(',', '.').replace('%', '') + return super(FloatField, self).clean(value) + +class FinalForm(forms.Form): + final = True + form_label = _(u"Confirm") + +class FormSet(BaseFormSet): + def check_duplicate(self, key_names, error_msg=""): + """Check for duplicate items in the formset""" + if any(self.errors): + return + if not error_msg: + error_msg = _("There are identical items.") + items = [] + for i in range(0, self.total_form_count()): + form = self.forms[i] + if not form.is_valid(): + continue + item = [key_name in form.cleaned_data and form.cleaned_data[key_name] + for key_name in key_names] + if not [v for v in item if v]: + continue + if item in items: + raise forms.ValidationError, error_msg + items.append(item) + + def add_fields(self, form, index): + super(FormSet, self).add_fields(form, index) + form.fields[DELETION_FIELD_NAME].label = '' + form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget() + +''' +class SearchWizard(NamedUrlSessionFormWizard): + model = None + + def get_wizard_name(self): + """ + As the class name can interfere when reused, use the url_name + """ + return self.url_name + + def get_template(self, request, storage): + templates = ['search.html'] + return templates + +def get_now(): + format = formats.get_format('DATE_INPUT_FORMATS')[0] + value = datetime.datetime.now().strftime(format) + return value + +class DeletionWizard(Wizard): + def get_formated_datas(self, forms): + datas = super(DeletionWizard, self).get_formated_datas(forms) + self.current_obj = None + for form in forms: + if not hasattr(form, "cleaned_data"): + continue + for key in form.cleaned_data: + if key == 'pk': + model = form.associated_models['pk'] + self.current_obj = model.objects.get(pk=form.cleaned_data['pk']) + if not self.current_obj: + return datas + res = {} + for field in self.model._meta.fields + self.model._meta.many_to_many: + if field.name not in self.fields: + continue + value = getattr(self.current_obj, field.name) + if not value: + continue + if hasattr(value, 'all'): + value = ", ".join([unicode(item) for item in value.all()]) + if not value: + continue + else: + value = unicode(value) + res[field.name] = (field.verbose_name, value, '') + if not datas and self.fields: + datas = [['', []]] + for field in self.fields: + if field in res: + datas[0][1].append(res[field]) + return datas + + def done(self, request, storage, form_list, **kwargs): + obj = self.get_current_object(request, storage) + obj.delete() + return render_to_response('wizard_delete_done.html', {}, + context_instance=RequestContext(request)) + +class ClosingDateFormSelection(forms.Form): + form_label = _("Closing date") + end_date = forms.DateField(label=_(u"Closing date"), + widget=widgets.JQueryDate) + +class ClosingWizard(Wizard): + # "close" an item + # to be define in the overloaded class + model = None + fields = [] + + def get_formated_datas(self, forms): + datas = super(ClosingWizard, self).get_formated_datas(forms) + self.current_obj = None + for form in forms: + if not hasattr(form, "cleaned_data"): + continue + for key in form.cleaned_data: + if key == 'pk': + model = form.associated_models['pk'] + self.current_obj = model.objects.get( + pk=form.cleaned_data['pk']) + if not self.current_obj: + return datas + res = {} + for field in self.model._meta.fields + self.model._meta.many_to_many: + if field.name not in self.fields: + continue + value = getattr(self.current_obj, field.name) + if not value: + continue + if hasattr(value, 'all'): + value = ", ".join([unicode(item) for item in value.all()]) + if not value: + continue + else: + value = unicode(value) + res[field.name] = (field.verbose_name, value, '') + if not datas and self.fields: + datas = [['', []]] + for field in self.fields: + if field in res: + datas[0][1].append(res[field]) + return datas + + def done(self, request, storage, form_list, **kwargs): + obj = self.get_current_object(request, storage) + for form in form_list: + if form.is_valid(): + if 'end_date' in form.cleaned_data and hasattr(obj, 'end_date'): + obj.end_date = form.cleaned_data['end_date'] + obj.save() + return render_to_response('wizard_closing_done.html', {}, + context_instance=RequestContext(request)) + +def get_form_selection(class_name, label, key, model, base_form, get_url, + not_selected_error=_(u"You should select an item."), new=False, + new_message=_(u"Add a new item")): + """ + Generate a class selection form + class_name -- name of the class + label -- label of the form + key -- model, + base_form -- base form to select + get_url -- url to get the item + not_selected_error -- message displayed when no item is selected + new -- can add new items + new_message -- message of link to add new items + """ + attrs = {'_main_key':key, + '_not_selected_error':not_selected_error, + 'form_label':label, + 'associated_models':{key:model}, + 'currents':{key:model},} + attrs[key] = forms.IntegerField(label="", required=False, + validators=[models.valid_id(model)], + widget=widgets.JQueryJqGrid(reverse_lazy(get_url), base_form(), model, + new=new, new_message=new_message)) + def clean(self): + cleaned_data = self.cleaned_data + if self._main_key not in cleaned_data \ + or not cleaned_data[self._main_key]: + raise forms.ValidationError(self._not_selected_error) + return cleaned_data + attrs['clean'] = clean + return type(class_name, (forms.Form,), attrs) +''' |