summaryrefslogtreecommitdiff
path: root/chimere/forms.py
diff options
context:
space:
mode:
Diffstat (limited to 'chimere/forms.py')
-rw-r--r--chimere/forms.py331
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
+