diff options
Diffstat (limited to 'chimere/forms.py')
| -rw-r--r-- | chimere/forms.py | 855 |
1 files changed, 855 insertions, 0 deletions
diff --git a/chimere/forms.py b/chimere/forms.py new file mode 100644 index 0000000..8b86df1 --- /dev/null +++ b/chimere/forms.py @@ -0,0 +1,855 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2008-2016 É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.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.urlresolvers import reverse +from django.db.models import Q +from django.forms.formsets import formset_factory +from django.utils.translation import ugettext as _ +from django.contrib.auth.models import User, Permission, ContentType +from django.core.mail import EmailMessage, BadHeaderError + +if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and \ + settings.CHIMERE_SEARCH_ENGINE: + from haystack.forms import SearchForm as HaystackSearchForm + +from chimere.models import Marker, Route, PropertyModel, Area,\ + News, Category, RouteFile, MultimediaFile, MultimediaType, \ + PictureFile, Importer, PropertyModelChoice, Page, IMPORTER_CHOICES, \ + get_areas_for_user, SubCategoryUserLimit, Polygon +from chimere.widgets import AreaField, PointField, TextareaWidget, \ + FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget,\ + TextareaAdminWidget, ImportFiltrWidget, ImporterChoicesWidget, RE_XAPI + +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 getStaffEmails(): + return [u.email for u in User.objects.filter( + is_superuser=True).exclude(email="").order_by('id')] + + +def getRelevantModeratorEmails(geo_object): + categories = list(geo_object.categories.all()) + # q = Q(is_staff=True) & ( + # Q(subcategory_limit_to__count=0) | + # Q(subcategory_limit_to__subcategory__in=categories)) + q1 = Q(is_staff=True) & ( + Q(subcategory_limit_to__subcategory__in=categories)) + qusers = list(User.objects.filter(q1).exclude(email="").all()) + q2 = Q(is_staff=True) + qusers += list(User.objects.filter(q2).exclude( + email="").exclude(pk__in=[ + sl.user.pk for sl in SubCategoryUserLimit.objects.all()]).all()) + users = [] + for user in qusers: + areas = get_areas_for_user(user) + if not areas: + users.append(user) + continue + contained = Q() + qs = geo_object.__class__.objects.filter(pk=geo_object.pk) + for area in areas: + if hasattr(geo_object, 'point'): + contained = contained | area.getIncludeMarker() + elif hasattr(geo_object, 'route'): + contained = contained | area.getIncludeRoute() + qs = qs.filter(contained) + if qs.count(): + users.append(user) + lst = [u.email for u in users] + return lst + + +def notifyStaff(subject, body, sender=None): + user_list = getStaffEmails() + notifyByEmail(subject, body, user_list, sender) + + +def notifyByEmail(subject, body, user_list, sender=None): + if not settings.EMAIL_HOST or not user_list: + return + if settings.PROJECT_NAME: + subject = u'[%s] %s' % (settings.PROJECT_NAME, subject) + 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(absolute_uri, 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: ") + named_url = 'admin:chimere_%s_change' % \ + geo_object.__class__.__name__.lower() + message += absolute_uri + reverse(named_url, args=(geo_object.pk,)) + message += u"\n\n--\nChimère" + + user_list = getStaffEmails() + getRelevantModeratorEmails(geo_object) + user_list = list(set(user_list)) + return notifyByEmail(subject, message, user_list) + + +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 SubCategoryAdminForm(forms.ModelForm): + ''' + Add a tinyMCE widget to fill description + ''' + description = forms.CharField(widget=FullTextareaWidget, required=False) + + +class PageAdminForm(forms.ModelForm): + """ + Main form for extra pages + """ + content = forms.CharField(widget=FullTextareaWidget) + + class Meta: + model = Page + + +class OSMForm(forms.Form): + """ + OSM export form + """ + username = forms.CharField(label=_("OSM user")) + password = forms.CharField(label=_(u"Password"), + widget=forms.PasswordInput(render_value=False)) + # API URL are hardcoded: the day the API change Chimère will need + # adaptations not only on this portion... + api = forms.ChoiceField( + label=_(u"API"), + choices=(('', '--'), + ('api06.dev.openstreetmap.org', + _(u"Test API - %s") % 'api06.dev.openstreetmap.org'), + ('api.openstreetmap.org/api', + _(u"Main API - %s") % 'api.openstreetmap.org/api'), + )) + + +class NewsAdminForm(forms.ModelForm): + """ + Main form for news + """ + content = forms.CharField(widget=TextareaAdminWidget) + + class Meta: + model = News + + +class ImporterAdminForm(forms.ModelForm): + filtr = forms.CharField(widget=ImportFiltrWidget, required=False) + importer_type = forms.ChoiceField( + widget=ImporterChoicesWidget, + choices=[('', '--')] + list(IMPORTER_CHOICES)) + default_description = forms.CharField(widget=TextareaAdminWidget, + required=False) + + class Meta: + model = Importer + widgets = { + 'source': forms.TextInput(attrs={'size': 80}), + 'filtr': forms.Textarea(attrs={'size': 80}), + } + + def clean(self): + ''' + Verify that only one type of source is provided + Verify that shapefiles are zipped + ''' + if self.cleaned_data.get('importer_type') == 'OSM' and \ + not self.cleaned_data.get('filtr'): + raise forms.ValidationError( + _(u"For OSM import you must be provide a filter. Select an " + u"area and node/way filter.")) + if self.cleaned_data.get('importer_type') == 'OSM' and \ + not RE_XAPI.match(self.cleaned_data.get('filtr')): + raise forms.ValidationError( + _(u"For OSM import you must be provide a filter. Select an " + u"area and node/way filter.")) + if self.cleaned_data.get('importer_type') == 'SHP' and \ + not self.cleaned_data.get('zipped'): + raise forms.ValidationError(_(u"Shapefiles must be provided in a " + u"zipped archive.")) + if self.cleaned_data.get('importer_type') not in ('XSLT', 'XXLT') and \ + self.cleaned_data.get('source') and \ + self.cleaned_data.get('source_file'): + raise forms.ValidationError(_(u"You have to set \"source\" or " + u"\"source file\" but not both.")) + if not self.cleaned_data.get('source') and \ + not self.cleaned_data.get('source_file') and \ + self.cleaned_data.get('importer_type') != 'OSM': + raise forms.ValidationError(_(u"You have to set \"source\" or " + u"\"source file\".")) + return self.cleaned_data + + +class CategoryAdminForm(forms.ModelForm): + """ + Main form for categories + """ + description = forms.CharField(widget=TextareaAdminWidget, required=False) + + class Media: + js = list(settings.JQUERY_JS_URLS) + [ + '%schimere/js/menu-sort.js' % settings.STATIC_URL, + ] + css = { + 'all': ('chimere/css/admin.css',) + } + + class Meta: + model = Category + + +def get_properties(queryset): + # As we have dynamic fields, it's cleaner to make the class dynamic too + fields = {} + for prop in queryset: + key = "property_%d_%d" % (prop.order, prop.id) + if prop.type == 'C': + choices = PropertyModelChoice.objects.filter(propertymodel=prop, + available=True + ).order_by('value') + fields[key] = forms.ChoiceField( + label=prop.name, choices=[('', '--')] + + [(choice.pk, unicode(choice)) for choice in choices], + required=False) + elif prop.type == 'A': + widget = PropertyModel.TYPE_WIDGET[prop.type] + widget = widget(slug=prop.slug) + fields[key] = forms.CharField(label=prop.name, widget=widget, + required=False) + else: + widget = PropertyModel.TYPE_WIDGET[prop.type] + fields[key] = forms.CharField( + label=prop.name, widget=widget, + required=False) + return fields + + +class MarkerAdminFormBase(forms.ModelForm): + """ + Main form for marker + """ + is_admin = True + name = forms.CharField(_(u"Name"), required=True) + description = forms.CharField(widget=TextareaAdminWidget, required=False) + _PROPERTY_FILTERS = {} + + class Meta: + model = Marker + + @classmethod + def _set_cls_fields(cls): + fields = get_properties( + PropertyModel.objects.filter(**cls._PROPERTY_FILTERS).all()) + for key in fields: + print(key) + setattr(cls, key, fields[key]) + + def _set_fields(self): + fields = get_properties( + PropertyModel.objects.filter(**self._PROPERTY_FILTERS).all()) + for key in fields: + self.fields[key] = fields[key] + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage properties + """ + area_name = None + if 'area_name' in keys: + area_name = keys.pop('area_name') + querys = PropertyModel.getAvailable(area_name=area_name) + self.pms = [] + for query in querys: + self.pms += [pm for pm in query.all()] + if 'instance' in keys and keys['instance']: + instance = keys['instance'] + property_dct = {} + for pm in self.pms: + 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 + subcategories = keys.pop('subcategories') \ + if 'subcategories' in keys else [] + super(MarkerAdminFormBase, self).__init__(*args, **keys) + self._set_fields() + if settings.CHIMERE_DAYS_BEFORE_EVENT: + self.fields['start_date'].widget = DatePickerWidget() + self.fields['end_date'].widget = DatePickerWidget() + if self.is_admin: + return + if subcategories: + self.fields['categories'].choices = subcategories + # auto select if there is only one category + choices = list(self.fields['categories'].choices) + self.fields['categories'].choices = choices + self.fields['categories'].label = "" + if (len(choices) == 1): + self.fields['categories'].widget = forms.MultipleHiddenInput() + choices = list(self.fields['categories'].choices) + if type(choices[0][1]) in (list, tuple): + # hierarchical choices + self.fields['categories'].label = u"{} / {}".format( + choices[0][0], choices[0][1][0][1]) + self.fields['categories'].initial = \ + [self.fields['categories'].choices[0][1][0][0]] + else: + self.fields['categories'].label = u"{}".format( + choices[0][1]) + self.fields['categories'].initial = \ + [self.fields['categories'].choices[0][0]] + if not settings.CHIMERE_SEARCH_ENGINE and 'keywords' in self.fields: + self.fields.pop('keywords') + if not settings.CHIMERE_DAYS_BEFORE_EVENT: + self.fields.pop('start_date') + self.fields.pop('end_date') + # not a clean way to filter properties... + # to do: change creation process + pms = [pm.getNamedId() for pm in self.pms] + for k in self.fields.keys(): + if not k.startswith('property_') or \ + k in pms: + continue + self.fields.pop(k) + + def clean(self): + ''' + Verify that a start date is provided when an end date is set + Verify the mandatory properties (to be check manualy because it depends + on the checked categories) + ''' + start_date = self.cleaned_data.get('start_date') + end_date = self.cleaned_data.get('end_date') + if end_date and not 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'] + if end_date and start_date and start_date > end_date: + msg = _(u"End date can't be before start date") + self._errors["end_date"] = self.error_class([msg]) + raise forms.ValidationError(msg) + for pm in self.pms: + if not pm.mandatory or self.cleaned_data[pm.getNamedId()]: + continue + pm_cats = pm.subcategories.all() + if not pm_cats or \ + [submited_cat for submited_cat in + self.cleaned_data['categories'] + if submited_cat in pm_cats]: + msg = _(u"This field is mandatory for the selected categories") + self._errors[pm.getNamedId()] = self.error_class([msg]) + # raise forms.ValidationError() + return self.cleaned_data + + def save(self, *args, **keys): + """ + Custom save method in order to manage associated properties + """ + new_marker = super(MarkerAdminFormBase, self).save(*args, **keys) + if 'status' not in self.cleaned_data and not new_marker.status: + 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 MarkerAdminForm(MarkerAdminFormBase): + pass + + +class MarkerBaseForm(MarkerAdminFormBase): + # in public form only visible fields are displayed + _PROPERTY_FILTERS = {'available': True} + + +EXCLUDED_FIELDS = ['status'] +if not settings.CHIMERE_SEARCH_ENGINE: + EXCLUDED_FIELDS.append('keywords') + + +class MarkerForm(MarkerBaseForm): + """ + Form for the edit page + """ + is_admin = False + ref_pk = forms.IntegerField(label=u" ", widget=forms.HiddenInput(), + required=False) + description = forms.CharField(widget=TextareaWidget, required=False) + keywords = forms.CharField(widget=TextareaWidget, max_length=200, + required=False) + + class Meta: + model = Marker + exclude = EXCLUDED_FIELDS + widgets = { + 'description': TextareaWidget(), + } + + +class RouteAdminForm(forms.ModelForm): + """ + Main form for route + """ + is_admin = True + name = forms.CharField(_(u"Name"), required=True) + + class Meta: + model = Route + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage properties + """ + area_name = None + if 'area_name' in keys: + area_name = keys.pop('area_name') + querys = PropertyModel.getAvailable(area_name=area_name) + self.pms = [] + for query in querys: + self.pms += [pm for pm in query.all()] + 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 + subcategories = keys.pop('subcategories') \ + if 'subcategories' in keys else [] + super(RouteAdminForm, self).__init__(*args, **keys) + if self.is_admin: + return + if not settings.CHIMERE_SEARCH_ENGINE and 'keywords' in self.fields: + self.fields.pop('keywords') + if settings.CHIMERE_DAYS_BEFORE_EVENT: + self.fields['start_date'].widget = DatePickerWidget() + self.fields['end_date'].widget = DatePickerWidget() + self.fields['categories'].choices = [] + if subcategories: + self.fields['categories'].choices = subcategories + # not a clean way to filter properties... + # to do: change creation process + pms = [pm.getNamedId() for pm in self.pms] + for k in self.fields.keys(): + if not k.startswith('property_') or \ + k in pms: + continue + self.fields.pop(k) + + def save(self, *args, **keys): + """ + Custom save method in order to manage associated properties + """ + new_route = super(RouteAdminForm, self).save(*args, **keys) + if 'status' not in self.cleaned_data and not new_route.status: + new_route.status = 'S' + new_route.save() + return new_route + + +class RouteForm(RouteAdminForm): + """ + Form for the edit page + """ + is_admin = False + description = forms.CharField(widget=TextareaWidget, required=False) + point = forms.CharField(label=" ", required=False, + widget=forms.HiddenInput) + associated_file_id = forms.CharField( + label=" ", required=False, widget=forms.HiddenInput) + keywords = forms.CharField(widget=TextareaWidget, max_length=200, + required=False) + + class Meta: + model = Route + exclude = EXCLUDED_FIELDS + + def __init__(self, *args, **kwargs): + if kwargs.get('instance'): + try: + marker = Marker.objects.get(route=kwargs['instance']) + kwargs['initial'] = { + 'point': marker.point, + 'description': marker.description} + property_dct = {} + for pm in PropertyModel.objects.filter(available=True): + property = marker.getProperty(pm) + if property: + property_dct[pm.getNamedId()] = property.value + if 'initial' in kwargs: + kwargs['initial'].update(property_dct) + else: + kwargs['initial'] = property_dct + except: + pass + super(RouteForm, self).__init__(*args, **kwargs) + + def save(self, *args, **keys): + """ + Custom save method in order to manage associated marker and file + """ + new_route = super(RouteForm, self).save(*args, **keys) + if new_route.status == 'S': + new_route.has_associated_marker = True + new_route.save() + # associate a route file + if 'associated_file_id' in self.cleaned_data and \ + self.cleaned_data['associated_file_id']: + file_pk = int(self.cleaned_data['associated_file_id']) + new_route.associated_file = RouteFile.objects.get(pk=file_pk) + new_route.save() + # change the associated marker (if available) + q_new_marker = Marker.objects.filter(route=new_route) + if not q_new_marker.count(): + return new_route + new_marker = q_new_marker.all()[0] + # save description + if self.cleaned_data['description']: + new_marker.description = self.cleaned_data['description'] + 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 PolygonAdminForm(MarkerAdminForm): + """ + Main form for polygon + """ + class Meta: + model = Polygon + + +class PolygonForm(PolygonAdminForm): + """ + Form for the edit page + """ + is_admin = False + description = forms.CharField(widget=TextareaWidget, required=False) + + class Meta: + model = Polygon + exclude = EXCLUDED_FIELDS + + +class BaseFileForm(forms.ModelForm): + id = forms.IntegerField(label=u"", widget=forms.HiddenInput(), + required=False) + + def __init__(self, *args, **kwargs): + if not hasattr(self, '_related_name') or not self._related_name: + raise ImproperlyConfigured + super(BaseFileForm, self).__init__(*args, **kwargs) + self.fields.pop('marker') + self.fields.pop('polygon') + + def save(self, associated_item): + if not hasattr(self, 'cleaned_data') or not self.cleaned_data: + return + instance = None + if self.cleaned_data.get('id'): + try: + instance = self._meta.model.objects.get( + pk=self.cleaned_data['id']) + except: + pass + self.cleaned_data.pop('id') + if self.cleaned_data.get('DELETE'): + if instance: + instance.delete() + return + self.cleaned_data.pop('DELETE') + if type(associated_item) == Marker: + self.cleaned_data['marker'] = associated_item + if type(associated_item) == Polygon: + self.cleaned_data['polygon'] = associated_item + if instance: + for k in self.cleaned_data: + setattr(instance, k, self.cleaned_data[k]) + instance.save() + else: + instance = self._meta.model.objects.create(**self.cleaned_data) + + +class MultimediaFileAdminForm(forms.ModelForm): + class Meta: + model = MultimediaFile + + class Media: + js = list(settings.JQUERY_JS_URLS) + [ + '%schimere/js/menu-sort.js' % settings.STATIC_URL, + ] + + def __init__(self, *args, **kwargs): + super(MultimediaFileAdminForm, self).__init__(*args, **kwargs) + self.fields['multimedia_type'].widget.choices = \ + MultimediaType.get_tuples() + + +class MultimediaFileForm(BaseFileForm): + """ + Form for a multimedia file + """ + _related_name = 'multimedia_files' + + class Meta: + model = MultimediaFile + exclude = ('order',) + + def __init__(self, *args, **kwargs): + super(MultimediaFileForm, self).__init__(*args, **kwargs) + self.fields['multimedia_type'].widget.choices = \ + MultimediaType.get_tuples() + # this can be auto detect + self.fields['multimedia_type'].required = False + +MultimediaFileFormSet = formset_factory(MultimediaFileForm, can_delete=True) + + +class PictureFileAdminForm(forms.ModelForm): + class Meta: + model = PictureFile + + class Media: + js = list(settings.JQUERY_JS_URLS) + [ + '%schimere/js/menu-sort.js' % settings.STATIC_URL, + ] + + +class PictureFileForm(BaseFileForm): + """ + Form for a picture file + """ + _related_name = 'pictures' + + class Meta: + model = PictureFile + exclude = ('order', 'height', 'width', 'thumbnailfile', + 'thumbnailfile_height', 'thumbnailfile_width') + +PictureFileFormSet = formset_factory(PictureFileForm, can_delete=True) + + +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())) + welcome_message = forms.CharField(widget=TextareaAdminWidget, + required=False) + + class Meta: + model = Area + + def __init__(self, *args, **keys): + """ + Custom initialization method in order to manage area + """ + if args: + vals = args[0] + for k in ('upper_left_lat', 'upper_left_lon', + 'lower_right_lat', 'lower_right_lon'): + v = vals.get(k) + try: + v = float(v) + except ValueError: + v = None + if not v: + args[0][k] = None + 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 clean(self): + ''' + Verify that the area is not empty + ''' + if not self.cleaned_data.get('upper_left_lat') \ + and not self.cleaned_data.get('upper_left_lon') \ + and not self.cleaned_data.get('lower_right_lat') \ + and not self.cleaned_data.get('lower_right_lon') \ + and not self.cleaned_data.get('area'): + msg = _(u"No area selected.") + raise forms.ValidationError(msg) + if self.cleaned_data.get('order'): + q = Area.objects.filter(order=self.cleaned_data.get('order')) + if self.instance: + q = q.exclude(pk=self.instance.pk) + if q.count(): + msg = _(u"The area \"%s\" has the same order, you need to" + u" choose another one.") % unicode(q.all()[0]) + raise forms.ValidationError(msg) + return self.cleaned_data + + 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 + +CHIMERE_ROUTING_TRANSPORT = [] +ROUTING_INIT = None +if hasattr(settings, 'CHIMERE_ROUTING_TRANSPORT'): + CHIMERE_ROUTING_TRANSPORT = [ + (idx, _(lbl)) for idx, lbl in settings.CHIMERE_ROUTING_TRANSPORT] + if CHIMERE_ROUTING_TRANSPORT: + ROUTING_INIT = CHIMERE_ROUTING_TRANSPORT[0][0] + + +class RoutingForm(forms.Form): + transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, + choices=CHIMERE_ROUTING_TRANSPORT, + initial=ROUTING_INIT) + start = forms.CharField(label=_(u"Start"), widget=NominatimWidget) + end = forms.CharField(label=_(u"Finish"), widget=NominatimWidget) + speed = forms.ChoiceField(label=_(u"Speed"), choices=[], + required=False, widget=forms.RadioSelect) + + def __init__(self, *args, **kwargs): + super(RoutingForm, self).__init__(*args, **kwargs) + if not settings.CHIMERE_ROUTING_SPEEDS: + self.fields.pop('speed') + self.fields['speed'].widget.choices = [] + for transport in settings.CHIMERE_ROUTING_SPEEDS: + for speed, lbl in settings.CHIMERE_ROUTING_SPEEDS[transport]: + self.fields['speed'].widget.choices.append( + ("%s_%d" % (transport, speed), _(lbl))) + +SearchForm = None + + +if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \ + and settings.CHIMERE_SEARCH_ENGINE: + class SearchForm(HaystackSearchForm): + pass |
