diff options
| -rw-r--r-- | chimere/forms.py | 18 | ||||
| -rw-r--r-- | chimere/locale/fr/LC_MESSAGES/django.po | 256 | ||||
| -rw-r--r-- | chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py | 241 | ||||
| -rw-r--r-- | chimere/models.py | 23 | ||||
| -rw-r--r-- | chimere/templates/chimere/edit.html | 31 | ||||
| -rw-r--r-- | chimere/views.py | 4 | ||||
| -rw-r--r-- | debian/control | 3 | ||||
| -rw-r--r-- | docs/install.rst | 4 | ||||
| -rw-r--r-- | docs/upgrade.rst | 5 | ||||
| -rw-r--r-- | requirements.txt | 1 |
10 files changed, 455 insertions, 131 deletions
diff --git a/chimere/forms.py b/chimere/forms.py index e3486c0..d877a22 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -124,10 +124,11 @@ class MarkerAdminFormBase(forms.ModelForm): """ Custom initialization method in order to manage properties """ + self.pms = [pm for pm in PropertyModel.objects.filter(available=True)] if 'instance' in keys and keys['instance']: instance = keys['instance'] property_dct = {} - for pm in PropertyModel.objects.filter(available=True): + for pm in self.pms: property = instance.getProperty(pm) if property: property_dct[pm.getNamedId()] = property.value @@ -147,6 +148,8 @@ class MarkerAdminFormBase(forms.ModelForm): 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) ''' if not settings.CHIMERE_DAYS_BEFORE_EVENT: return self.cleaned_data @@ -155,6 +158,19 @@ class MarkerAdminFormBase(forms.ModelForm): 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'] + + for pm in self.pms: + if not pm.mandatory or self.cleaned_data[pm.getNamedId()]: + continue + pm_cats = pm.subcategories.all() + print self.cleaned_data['categories'] + print pm_cats + 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): diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index 5d4a250..4462ff1 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,18 +7,18 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-20 21:03+0200\n" +"POT-Creation-Date: 2012-08-20 21:17+0200\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks <etienne.loks@peacefrogs.net>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:8 models.py:492 +#: __init__.py:8 models.py:502 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: __init__.py:9 models.py:541 +#: __init__.py:9 models.py:551 msgid "Picture files" msgstr "Fichiers d'image" @@ -107,357 +107,361 @@ msgstr "Courriel (optionnel) " msgid "Object" msgstr "Objet" -#: forms.py:155 +#: forms.py:158 msgid "End date has been set with no start date" msgstr "Une date de fin a été donnée sans date de début" -#: forms.py:369 +#: forms.py:171 +msgid "This field is mandatory for the selected categories" +msgstr "Ce champ est obligatoire pour les catégories sélectionnées" + +#: forms.py:385 msgid "File" msgstr "Fichier" -#: forms.py:375 +#: forms.py:391 msgid "Bad file format: this must be a GPX or KML file" msgstr "Mauvais format de fichier : KML et GPX sont supportés" -#: forms.py:380 models.py:48 models.py:101 models.py:122 models.py:135 -#: models.py:149 models.py:232 models.py:439 models.py:482 models.py:526 -#: models.py:557 models.py:794 models.py:806 models.py:891 +#: forms.py:396 models.py:49 models.py:102 models.py:123 models.py:136 +#: models.py:150 models.py:233 models.py:449 models.py:492 models.py:536 +#: models.py:567 models.py:804 models.py:816 models.py:901 #: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 msgid "Name" msgstr "Nom" -#: forms.py:389 models.py:843 +#: forms.py:405 models.py:853 msgid "Area" msgstr "Zone" -#: models.py:49 models.py:123 models.py:150 models.py:243 models.py:443 -#: models.py:812 models.py:893 +#: models.py:50 models.py:124 models.py:151 models.py:244 models.py:453 +#: models.py:822 models.py:903 msgid "Available" msgstr "Disponible" -#: models.py:50 +#: models.py:51 models.py:912 msgid "Date" msgstr "Date" -#: models.py:56 models.py:57 +#: models.py:57 models.py:58 msgid "News" msgstr "Nouvelle" -#: models.py:62 +#: models.py:63 msgid "Parameters" msgstr "Paramètres" -#: models.py:66 +#: models.py:67 msgid "TinyUrl" msgstr "Mini-url" -#: models.py:105 models.py:112 models.py:152 +#: models.py:106 models.py:113 models.py:153 msgid "Color theme" msgstr "Thème de couleur" -#: models.py:110 +#: models.py:111 msgid "Code" msgstr "Code" -#: models.py:111 models.py:124 models.py:154 models.py:484 models.py:533 -#: models.py:811 models.py:880 models.py:892 +#: models.py:112 models.py:125 models.py:155 models.py:494 models.py:543 +#: models.py:821 models.py:890 models.py:902 msgid "Order" msgstr "Ordre" -#: models.py:117 +#: models.py:118 msgid "Color" msgstr "Couleur" -#: models.py:130 models.py:148 templates/chimere/main_map.html:13 +#: models.py:131 models.py:149 templates/chimere/main_map.html:13 msgid "Category" msgstr "Catégorie" -#: models.py:136 models.py:435 models.py:527 models.py:622 +#: models.py:137 models.py:445 models.py:537 models.py:632 msgid "Image" msgstr "Image" -#: models.py:138 models.py:529 models.py:624 +#: models.py:139 models.py:539 models.py:634 msgid "Height" msgstr "Hauteur" -#: models.py:139 models.py:530 models.py:625 +#: models.py:140 models.py:540 models.py:635 msgid "Width" msgstr "Largeur" -#: models.py:143 models.py:151 +#: models.py:144 models.py:152 msgid "Icon" msgstr "Icône" -#: models.py:155 +#: models.py:156 msgid "Marker" msgstr "Point d'intérêt" -#: models.py:156 models.py:618 models.py:633 +#: models.py:157 models.py:628 models.py:643 #: templates/chimere/edit_route.html:27 msgid "Route" msgstr "Trajet" -#: models.py:157 +#: models.py:158 msgid "Both" msgstr "Mixte" -#: models.py:158 +#: models.py:159 msgid "Item type" msgstr "Type d'élément" -#: models.py:163 +#: models.py:164 msgid "Sub-category" msgstr "Sous-catégorie" -#: models.py:164 +#: models.py:165 msgid "Sub-categories" msgstr "Sous-catégories" -#: models.py:210 +#: models.py:211 msgid "Importer type" msgstr "Type d'import" -#: models.py:213 models.py:254 +#: models.py:214 models.py:255 msgid "Source" msgstr "Source" -#: models.py:215 +#: models.py:216 msgid "Filter" msgstr "Filtre" -#: models.py:218 +#: models.py:219 msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:219 +#: models.py:220 msgid "State" msgstr "État" -#: models.py:221 +#: models.py:222 msgid "SRID" msgstr "SRID" -#: models.py:222 +#: models.py:223 msgid "Zipped file" msgstr "Fichier zippé" -#: models.py:225 +#: models.py:226 msgid "Importer" msgstr "Import" -#: models.py:234 +#: models.py:235 msgid "Submitter session key" msgstr "Clé de session du demandeur" -#: models.py:236 +#: models.py:237 msgid "Submitter name or nickname" msgstr "Nom ou pseudo du demandeur" -#: models.py:238 +#: models.py:239 msgid "Submitter email" msgstr "Courriel du demandeur" -#: models.py:240 +#: models.py:241 msgid "Submitter comment" msgstr "Commentaire du demandeur" -#: models.py:242 +#: models.py:243 msgid "Submited" msgstr "Soumis" -#: models.py:244 +#: models.py:245 msgid "Modified" msgstr "Modifié" -#: models.py:245 +#: models.py:246 msgid "Disabled" msgstr "Désactivé" -#: models.py:246 +#: models.py:247 msgid "Imported" msgstr "Importé" -#: models.py:247 +#: models.py:248 msgid "Excluded" msgstr "Exclu" -#: models.py:249 +#: models.py:250 msgid "Status" msgstr "État" -#: models.py:250 +#: models.py:251 msgid "Import key" msgstr "Clé d'import" -#: models.py:252 +#: models.py:253 msgid "Import version" msgstr "Version de l'import" -#: models.py:257 templates/chimere/edit.html:56 +#: models.py:258 templates/chimere/edit.html:56 #: templates/chimere/edit_route.html:52 msgid "Start date" msgstr "Date de début" -#: models.py:258 +#: models.py:259 msgid "Not mandatory. Set it for dated item such as event. Format YYYY-MM-DD" msgstr "" "Optionnel. Précisez ce champ pour les éléments datés comme un événement. " "Format du champ : AAAA-MM-JJ" -#: models.py:260 templates/chimere/edit.html:62 +#: models.py:261 templates/chimere/edit.html:62 #: templates/chimere/edit_route.html:58 msgid "End date" msgstr "Date de fin" -#: models.py:261 +#: models.py:262 msgid "" "Not mandatory. Set it only if you have a multi-day event. Format YYYY-MM-DD" msgstr "" "Optionnel. Précisez ce champ seulement pour des événements durant plusieurs " "jours. Format du champ : AAAA-MM-JJ" -#: models.py:293 +#: models.py:294 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:294 +#: models.py:295 msgid "Localisation" msgstr "Localisation" -#: models.py:296 +#: models.py:297 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:300 templates/chimere/edit.html:49 +#: models.py:301 templates/chimere/edit.html:49 #: templates/chimere/edit_route.html:46 msgid "Description" msgstr "Description" -#: models.py:339 models.py:915 +#: models.py:349 models.py:932 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:433 +#: models.py:443 msgid "Audio" msgstr "Audio" -#: models.py:434 +#: models.py:444 msgid "Video" msgstr "Vidéo" -#: models.py:436 +#: models.py:446 msgid "Other" msgstr "Autre" -#: models.py:437 +#: models.py:447 msgid "Media type" msgstr "Type de media" -#: models.py:440 +#: models.py:450 msgid "Mime type" msgstr "Type mime" -#: models.py:442 +#: models.py:452 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:446 +#: models.py:456 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:447 +#: models.py:457 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:483 +#: models.py:493 msgid "Url" msgstr "Url" -#: models.py:486 models.py:531 +#: models.py:496 models.py:541 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:491 +#: models.py:501 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:540 +#: models.py:550 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:558 +#: models.py:568 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:559 +#: models.py:569 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:561 +#: models.py:571 msgid "KML" msgstr "KML" -#: models.py:561 +#: models.py:571 msgid "GPX" msgstr "GPX" -#: models.py:566 +#: models.py:576 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:567 +#: models.py:577 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:617 +#: models.py:627 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:621 +#: models.py:631 msgid "Associated file" msgstr "Fichier associé" -#: models.py:795 +#: models.py:805 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:801 +#: models.py:811 msgid "Layer" msgstr "Couche" -#: models.py:807 +#: models.py:817 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:809 templates/chimere/blocks/welcome.html:3 +#: models.py:819 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:813 +#: models.py:823 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:815 +#: models.py:825 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:817 +#: models.py:827 msgid "Default area" msgstr "Zone par défaut" -#: models.py:818 +#: models.py:828 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:822 +#: models.py:832 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:824 +#: models.py:834 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:825 +#: models.py:835 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -465,57 +469,68 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:829 +#: models.py:839 models.py:906 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:830 +#: models.py:840 msgid "If no sub-category is set all sub-categories are available" msgstr "" "Si aucune sous-catégorie n'est définie toutes les sous-catégories sont " "disponibles" -#: models.py:832 +#: models.py:842 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:834 +#: models.py:844 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:881 +#: models.py:891 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:885 models.py:886 +#: models.py:895 models.py:896 msgid "Layers" msgstr "Couches" -#: models.py:894 +#: models.py:904 +msgid "Mandatory" +msgstr "Obligatoire" + +#: models.py:907 +msgid "" +"If no sub-category is set all the property applies to all sub-categories" +msgstr "" +"Si aucune sous-catégorie n'est précisée, cette propriété est disponible pour " +"toutes les sous-catégories" + +#: models.py:909 msgid "Text" msgstr "Texte" -#: models.py:895 +#: models.py:910 msgid "Long text" msgstr "Texte long" -#: models.py:896 +#: models.py:911 msgid "Password" msgstr "Mot de passe" -#: models.py:900 +#: models.py:917 msgid "Type" msgstr "Type" -#: models.py:905 models.py:917 +#: models.py:922 models.py:934 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:918 +#: models.py:935 msgid "Value" msgstr "Valeur" -#: models.py:922 +#: models.py:939 msgid "Property" msgstr "Propriété" @@ -619,15 +634,15 @@ msgstr "Mauvais paramètre" msgid "There are missing field(s) and/or errors in the submited form." msgstr "Il y a des champs manquants ou des erreurs dans ce formulaire." -#: views.py:308 +#: views.py:312 msgid "Bad file. Please check it with an external software." msgstr "Fichier incohérent. Merci de le vérifier avec un logiciel externe." -#: views.py:430 +#: views.py:434 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:433 +#: views.py:437 msgid "" "Thank you for your contribution. It will be taken into account. If you have " "left your email you may be contacted soon for more details." @@ -636,15 +651,15 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:437 +#: views.py:441 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:568 +#: views.py:572 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:675 +#: views.py:679 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" @@ -818,31 +833,32 @@ msgstr "indique un champ obligatoire" msgid "Categories" msgstr "Catégories" -#: templates/chimere/edit.html:88 +#: templates/chimere/edit.html:113 msgid "Personal information" msgstr "Informations personnelles" -#: templates/chimere/edit.html:90 +#: templates/chimere/edit.html:115 msgid "" "This fields are not mandatory. If you provided them they not will be made " "public and they will only used to join you for this project." -msgstr "Ces champs ne sont pas obligatoires. Si vous les renseignez, ils " -"ne seront pas publiés et ne seront utilisés seulement pour vous joindre " -"dans le cadre de ce projet." +msgstr "" +"Ces champs ne sont pas obligatoires. Si vous les renseignez, ils ne seront " +"pas publiés et ne seront utilisés seulement pour vous joindre dans le cadre " +"de ce projet." -#: templates/chimere/edit.html:93 +#: templates/chimere/edit.html:118 msgid "Your name or nickname" msgstr "Votre nom ou pseudo" -#: templates/chimere/edit.html:98 +#: templates/chimere/edit.html:123 msgid "Your email" msgstr "Votre courriel" -#: templates/chimere/edit.html:103 +#: templates/chimere/edit.html:128 msgid "Comments about your submission" msgstr "Commentaires au sujet de votre proposition" -#: templates/chimere/edit.html:108 templates/chimere/edit_route.html:77 +#: templates/chimere/edit.html:133 templates/chimere/edit_route.html:77 msgid "Propose" msgstr "Proposez" diff --git a/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py b/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py new file mode 100644 index 0000000..53ee3d4 --- /dev/null +++ b/chimere/migrations/0027_auto__add_field_propertymodel_mandatory__chg_field_marker_submiter_com.py @@ -0,0 +1,241 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'PropertyModel.mandatory' + db.add_column('chimere_propertymodel', 'mandatory', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding M2M table for field subcategories on 'PropertyModel' + db.create_table('chimere_propertymodel_subcategories', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('propertymodel', models.ForeignKey(orm['chimere.propertymodel'], null=False)), + ('subcategory', models.ForeignKey(orm['chimere.subcategory'], null=False)) + )) + db.create_unique('chimere_propertymodel_subcategories', ['propertymodel_id', 'subcategory_id']) + + + # Changing field 'Marker.submiter_comment' + db.alter_column('chimere_marker', 'submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True)) + + # Changing field 'Route.submiter_comment' + db.alter_column('chimere_route', 'submiter_comment', self.gf('django.db.models.fields.TextField')(max_length=200, null=True)) + + def backwards(self, orm): + # Deleting field 'PropertyModel.mandatory' + db.delete_column('chimere_propertymodel', 'mandatory') + + # Removing M2M table for field subcategories on 'PropertyModel' + db.delete_table('chimere_propertymodel_subcategories') + + + # Changing field 'Marker.submiter_comment' + db.alter_column('chimere_marker', 'submiter_comment', self.gf('django.db.models.fields.CharField')(max_length=200, null=True)) + + # Changing field 'Route.submiter_comment' + db.alter_column('chimere_route', 'submiter_comment', self.gf('django.db.models.fields.CharField')(max_length=200, null=True)) + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}), + 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'restrict_to_extent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'db_table': "'chimere_subcategory_areas'", 'to': "orm['chimere.SubCategory']"}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'blank': 'True'}), + 'welcome_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.arealayers': { + 'Meta': {'ordering': "('order',)", 'object_name': 'AreaLayers'}, + 'area': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Area']"}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Layer']"}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.color': { + 'Meta': {'ordering': "['order']", 'object_name': 'Color'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.colortheme': { + 'Meta': {'object_name': 'ColorTheme'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.icon': { + 'Meta': {'object_name': 'Icon'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.importer': { + 'Meta': {'object_name': 'Importer'}, + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'chimere.layer': { + 'Meta': {'object_name': 'Layer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'point': ('chimere.widgets.PointField', [], {}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.multimediafile': { + 'Meta': {'object_name': 'MultimediaFile'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'multimedia_files'", 'to': "orm['chimere.Marker']"}), + 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'multimedia_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.MultimediaType']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'chimere.multimediatype': { + 'Meta': {'object_name': 'MultimediaType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'content': ('django.db.models.fields.TextField', [], {}), + 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.picturefile': { + 'Meta': {'object_name': 'PictureFile'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pictures'", 'to': "orm['chimere.Marker']"}), + 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.property': { + 'Meta': {'object_name': 'Property'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Marker']"}), + 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.PropertyModel']"}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'chimere.propertymodel': { + 'Meta': {'ordering': "('order',)", 'object_name': 'PropertyModel'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mandatory': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'properties'", 'blank': 'True', 'to': "orm['chimere.SubCategory']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '1'}) + }, + 'chimere.route': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Route'}, + 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.RouteFile']", 'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'}, + 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.subcategory': { + 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere']
\ No newline at end of file diff --git a/chimere/models.py b/chimere/models.py index 44265eb..ca608e8 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,6 +25,7 @@ import simplejson as json from lxml import etree from datetime import datetime, timedelta from subprocess import Popen, PIPE +import unidecode from django.conf import settings from django.contrib.gis.db import models @@ -38,7 +39,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from chimere.widgets import PointField, RouteField, SelectMultipleField, \ - TextareaWidget + TextareaWidget, DatePickerWidget from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager @@ -303,6 +304,15 @@ class Marker(GeographicItem): def __unicode__(self): return self.name + def __init__(self, *args, **kwargs): + super(Marker, self).__init__(*args, **kwargs) + # add read attributes for properties + for property in self.getProperties(): + attr_name = unidecode.unidecode(property.propertymodel.name).lower() + attr_name = re.sub(r'\W+','_', attr_name.strip()) + if not hasattr(self, attr_name): + setattr(self, attr_name, property.value) + def get_init_multi(self): multis = [forms.model_to_dict(multi) for multi in self.multimedia_files.all()] @@ -891,12 +901,19 @@ class PropertyModel(models.Model): name = models.CharField(_(u"Name"), max_length=150) order = models.IntegerField(_(u"Order")) available = models.BooleanField(_(u"Available")) + mandatory = models.BooleanField(_(u"Mandatory")) + subcategories = SelectMultipleField(SubCategory, related_name='properties', + blank=True, verbose_name=_(u"Restricted to theses sub-categories"), + help_text=_(u"If no sub-category is set all the property applies to all " + u"sub-categories")) TYPE = (('T', _('Text')), ('L', _('Long text')), - ('P', _('Password'))) + ('P', _('Password')), + ('D', _("Date"))) TYPE_WIDGET = {'T':forms.TextInput, 'L':TextareaWidget, - 'P':forms.PasswordInput} + 'P':forms.PasswordInput, + 'D':DatePickerWidget} type = models.CharField(_(u"Type"), max_length=1, choices=TYPE) def __unicode__(self): return self.name diff --git a/chimere/templates/chimere/edit.html b/chimere/templates/chimere/edit.html index bdd8b99..447de71 100644 --- a/chimere/templates/chimere/edit.html +++ b/chimere/templates/chimere/edit.html @@ -69,10 +69,9 @@ <div class='bottomform'> {% for field in form %} {% for property in properties %} - {% ifequal field.name property %} + {% ifequal field.name property.getNamedId %} <div class="fieldWrapper"> - <label for="id_{{field.name}}">{% trans field.label %}</label> - {{ field.errors }} + <label for="id_{{field.name}}">{% trans field.label %}{% if property.mandatory %} *{% endif %}</label> {% if field.errors %}<div class='errors'>{{ field.errors }}</div>{% endif %} {{ field }} </div> @@ -83,6 +82,32 @@ {% inline_formset "Multimedia files" formset_multi %} {% inline_formset "Picture files" formset_picture %} + {% if filtered_properties %} + <script type='text/javascript'> + var cat_filters = new Array(); + var cat_to_hide = new Array(); + {% for property in filtered_properties %} + cat_to_hide.push('#id_{{property.getNamedId}}'); + {% for subcat in property.subcategories.all %} + if(!cat_filters['{{subcat.id}}']) cat_filters['{{subcat.id}}'] = new Array(); + cat_filters['{{subcat.id}}'].push('#id_{{property.getNamedId}}'); + {% endfor %} + {% endfor %} + $('#id_categories').change(function(){ + for (idx in cat_to_hide){ + $(cat_to_hide[idx]).parent().hide(); + } + var vals = $(this).val(); + for (val_id in vals){ + var val = vals[val_id]; + for (ids in cat_filters[val]){ + $(cat_filters[val][ids]).parent().show(); + } + } + }); + $('#id_categories').change(); + </script> + {% endif %} </div> <div class='personalform'> <h3>{% trans "Personal information"%}</h3> diff --git a/chimere/views.py b/chimere/views.py index 3a59d3a..3150258 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -253,6 +253,9 @@ def edit(request, area_name="", item_id=None, submited=False): # get the "manualy" declared_fields. Ie: properties declared_fields = form.declared_fields.keys() + declared_fields = PropertyModel.objects.filter(available=True).all() + filtered_properties = PropertyModel.objects.filter(available=True, + subcategories__id__isnull=False).all() response_dct.update({ 'actions':actions, 'action_selected':('contribute', 'edit'), @@ -268,6 +271,7 @@ def edit(request, area_name="", item_id=None, submited=False): init_item.point if init_item else None, area_name=response_dct['area_name']), 'properties':declared_fields, + 'filtered_properties':filtered_properties, 'submited':submited }) # manualy populate the custom widget diff --git a/debian/control b/debian/control index 7317430..92cfa21 100644 --- a/debian/control +++ b/debian/control @@ -4,6 +4,7 @@ Depends: python-django (>=1.3), python-gdal, python-psycopg2, python-beautifulsoup, python-imaging, libjs-jquery, libjs-jquery-ui, libjs-jquery-ui-theme-base, postgresql-9.1, postgresql-9.1-postgis, gettext, - python-simplejson, gpsbabel, python-django-south + python-simplejson, gpsbabel, python-django-south, + python-unidecode Recommends: tinymce, python-django-celery, python-kombu Suggests: libjs-jquery-ui-theme-south-street diff --git a/docs/install.rst b/docs/install.rst index 2f66879..d0f918a 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -32,6 +32,7 @@ Prerequisites - `Beautiful Soup <http://www.crummy.com/software/BeautifulSoup/>`_ - python-simplejson - python-gdal + - `unidecode <http://pypi.python.org/pypi/Unidecode>_ - `lxml <http://lxml.de/>`_ - `jquery <http://jquery.com/>`_ version 1.7.1 or better - `jquery-ui <http://jqueryui.com/>`_ @@ -59,7 +60,8 @@ Linux distribution repositories. For instance on Debian Wheezy:: python-beautifulsoup tinymce apache2 libgeos-3.3.3 proj-bin gdal-bin \ python-gdal python-lxml python-psycopg2 python-imaging gettext \ postgresql-9.1 postgresql-9.1-postgis libjs-jquery libjs-jquery-ui \ - python-django-celery python-simplejson python-gdal gpsbabel + python-django-celery python-simplejson python-gdal python-unidecode \ + gpsbabel If these packages do not exist in your distribution's repository, please refer to the applications' websites. diff --git a/docs/upgrade.rst b/docs/upgrade.rst index 9f36eb4..aca3985 100644 --- a/docs/upgrade.rst +++ b/docs/upgrade.rst @@ -44,14 +44,15 @@ Activate the backports: http://backports-master.debian.org/Instructions/ Then install the new dependencies:: apt-get install -t squeeze-backports python-django python-django-south \ - python-simplejson libjs-jquery-ui + python-simplejson libjs-jquery-ui python-unidecode Debian Wheezy +++++++++++++ .. code-block:: bash - apt-get install python-django-south python-simplejson libjs-jquery-ui + apt-get install python-django-south python-simplejson libjs-jquery-ui \ + python-unidecode If you are planing to do major import consider the install of `Celery <http://celeryproject.org/>`_. diff --git a/requirements.txt b/requirements.txt index e1f2c46..843a351 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ pil lxml south==0.7.3 simplejson +unidecode |
