diff options
Diffstat (limited to 'chimere/forms.py')
-rw-r--r-- | chimere/forms.py | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/chimere/forms.py b/chimere/forms.py new file mode 100644 index 0000000..3691408 --- /dev/null +++ b/chimere/forms.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2008-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 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +""" +Forms +""" +from django import forms +from django.contrib.gis.db import models +from django.utils.translation import ugettext as _ +from django.contrib.auth.models import User, Permission, ContentType +from django.contrib.admin.widgets import AdminDateWidget +from django.core.mail import EmailMessage, BadHeaderError + +from chimere import settings + +from chimere.models import Marker, Route, PropertyModel, Property, Area,\ + News, Category, SubCategory, RouteFile +from chimere.widgets import AreaField, PointField, TextareaWidget + +from datetime import timedelta, datetime, tzinfo + +ZERO = timedelta(0) + +class UTC(tzinfo): + """UTC time zone""" + + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return settings.TIME_ZONE + + def dst(self, dt): + return ZERO + +def notifyStaff(subject, body, sender=None): + if not settings.EMAIL_HOST: + return + if settings.PROJECT_NAME: + subject = u'[%s] %s' % (settings.PROJECT_NAME, subject) + user_list = [u.email for u in + User.objects.filter(is_staff=True).exclude(email="").order_by('id')] + headers = {} + if sender: + headers['Reply-To'] = sender + email = EmailMessage(subject, body, user_list[0], user_list, + headers=headers) + try: + email.send() + except BadHeaderError: + return False + return True + +def notifySubmission(geo_object): + category = u" - ".join([unicode(cat) for cat in geo_object.categories.all()]) + subject = u'%s %s' % (_(u"New submission for"), category) + message = _(u'The new item "%s" has been submited in the category: ') % \ + geo_object.name + category + message += "\n\n" + _(u"To valid, precise or unvalid this item: ") + message += settings.BASE_URL + 'admin' + message += u"\n\n--\nChimère" + return notifyStaff(subject, message) + +class ContactForm(forms.Form): + """ + Main form for categories + """ + email = forms.EmailField(label=_("Email (optional)"), required=False) + content = forms.CharField(label=_("Object"), widget=forms.Textarea) + +class NewsAdminForm(forms.ModelForm): + """ + Main form for news + """ + content = forms.CharField(widget=TextareaWidget) + class Meta: + model = News + +class CategoryAdminForm(forms.ModelForm): + """ + Main form for categories + """ + description = forms.CharField(widget=TextareaWidget, required=False) + class Meta: + model = Category + +class MarkerAdminForm(forms.ModelForm): + """ + Main form for marker + """ + # declare properties + for property in PropertyModel.objects.filter(available=True): + exec('property_%d_%d = forms.CharField(label="%s", widget=%s, '\ + 'required=False)' % (property.order, property.id, property.name, + PropertyModel.TYPE_WIDGET[property.type])) + class Meta: + model = Marker + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage properties + """ + if 'instance' in keys and keys['instance']: + instance = keys['instance'] + property_dct = {} + for pm in PropertyModel.objects.filter(available=True): + property = instance.getProperty(pm) + if property: + property_dct[pm.getNamedId()] = property.value + if 'initial' in keys: + keys['initial'].update(property_dct) + else: + keys['initial'] = property_dct + super(MarkerAdminForm, self).__init__(*args, **keys) + if settings.DAYS_BEFORE_EVENT: + self.fields['start_date'].widget = AdminDateWidget() + self.fields['end_date'].widget = AdminDateWidget() + + def clean(self): + ''' + Verify that a start date is provided when an end date is set + ''' + if not settings.DAYS_BEFORE_EVENT: + return self.cleaned_data + if self.cleaned_data['end_date'] and \ + not self.cleaned_data['start_date']: + msg = _(u"End date has been set with no start date") + self._errors["end_date"] = self.error_class([msg]) + del self.cleaned_data['end_date'] + return self.cleaned_data + + def save(self, *args, **keys): + """ + Custom save method in order to manage associated properties + """ + new_marker = super(MarkerAdminForm, self).save(*args, **keys) + if 'status' not in self.cleaned_data: + new_marker.status = 'S' + if new_marker.status == 'A': + tz = UTC() + new_marker.available_date = datetime.replace(datetime.utcnow(), + tzinfo=tz) + new_marker.save() + # save properties + properties = dict([(k.split('_')[-1], self.cleaned_data[k]) \ + for k in self.cleaned_data.keys() if k.startswith('property_')]) + new_marker.saveProperties(properties) + return new_marker + +class MarkerForm(MarkerAdminForm): + """ + Form for the edit page + """ + class Meta: + model = Marker + exclude = ('status',) + +class RouteAdminForm(forms.ModelForm): + """ + Main form for route + """ + class Meta: + model = Route + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage properties + """ + if 'instance' in keys and keys['instance']: + instance = keys['instance'] + property_dct = {} + for pm in PropertyModel.objects.filter(available=True): + property = instance.getProperty(pm) + if property: + property_dct[pm.getNamedId()] = property.value + if 'initial' in keys: + keys['initial'].update(property_dct) + else: + keys['initial'] = property_dct + super(RouteAdminForm, self).__init__(*args, **keys) + if settings.DAYS_BEFORE_EVENT: + self.fields['start_date'].widget = AdminDateWidget() + self.fields['end_date'].widget = AdminDateWidget() + + def save(self, *args, **keys): + """ + Custom save method in order to manage status + """ + new_route = super(RouteAdminForm, self).save(*args, **keys) + if 'status' not in self.cleaned_data: + new_route.status = 'S' + new_route.save() + return new_route + +class RouteForm(RouteAdminForm): + """ + Form for the edit page + """ + picture = forms.ImageField(label=_("Image"), required=False) + point = forms.CharField(label=" ", required=False, widget=forms.HiddenInput) + associated_file_id = forms.CharField(label=" ", required=False, + widget=forms.HiddenInput) + class Meta: + model = Route + exclude = ('status',) + # marker properties + for property in PropertyModel.objects.filter(available=True): + exec('property_%d_%d = forms.CharField(label="%s", widget=%s, '\ + 'required=False)' % (property.order, property.id, property.name, + PropertyModel.TYPE_WIDGET[property.type])) + + def save(self, *args, **keys): + """ + Custom save method in order to manage associated marker and file + """ + new_route = super(RouteForm, self).save(*args, **keys) + # associate a route file + if 'associated_file_id' in self.cleaned_data and \ + self.cleaned_data['associated_file_id']: + #try: + file_pk = int(self.cleaned_data['associated_file_id']) + new_route.associated_file = RouteFile.objects.get(pk=file_pk) + new_route.save() + #except: + #pass + marker_fields = [f.attname for f in Marker._meta.fields] + marker_dct = dict([(k, self.cleaned_data[k]) for k in self.cleaned_data + if k in marker_fields]) + marker_dct['route'] = new_route + if 'status' not in marker_dct: + marker_dct['status'] = "S" + categories = [] + new_marker = Marker(**marker_dct) + new_marker.save() + for category in self.cleaned_data['categories']: + new_marker.categories.add(category) + new_marker.save() + # save properties + properties = dict([(k.split('_')[-1], self.cleaned_data[k]) \ + for k in self.cleaned_data.keys() if k.startswith('property_')]) + new_marker.saveProperties(properties) + return new_route + +class FileForm(forms.Form): + raw_file = forms.FileField(label=_(u"File")) + + def clean_raw_file(self): + data = self.cleaned_data['raw_file'] + if '.' not in data.name or \ + data.name.split('.')[-1].lower() not in ('kml', 'gpx'): + raise forms.ValidationError(_(u"Bad file format: this must be a "\ + u"GPX or KML file")) + return data + +class FullFileForm(FileForm): + name = forms.CharField(label=_(u"Name"), max_length=150) + def __init__(self, *args, **kwargs): + super(FullFileForm, self).__init__(*args, **kwargs) + self.fields.keyOrder = ['name', 'raw_file'] + +class AreaAdminForm(forms.ModelForm): + """ + Admin page to create an area + """ + area = AreaField(label=_("Area"), fields=(PointField(), PointField())) + class Meta: + model = Area + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage area + """ + if 'instance' in keys and keys['instance']: + instance = keys['instance'] + dct = {'area':(instance.upper_left_corner, + instance.lower_right_corner)} + if 'initial' in keys: + keys['initial'].update(dct) + else: + keys['initial'] = dct + super(AreaAdminForm, self).__init__(*args, **keys) + + def save(self, *args, **keys): + """ + Custom save method in order to manage area + """ + new_area = super(AreaAdminForm, self).save(*args, **keys) + area = self.cleaned_data['area'] + new_area.upper_left_corner = 'POINT(%s %s)' % (area[0][0], area[0][1]) + new_area.lower_right_corner = 'POINT(%s %s)' % (area[1][0], + area[1][1]) + content_type = ContentType.objects.get(app_label="chimere", + model="area") + if new_area.urn: + mnemo = 'change_area_' + new_area.urn + perm = Permission.objects.filter(codename=mnemo) + if not perm: + perm = Permission(name='Can change ' + new_area.name, + content_type_id=content_type.id, codename=mnemo) + perm.save() + else: + if 'urn' in self.initial: + mnemo = 'change_area_' + self.initial['urn'] + perm = Permission.objects.filter(codename=mnemo) + if perm: + perm[0].delete() + return new_area + +class AreaForm(AreaAdminForm): + """ + Form for the edit page + """ + class Meta: + model = Area + |