#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2008-2010 Étienne Loks # 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 . # 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.main.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory from chimere.main.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 associeted 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 each property for propertymodel in PropertyModel.objects.filter(available=True): properties = Property.objects.filter(marker=new_marker, propertymodel=propertymodel) # new property if not properties: new_property = Property.objects.create(marker=new_marker, propertymodel=propertymodel, value=self.cleaned_data['property_%d_%d' % ( propertymodel.order, propertymodel.id)]) new_property.save() else: # in case of multiple edition as the same time delete arbitrary # the others if len(properties) > 1: for property in properties[1:]: property.delete() property = properties[0] property.value = self.cleaned_data['property_%d_%d' % ( propertymodel.order, propertymodel.id)] property.save() 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 """ """ # 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 = 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 associeted properties """ new_marker = super(RouteAdminForm, self).save(*args, **keys) if 'status' not in self.cleaned_data: new_marker.status = 'S' new_marker.save() """ # save each property for propertymodel in PropertyModel.objects.filter(available=True): properties = Property.objects.filter(marker=new_marker, propertymodel=propertymodel) # new property if not properties: new_property = Property.objects.create(marker=new_marker, propertymodel=propertymodel, value=self.cleaned_data['property_%d_%d' % ( propertymodel.order, propertymodel.id)]) new_property.save() else: # in case of multiple edition as the same time delete arbitrary # the others if len(properties) > 1: for property in properties[1:]: property.delete() property = properties[0] property.value = self.cleaned_data['property_%d_%d' % ( propertymodel.order, propertymodel.id)] property.save()""" return new_marker class RouteForm(RouteAdminForm): """ Form for the edit page """ class Meta: model = Route exclude = ('status',) 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="main", 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