summaryrefslogtreecommitdiff
path: root/chimere
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-14 16:55:22 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-14 16:55:22 +0200
commitea65e5512c236b81e7f4b8757521facadae4b3b8 (patch)
tree739cdf40fb6a89de90c4189936d695288a82849f /chimere
parent4b0f0777c434f5fa1366ca408c34d257d4833fad (diff)
parenta55f77a246f99764ff6289686f80825526654e2b (diff)
downloadChimère-ea65e5512c236b81e7f4b8757521facadae4b3b8.tar.bz2
Chimère-ea65e5512c236b81e7f4b8757521facadae4b3b8.zip
Merge branch 'master' into saclay
Conflicts: chimere/admin.py chimere/fixtures/initial_data.json chimere/forms.py chimere/locale/fr/LC_MESSAGES/django.po chimere/models.py chimere/static/chimere/css/styles.css chimere/templates/chimere/detail.html chimere/templatetags/chimere_tags.py chimere/views.py chimere/widgets.py
Diffstat (limited to 'chimere')
-rw-r--r--chimere/admin.py61
-rw-r--r--chimere/feeds.py6
-rw-r--r--chimere/fixtures/default_data.json69
-rw-r--r--chimere/fixtures/initial_data.json78
-rw-r--r--chimere/forms.py50
-rw-r--r--chimere/locale/fr/LC_MESSAGES/django.po474
-rw-r--r--chimere/management/__init__.py0
-rw-r--r--chimere/management/commands/__init__.py0
-rw-r--r--chimere/management/commands/chimere_export.py86
-rw-r--r--chimere/management/commands/chimere_import.py53
-rw-r--r--chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py2
-rw-r--r--chimere/migrations/0041_auto__add_field_importer_source_file.py30
-rw-r--r--chimere/migrations/0042_auto__add_field_importer_origin__add_field_importer_license__add_field.py274
-rw-r--r--chimere/migrations/0043_area_permissions.py230
-rw-r--r--chimere/migrations/0044_auto.py238
-rw-r--r--chimere/models.py244
-rw-r--r--chimere/static/chimere/css/styles.css18
-rw-r--r--chimere/static/chimere/js/edit_area.js54
-rw-r--r--chimere/static/chimere/js/jquery.chimere.js1
-rw-r--r--chimere/static/chimere/js/menu-sort.js14
-rw-r--r--chimere/static/chimere/js/textareas.js22
-rw-r--r--chimere/static/chimere/js/textareas_admin.js30
-rw-r--r--chimere/templates/admin/base_site.html4
-rw-r--r--chimere/templates/chimere/detail.html13
-rw-r--r--chimere/templates/chimere/export.csv (renamed from chimere/templates/chimere/export_marker.csv)0
-rw-r--r--chimere/templates/chimere/export.kml3
-rw-r--r--chimere/templates/chimere/upload_file.html5
-rw-r--r--chimere/templatetags/chimere_tags.py28
-rw-r--r--chimere/tests.py11
-rw-r--r--chimere/tests/georss.xml21
-rw-r--r--chimere/tests/sample.kml10
-rw-r--r--chimere/utils.py272
-rw-r--r--chimere/views.py37
-rw-r--r--chimere/widgets.py64
34 files changed, 1998 insertions, 504 deletions
diff --git a/chimere/admin.py b/chimere/admin.py
index ae6fbc4..cc7925c 100644
--- a/chimere/admin.py
+++ b/chimere/admin.py
@@ -25,6 +25,7 @@ import datetime
from django import forms
from django.conf import settings
from django.contrib import admin
+from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.utils.translation import ugettext_lazy as _
@@ -35,28 +36,16 @@ except ImportError:
pass
from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\
- SubCategoryAdminForm, NewsAdminForm, CategoryAdminForm, ImporterAdminForm,\
- PageAdminForm
+ NewsAdminForm, CategoryAdminForm, ImporterAdminForm,\
+ PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm
from chimere.models import Category, Icon, SubCategory, Marker, \
- PropertyModel, News, Route, Area, ColorTheme, Color, RouteFile,\
- MultimediaType, MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\
- PropertyModelChoice, MultimediaExtension, Page
+ PropertyModel, News, Route, Area, ColorTheme, Color, \
+ MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\
+ PropertyModelChoice, MultimediaExtension, Page,\
+ get_areas_for_user, get_users_by_area
from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\
CSVManager
-def get_areas_for_user(user):
- """
- Getting subcats for a specific user
- """
- perms = user.get_all_permissions()
- areas = set()
- prefix = 'chimere.change_area_'
- for perm in perms:
- if perm.startswith(prefix):
- area = Area.objects.get(urn=perm[len(prefix):])
- areas.add(area)
- return areas
-
def validate(modeladmin, request, queryset):
for item in queryset:
item.status = 'A'
@@ -101,10 +90,16 @@ export_to_csv.short_description = _(u"Export to CSV")
class PictureInline(admin.TabularInline):
model = PictureFile
extra = 1
+ ordering = ('order',)
+ form = PictureFileAdminForm
+ readonly_fields = ('height', 'width')
+ exclude = ('thumbnailfile', 'thumbnailfile_height', 'thumbnailfile_width')
class MultimediaInline(admin.TabularInline):
model = MultimediaFile
extra = 1
+ ordering = ('order',)
+ form = MultimediaFileAdminForm
class MarkerAdmin(admin.ModelAdmin):
"""
@@ -125,13 +120,14 @@ class MarkerAdmin(admin.ModelAdmin):
qs = self.model._default_manager.get_query_set()
if not request.user.is_superuser:
areas = get_areas_for_user(request.user)
- if areas:
- in_areas = " or ".join([area.getIncludeSql() for area in areas])
- qs = qs.extra(where=[in_areas])
+ contained = Q()
+ for area in areas:
+ contained = contained | area.getIncludeMarker()
+ qs = qs.filter(contained)
ordering = self.ordering or ()
if ordering:
qs = qs.order_by(*ordering)
- return qs
+ return qs.distinct()
class RouteAdmin(admin.ModelAdmin):
"""
@@ -143,16 +139,16 @@ class RouteAdmin(admin.ModelAdmin):
exclude = ['height', 'width']
form = RouteAdminForm
readonly_fields = ('associated_file',)
- actions = [validate]
+ actions = [validate, export_to_kml, export_to_shapefile, export_to_csv]
def queryset(self, request):
qs = self.model._default_manager.get_query_set()
if not request.user.is_superuser:
areas = get_areas_for_user(request.user)
- if areas:
- in_areas = " or ".join([area.getIncludeSql(
- geometry='"chimere_route".route') for area in areas])
- qs = qs.extra(where=[in_areas])
+ contained = Q()
+ for area in areas:
+ contained = contained | area.getIncludeRoute()
+ qs = qs.filter(contained)
ordering = self.ordering or ()
if ordering:
qs = qs.order_by(*ordering)
@@ -239,15 +235,6 @@ class ColorThemeAdmin(admin.ModelAdmin):
class IconAdmin(admin.ModelAdmin):
exclude = ['height', 'width']
-class MultimediaTypeAdmin(admin.ModelAdmin):
- search_fields = ("name",)
- list_display = ('name', 'media_type', 'mime_type', 'iframe', 'available')
- list_filter = ('media_type', 'available')
-
-class MultimediaExtensionAdmin(admin.ModelAdmin):
- list_display = ('name', 'multimedia_type')
- list_filter = ('multimedia_type',)
-
class PropertyModelChoiceInline(admin.TabularInline):
model = PropertyModelChoice
extra = 1
@@ -264,6 +251,4 @@ admin.site.register(Route, RouteAdmin)
admin.site.register(PropertyModel, PropertyModelAdmin)
admin.site.register(Area, AreaAdmin)
admin.site.register(ColorTheme, ColorThemeAdmin)
-admin.site.register(MultimediaExtension, MultimediaExtensionAdmin)
-admin.site.register(MultimediaType, MultimediaTypeAdmin)
admin.site.register(Layer)
diff --git a/chimere/feeds.py b/chimere/feeds.py
index c4ee7a5..100dd6b 100644
--- a/chimere/feeds.py
+++ b/chimere/feeds.py
@@ -21,7 +21,8 @@
from django.conf import settings
from django.contrib.gis.geos import *
-from django.contrib.syndication.views import Feed, FeedDoesNotExist
+from django.contrib.gis.feeds import Feed
+from django.contrib.syndication.views import FeedDoesNotExist
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
@@ -53,6 +54,9 @@ class BaseFeed(Feed):
def description(self, obj):
return ""
+ def item_geometry(self, obj):
+ return obj.point
+
class LatestPOIsByCategory(BaseFeed):
'''
Last Points of interests by category in Feeds
diff --git a/chimere/fixtures/default_data.json b/chimere/fixtures/default_data.json
new file mode 100644
index 0000000..56df4c3
--- /dev/null
+++ b/chimere/fixtures/default_data.json
@@ -0,0 +1,69 @@
+[
+ {
+ "pk": 1,
+ "model": "chimere.colortheme",
+ "fields": {
+ "name": "Blue"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "chimere.color",
+ "fields": {
+ "code": "0000FF",
+ "color_theme": 1,
+ "order": 10
+ }
+ },
+ {
+ "pk": 2,
+ "model": "chimere.color",
+ "fields": {
+ "code": "2222FF",
+ "color_theme": 1,
+ "order": 20
+ }
+ },
+ {
+ "pk": 3,
+ "model": "chimere.color",
+ "fields": {
+ "code": "4444FF",
+ "color_theme": 1,
+ "order": 30
+ }
+ },
+ {
+ "pk": 1,
+ "model": "chimere.category",
+ "fields": {
+ "available": true,
+ "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc blandit porta eros, quis varius orci luctus nec. Suspendisse tempor sagittis tortor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus imperdiet consequat dolor. Etiam risus orci, auctor nec hendrerit ut, congue at ante. Aliquam et accumsan neque. Aliquam ac massa felis, ac porttitor nunc. Curabitur blandit odio id enim sodales blandit. Curabitur eleifend commodo lorem a feugiat. Nam at quam semper justo ultricies tempor.\r\n",
+ "name": "Default category",
+ "order": 10
+ }
+ },
+ {
+ "pk": 1,
+ "model": "chimere.icon",
+ "fields": {
+ "width": 21,
+ "image": "icons/marker.png",
+ "name": "Default icon",
+ "height": 25
+ }
+ },
+ {
+ "pk": 1,
+ "model": "chimere.subcategory",
+ "fields": {
+ "category": 1,
+ "available": true,
+ "name": "Default subcategory",
+ "item_type": "M",
+ "color_theme": null,
+ "order": 10,
+ "icon": 1
+ }
+ }
+]
diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json
index 71f4972..20347a3 100644
--- a/chimere/fixtures/initial_data.json
+++ b/chimere/fixtures/initial_data.json
@@ -1,39 +1,5 @@
[
{
- "pk": 1,
- "model": "chimere.colortheme",
- "fields": {
- "name": "Blue"
- }
- },
- {
- "pk": 1,
- "model": "chimere.color",
- "fields": {
- "code": "0000FF",
- "color_theme": 1,
- "order": 10
- }
- },
- {
- "pk": 2,
- "model": "chimere.color",
- "fields": {
- "code": "2222FF",
- "color_theme": 1,
- "order": 20
- }
- },
- {
- "pk": 3,
- "model": "chimere.color",
- "fields": {
- "code": "4444FF",
- "color_theme": 1,
- "order": 30
- }
- },
- {
"pk": 7,
"model": "chimere.multimediatype",
"fields": {
@@ -320,5 +286,49 @@
"layer_code": "new OpenLayers.Layer.MapQuestOSM()",
"name": "OSM - MapQuest"
}
+ },
+ {
+ "pk": 1,
+ "model": "auth.group",
+ "fields": {
+ "name": "Application administrator",
+ "permissions": [
+ 67,
+ 68,
+ 40,
+ 41,
+ 42,
+ 37,
+ 38,
+ 39,
+ 34,
+ 35,
+ 36,
+ 43,
+ 44,
+ 45,
+ 49,
+ 50,
+ 51,
+ 55,
+ 56,
+ 57,
+ 28,
+ 29,
+ 30,
+ 58,
+ 59,
+ 60,
+ 64,
+ 65,
+ 66,
+ 61,
+ 62,
+ 63,
+ 46,
+ 47,
+ 48
+ ]
+ }
}
]
diff --git a/chimere/forms.py b/chimere/forms.py
index b584f4f..8ce9ad2 100644
--- a/chimere/forms.py
+++ b/chimere/forms.py
@@ -36,7 +36,8 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\
PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, \
MultimediaExtension, Page
from chimere.widgets import AreaField, PointField, TextareaWidget, \
- FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget
+ FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget, \
+ TextareaAdminWidget
from datetime import timedelta, datetime, tzinfo
@@ -113,7 +114,7 @@ class NewsAdminForm(forms.ModelForm):
"""
Main form for news
"""
- content = forms.CharField(widget=FullTextareaWidget)
+ content = forms.CharField(widget=TextareaAdminWidget)
class Meta:
model = News
@@ -125,11 +126,31 @@ class ImporterAdminForm(forms.ModelForm):
'filtr': forms.TextInput(attrs={'size': 80}),
}
+ def clean(self):
+ '''
+ Verify that only one type of source is provided
+ Verify that shapefiles are zipped
+ '''
+ if self.cleaned_data['importer_type'] == 'SHP' and \
+ not self.cleaned_data['zipped']:
+ raise forms.ValidationError(_(u"Shapefiles must be provided in a "\
+ u"zipped archive."))
+ if self.cleaned_data['source'] and \
+ self.cleaned_data['source_file']:
+ raise forms.ValidationError(_(u"You have to set \"source\" or "
+ u"\"source file\" but not both."))
+ if not self.cleaned_data['source'] and \
+ not self.cleaned_data['source_file'] and \
+ self.cleaned_data['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=TextareaWidget, required=False)
+ description = forms.CharField(widget=TextareaAdminWidget, required=False)
class Media:
js = list(settings.JQUERY_JS_URLS) + [
'%schimere/js/menu-sort.js' % settings.STATIC_URL,
@@ -141,7 +162,7 @@ class MarkerAdminFormBase(forms.ModelForm):
"""
Main form for marker
"""
- description = forms.CharField(widget=TextareaWidget, required=False)
+ description = forms.CharField(widget=TextareaAdminWidget, required=False)
class Meta:
model = Marker
@@ -246,6 +267,7 @@ class MarkerForm(MarkerBaseForm):
"""
ref_pk = forms.IntegerField(label=u" ", widget=forms.HiddenInput(),
required=False)
+ description = forms.CharField(widget=TextareaWidget, required=False)
class Meta:
model = Marker
exclude = ('status',)
@@ -348,7 +370,6 @@ class RouteForm(RouteAdminForm):
new_marker.saveProperties(properties)
return new_route
-
class BaseFileForm(forms.ModelForm):
id = forms.IntegerField(label=u"", widget=forms.HiddenInput(),
required=False)
@@ -383,6 +404,14 @@ class BaseFileForm(forms.ModelForm):
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,
+ ]
+
class MultimediaFileForm(BaseFileForm):
"""
Form for a multimedia file
@@ -425,6 +454,14 @@ class MultimediaFileForm(BaseFileForm):
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
@@ -459,7 +496,8 @@ class AreaAdminForm(forms.ModelForm):
Admin page to create an area
"""
area = AreaField(label=_("Area"), fields=(PointField(), PointField()))
- welcome_message = forms.CharField(widget=TextareaWidget, required=False)
+ welcome_message = forms.CharField(widget=TextareaAdminWidget,
+ required=False)
class Meta:
model = Area
diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po
index 9973efb..5956c20 100644
--- a/chimere/locale/fr/LC_MESSAGES/django.po
+++ b/chimere/locale/fr/LC_MESSAGES/django.po
@@ -7,17 +7,17 @@ msgid ""
msgstr ""
"Project-Id-Version: 2.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-10-02 19:08+0200\n"
+"POT-Creation-Date: 2012-10-14 16:46+0200\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:677
+#: __init__.py:8 models.py:734
msgid "Multimedia files"
msgstr "Fichiers multimedias"
-#: __init__.py:9 models.py:733
+#: __init__.py:9 models.py:790
msgid "Picture files"
msgstr "Fichiers d'image"
@@ -45,510 +45,545 @@ msgstr "Flux RSS"
msgid "Contact us"
msgstr "Nous contacter"
-#: admin.py:64 templates/chimere/feeds/rss.html:69
+#: admin.py:53 templates/chimere/feeds/rss.html:69
msgid "Validate"
msgstr "Valider"
-#: admin.py:75
+#: admin.py:64
msgid "Export to KML"
msgstr "Exporter en KML"
-#: admin.py:89
+#: admin.py:78
msgid "Export to Shapefile"
msgstr "Exporter en Shapefile"
-#: admin.py:99
+#: admin.py:88
msgid "Export to CSV"
msgstr "Exporter en CSV"
-#: admin.py:182
+#: admin.py:174
msgid "Import"
msgstr "Import"
-#: admin.py:188
+#: admin.py:180
msgid "Cancel import"
msgstr "Annuler l'import"
-#: admin.py:194
+#: admin.py:186
msgid "Cancel export"
msgstr "Annuler l'export"
-#: admin.py:202
+#: admin.py:194
msgid "Export to osm"
msgstr "Exporter vers osm"
-#: feeds.py:124 feeds.py:211
+#: feeds.py:128 feeds.py:215
msgid "Last points of interest"
msgstr "Derniers points d'intérêt"
-#: feeds.py:130
+#: feeds.py:134
msgid "Latest points of interest from "
msgstr "Nouveaux points d'intérêt de "
-#: feeds.py:176
+#: feeds.py:180
msgid "Last points of interest by area"
msgstr "Nouveaux points d'intérêt par zone"
-#: forms.py:82
+#: forms.py:83
msgid "New submission for"
msgstr "Nouvelle proposition pour"
-#: forms.py:83
+#: forms.py:84
#, python-format
msgid "The new item \"%s\" has been submited in the category: "
msgstr "Le nouvel élément « %s » a été proposé dans la catégorie : "
-#: forms.py:85
+#: forms.py:86
msgid "To valid, precise or unvalid this item: "
msgstr "Pour valider, préciser ou rejeter cet élément : "
-#: forms.py:95
+#: forms.py:96
msgid "Email (optional)"
msgstr "Courriel (optionnel) "
-#: forms.py:96
+#: forms.py:97
msgid "Object"
msgstr "Objet"
-#: forms.py:183
+#: forms.py:136
+msgid "Shapefiles must be provided in a zipped archive."
+msgstr ""
+"Les fichiers Shapefiles doivent être fournis regroupés dans une archive zip."
+
+#: forms.py:140
+msgid "You have to set \"source\" or \"source file\" but not both."
+msgstr ""
+"Vous devez spécifier le champ « Source » ou « Fichier source » mais pas les "
+"deux."
+
+#: forms.py:145
+msgid "You have to set \"source\" or \"source file\"."
+msgstr "Vous devez spécifier le champ « Source » ou « Fichier source »."
+
+#: forms.py:204
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:194
+#: forms.py:215
msgid "This field is mandatory for the selected categories"
msgstr "Ce champ est obligatoire pour les catégories sélectionnées"
-#: forms.py:441
+#: forms.py:478
msgid "File"
msgstr "Fichier"
-#: forms.py:447
+#: forms.py:484
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:452 models.py:50 models.py:98 models.py:158 models.py:179
-#: models.py:192 models.py:206 models.py:324 models.py:611 models.py:667
-#: models.py:710 models.py:826 models.py:1119 models.py:1131 models.py:1216
-#: utils.py:444 templates/chimere/edit.html:39
+#: forms.py:489 models.py:53 models.py:101 models.py:163 models.py:184
+#: models.py:197 models.py:212 models.py:352 models.py:668 models.py:724
+#: models.py:767 models.py:883 models.py:1199 models.py:1211 models.py:1384
+#: utils.py:454 templates/chimere/edit.html:39
#: templates/chimere/edit_route.html:36
#: templates/chimere/blocks/alternate_multimedia.html:39
msgid "Name"
msgstr "Nom"
-#: forms.py:461 models.py:1168
+#: forms.py:498 models.py:1248
msgid "Area"
msgstr "Zone"
-#: forms.py:520
+#: forms.py:558
msgid "Start"
msgstr "Départ"
-#: forms.py:521
+#: forms.py:559
msgid "Finish"
msgstr "Arrivée :"
-#: forms.py:522
+#: forms.py:560
msgid "Speed"
msgstr "Vitesse"
-#: models.py:51
+#: models.py:54
msgid "Mnemonic"
msgstr "Mnémonique"
-#: models.py:53 models.py:99 models.py:180 models.py:207 models.py:335
-#: models.py:615 models.py:1137 models.py:1218 models.py:1259
+#: models.py:56 models.py:102 models.py:185 models.py:213 models.py:363
+#: models.py:672 models.py:1217 models.py:1386 models.py:1427
msgid "Available"
msgstr "Disponible"
-#: models.py:54 models.py:168 models.py:181 models.py:215 models.py:669
-#: models.py:725 models.py:1136 models.py:1205 models.py:1217
+#: models.py:57 models.py:173 models.py:186 models.py:223 models.py:726
+#: models.py:782 models.py:1216 models.py:1373 models.py:1385
msgid "Order"
msgstr "Ordre"
-#: models.py:55
+#: models.py:58
msgid "Template path"
msgstr "Chemin du patron"
-#: models.py:62 models.py:63
+#: models.py:65 models.py:66
msgid "Page"
msgstr "Page"
-#: models.py:100 models.py:401
+#: models.py:103 models.py:443
msgid "Is front page"
msgstr "Est en page principale"
-#: models.py:102 models.py:1227
+#: models.py:105 models.py:1395
msgid "Date"
msgstr "Date"
-#: models.py:104 models.py:668
+#: models.py:107 models.py:725
msgid "Url"
msgstr "Url"
-#: models.py:109 models.py:110 templates/chimere/blocks/news.html:3
+#: models.py:108
+msgid "Associated areas"
+msgstr "Zones associées"
+
+#: models.py:114 models.py:115 templates/chimere/blocks/news.html:3
#: templates/chimere/blocks/news.html:5
msgid "News"
msgstr "Nouvelle"
-#: models.py:119
+#: models.py:124
msgid "Parameters"
msgstr "Paramètres"
-#: models.py:123
+#: models.py:128
msgid "TinyUrl"
msgstr "Mini-url"
-#: models.py:162 models.py:169 models.py:213
+#: models.py:167 models.py:174 models.py:221
msgid "Color theme"
msgstr "Thème de couleur"
-#: models.py:167
+#: models.py:172
msgid "Code"
msgstr "Code"
-#: models.py:174
+#: models.py:179
msgid "Color"
msgstr "Couleur"
-#: models.py:187 models.py:205 templates/chimere/main_map.html:13
+#: models.py:192 models.py:210 templates/chimere/main_map.html:13
msgid "Category"
msgstr "Catégorie"
-#: models.py:193 models.py:607 models.py:711 models.py:891
+#: models.py:198 models.py:664 models.py:768 models.py:949
#: templates/chimere/blocks/alternate_multimedia.html:43
msgid "Image"
msgstr "Image"
-#: models.py:195 models.py:713 models.py:893
+#: models.py:200 models.py:770 models.py:951
msgid "Height"
msgstr "Hauteur"
-#: models.py:196 models.py:714 models.py:894
+#: models.py:201 models.py:771 models.py:952
msgid "Width"
msgstr "Largeur"
-#: models.py:200 models.py:210
+#: models.py:205 models.py:218
msgid "Icon"
msgstr "Icône"
-#: models.py:208
+#: models.py:214
msgid "Available for submission"
msgstr "Disponible pour soumission"
-#: models.py:211
+#: models.py:216
+msgid "Displayed in the layer menu"
+msgstr "Apparaît dans le menu des couches ?"
+
+#: models.py:219
msgid "Hover icon"
msgstr "Icône en survol"
-#: models.py:216
+#: models.py:224
msgid "Is dated"
msgstr "Est daté"
-#: models.py:217
+#: models.py:225
msgid "Marker"
msgstr "Point d'intérêt"
-#: models.py:218 models.py:887 models.py:902
+#: models.py:226 models.py:945 models.py:960
#: templates/chimere/edit_route.html:27
msgid "Route"
msgstr "Trajet"
-#: models.py:219
+#: models.py:227
msgid "Both"
msgstr "Mixte"
-#: models.py:220
+#: models.py:228
msgid "Item type"
msgstr "Type d'élément"
-#: models.py:226
+#: models.py:234
msgid "Sub-category"
msgstr "Sous-catégorie"
-#: models.py:227
+#: models.py:235
msgid "Sub-categories"
msgstr "Sous-catégories"
-#: models.py:297
+#: models.py:311
msgid "Importer type"
msgstr "Type d'import"
-#: models.py:300 models.py:346
+#: models.py:314 models.py:374
msgid "Source"
msgstr "Source"
-#: models.py:302
+#: models.py:316
+msgid "Source file"
+msgstr "Fichier source"
+
+#: models.py:318
msgid "Filter"
msgstr "Filtre"
-#: models.py:304
+#: models.py:320
msgid "Name by default"
msgstr "Nom par défaut"
-#: models.py:307
-msgid "Associated subcategories"
-msgstr "Sous-catégories associées"
-
-#: models.py:308 utils.py:447
-msgid "State"
-msgstr "État"
-
-#: models.py:310
+#: models.py:322
msgid "SRID"
msgstr "SRID"
-#: models.py:311
+#: models.py:323
msgid "Zipped file"
msgstr "Fichier zippé"
-#: models.py:314
+#: models.py:324 models.py:380
+msgid "Origin"
+msgstr "Origine"
+
+#: models.py:326 models.py:382
+msgid "License"
+msgstr "Licence"
+
+#: models.py:329
+msgid "Associated subcategories"
+msgstr "Sous-catégories associées"
+
+#: models.py:330 utils.py:458
+msgid "State"
+msgstr "État"
+
+#: models.py:334
msgid "Importer"
msgstr "Import"
-#: models.py:326
+#: models.py:354
msgid "Submitter session key"
msgstr "Clé de session du demandeur"
-#: models.py:328
+#: models.py:356
msgid "Submitter name or nickname"
msgstr "Nom ou pseudo du demandeur"
-#: models.py:330
+#: models.py:358
msgid "Submitter email"
msgstr "Courriel du demandeur"
-#: models.py:332
+#: models.py:360
msgid "Submitter comment"
msgstr "Commentaire du demandeur"
-#: models.py:334
+#: models.py:362
msgid "Submited"
msgstr "Soumis"
-#: models.py:336
+#: models.py:364
msgid "Modified"
msgstr "Modifié"
-#: models.py:337
+#: models.py:365
msgid "Disabled"
msgstr "Désactivé"
-#: models.py:338
+#: models.py:366
msgid "Imported"
msgstr "Importé"
-#: models.py:339
+#: models.py:367
msgid "Excluded"
msgstr "Exclu"
-#: models.py:341
+#: models.py:369
msgid "Status"
msgstr "État"
-#: models.py:342
+#: models.py:370
msgid "Import key"
msgstr "Clé d'import"
-#: models.py:344
+#: models.py:372
msgid "Import version"
msgstr "Version de l'import"
-#: models.py:348
+#: models.py:376
msgid "Modified since last import"
msgstr "Modifié depuis le dernier import"
-#: models.py:350
+#: models.py:378
msgid "Not to be imported inside OSM"
msgstr "Ne pas importer dans OSM"
-#: models.py:353 templates/chimere/edit.html:56
+#: models.py:385 templates/chimere/edit.html:56
#: templates/chimere/edit_route.html:52
msgid "Start date"
msgstr "Date de début"
-#: models.py:354
+#: models.py:386
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:356 templates/chimere/edit.html:62
+#: models.py:388 templates/chimere/edit.html:62
#: templates/chimere/edit_route.html:58
msgid "End date"
msgstr "Date de fin"
-#: models.py:357
+#: models.py:389
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:393
+#: models.py:435
msgid "Reference marker"
msgstr "Point d'intérêt de référence"
-#: models.py:394 utils.py:449 utils.py:450
+#: models.py:436 utils.py:460
msgid "Localisation"
msgstr "Localisation"
-#: models.py:396
+#: models.py:438
msgid "Available Date"
msgstr "Date de mise en disponibilité"
-#: models.py:400 utils.py:448 templates/chimere/edit.html:49
+#: models.py:442 utils.py:459 templates/chimere/edit.html:49
#: templates/chimere/edit_route.html:46
msgid "Description"
msgstr "Description"
-#: models.py:461 models.py:1269
+#: models.py:506 models.py:1437
msgid "Point of interest"
msgstr "Point d'intérêt"
-#: models.py:605
+#: models.py:662
msgid "Audio"
msgstr "Audio"
-#: models.py:606
+#: models.py:663
msgid "Video"
msgstr "Vidéo"
-#: models.py:608
+#: models.py:665
msgid "Other"
msgstr "Autre"
-#: models.py:609
+#: models.py:666
msgid "Media type"
msgstr "Type de media"
-#: models.py:612
+#: models.py:669
msgid "Mime type"
msgstr "Type mime"
-#: models.py:614
+#: models.py:671
msgid "Inside an iframe"
msgstr "À l'intérieur d'un iframe"
-#: models.py:618
+#: models.py:675
msgid "Multimedia type"
msgstr "Type de multimedia"
-#: models.py:619
+#: models.py:676
msgid "Multimedia types"
msgstr "Types de multimedia"
-#: models.py:654
+#: models.py:711
msgid "Extension name"
msgstr "Nom de l'extension"
-#: models.py:656
+#: models.py:713
msgid "Associated multimedia type"
msgstr "Type de multimedia associé"
-#: models.py:660
+#: models.py:717
msgid "Multimedia extension"
msgstr "Extension de fichier multimedia"
-#: models.py:661
+#: models.py:718
msgid "Multimedia extensions"
msgstr "Extensions de fichier multimedia"
-#: models.py:671 models.py:715
+#: models.py:728 models.py:772
msgid "Display inside the description?"
msgstr "Apparaît dans la description ?"
-#: models.py:676
+#: models.py:733
msgid "Multimedia file"
msgstr "Fichier multimedia"
-#: models.py:717
+#: models.py:774
msgid "Thumbnail"
msgstr "Miniature"
-#: models.py:721
+#: models.py:778
msgid "Thumbnail height"
msgstr "Hauteur de la miniature"
-#: models.py:723
+#: models.py:780
msgid "Thumbnail width"
msgstr "Largeur de la miniature"
-#: models.py:732
+#: models.py:789
msgid "Picture file"
msgstr "Fichier d'image"
-#: models.py:827
+#: models.py:884
msgid "Raw file (gpx or kml)"
msgstr "Fichier brut (gpx ou kml)"
-#: models.py:828
+#: models.py:886
msgid "Simplified file"
msgstr "Fichier simplifié"
-#: models.py:830
+#: models.py:888
msgid "KML"
msgstr "KML"
-#: models.py:830
+#: models.py:888
msgid "GPX"
msgstr "GPX"
-#: models.py:835
+#: models.py:893
msgid "Route file"
msgstr "Fichier de trajet"
-#: models.py:836
+#: models.py:894
msgid "Route files"
msgstr "Fichiers de trajet"
-#: models.py:886
+#: models.py:944
msgid "Reference route"
msgstr "Trajet de référence"
-#: models.py:890
+#: models.py:948
msgid "Associated file"
msgstr "Fichier associé"
-#: models.py:1120
+#: models.py:1200
msgid "Layer code"
msgstr "Code pour la couche"
-#: models.py:1126
+#: models.py:1206
msgid "Layer"
msgstr "Couche"
-#: models.py:1132
+#: models.py:1212
msgid "Area urn"
msgstr "Urn de la zone"
-#: models.py:1134 templates/chimere/blocks/welcome.html:3
+#: models.py:1214 templates/chimere/blocks/welcome.html:3
msgid "Welcome message"
msgstr "Message d'accueil"
-#: models.py:1138
+#: models.py:1218
msgid "Upper left corner"
msgstr "Coin en haut à gauche"
-#: models.py:1140
+#: models.py:1220
msgid "Lower right corner"
msgstr "Coin en bas à droite"
-#: models.py:1142
+#: models.py:1222
msgid "Default area"
msgstr "Zone par défaut"
-#: models.py:1143
+#: models.py:1223
msgid "Only one area is set by default"
msgstr "Seule une zone est définie par défaut"
-#: models.py:1147
+#: models.py:1227
msgid "Sub-categories checked by default"
msgstr "Sous-catégories cochées par défaut"
-#: models.py:1149
+#: models.py:1229
msgid "Sub-categories dynamicaly displayed"
msgstr "Sous-categories affichées dynamiquement"
-#: models.py:1150
+#: models.py:1230
msgid ""
"If checked, categories are only displayed in the menu if they are available "
"on the current extent."
@@ -556,76 +591,76 @@ msgstr ""
"Si coché, les catégories sont disponibles sur le menu seulement si elles "
"apparaissent sur la zone affichée."
-#: models.py:1154 models.py:1221
+#: models.py:1234 models.py:1389
msgid "Restricted to theses sub-categories"
msgstr "Restreindre à ces sous-categories"
-#: models.py:1155
+#: models.py:1235
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:1157
+#: models.py:1237
msgid "Link to an external CSS"
msgstr "Lien vers une feuille de style externe"
-#: models.py:1159
+#: models.py:1239
msgid "Restrict to the area extent"
msgstr "Restreindre à l'étendue de la zone"
-#: models.py:1206
+#: models.py:1374 widgets.py:86
msgid "Default layer"
msgstr "Couche par défaut"
-#: models.py:1210 models.py:1211
+#: models.py:1378 models.py:1379
msgid "Layers"
msgstr "Couches"
-#: models.py:1219
+#: models.py:1387
msgid "Mandatory"
msgstr "Obligatoire"
-#: models.py:1222
+#: models.py:1390
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:1224
+#: models.py:1392
msgid "Text"
msgstr "Texte"
-#: models.py:1225
+#: models.py:1393
msgid "Long text"
msgstr "Texte long"
-#: models.py:1226
+#: models.py:1394
msgid "Password"
msgstr "Mot de passe"
-#: models.py:1228
+#: models.py:1396
msgid "Choices"
msgstr "Choix"
-#: models.py:1236
+#: models.py:1404
msgid "Type"
msgstr "Type"
-#: models.py:1241 models.py:1257 models.py:1271
+#: models.py:1409 models.py:1425 models.py:1439
msgid "Property model"
msgstr "Modèle de propriété"
-#: models.py:1258 models.py:1272
+#: models.py:1426 models.py:1440
msgid "Value"
msgstr "Valeur"
-#: models.py:1264
+#: models.py:1432
msgid "Model property choice"
msgstr "Choix pour les modèles de propriété"
-#: models.py:1283
+#: models.py:1451
msgid "Property"
msgstr "Propriété"
@@ -679,14 +714,18 @@ msgstr "Export échoué"
msgid "Export canceled"
msgstr "Export annulé"
-#: utils.py:118 utils.py:166
+#: utils.py:123 utils.py:172
msgid "Bad zip file"
msgstr "Mauvais fichier zip"
-#: utils.py:169
+#: utils.py:175
msgid "Missing file(s) inside the zip file"
msgstr "Fichier(s) manquant(s) dans l'archive zip"
+#: utils.py:216
+msgid "Bad XML file"
+msgstr "Mauvais fichier XML"
+
#: utils.py:301
msgid "Error while reading the data source."
msgstr "Erreur lors de la lecture de la source."
@@ -697,28 +736,40 @@ msgstr ""
"Les types des éléments géographiques de ce fichier Shapefile ne sont pas "
"gérés par Chimère."
-#: utils.py:393
+#: utils.py:356
+msgid "Bad Shapefile"
+msgstr "Mauvais fichier Shapefile"
+
+#: utils.py:398
msgid "Could not create file!"
msgstr "Ne peut pas créer le fichier !"
-#: utils.py:404
+#: utils.py:409
msgid "Failed to create field"
msgstr "Ne peut pas créer un champ"
-#: utils.py:445 templates/chimere/edit.html:44
+#: utils.py:455 templates/chimere/edit.html:44
#: templates/chimere/edit_route.html:41
msgid "Categories"
msgstr "Catégories"
-#: utils.py:509
+#: utils.py:488
+msgid "Invalid CSV format"
+msgstr "Fichier CSV non valide"
+
+#: utils.py:563
+msgid "RSS feed is not well formed"
+msgstr "Flux RSS non valide"
+
+#: utils.py:633
msgid "Nothing to import"
msgstr "Rien à importer"
-#: utils.py:589
+#: utils.py:721
msgid "New items imported - validate them before exporting"
msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter"
-#: utils.py:591
+#: utils.py:723
msgid ""
"There are items from a former import not yet validated - validate them "
"before exporting"
@@ -726,15 +777,15 @@ msgstr ""
"Il y a des éléments d'un import précédent pas encore validé - Validez les "
"avant d'exporter"
-#: utils.py:601
+#: utils.py:733
msgid "Bad param"
msgstr "Mauvais paramètre"
-#: utils.py:616
+#: utils.py:748
msgid "No non ambigious tag is defined in the XAPI request"
msgstr "Aucun « tag » non ambigu n'est défini dans la requête XAPI"
-#: utils.py:618
+#: utils.py:750
msgid ""
"No bounding box is defined in the XAPI request.If you are sure to manage the "
"entire planet set the bounding box to -180,-90,180,90"
@@ -747,15 +798,15 @@ msgstr ""
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:350
+#: views.py:353
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:482
+#: views.py:465
msgid "Comments/request on the map"
msgstr "Commentaires/requètes sur la carte"
-#: views.py:485
+#: views.py:468
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."
@@ -764,52 +815,52 @@ msgstr ""
"laissé votre courriel vous serez peut-être contacté bientôt pour plus de "
"détails."
-#: views.py:489
+#: views.py:472
msgid "Temporary error. Renew your message later."
msgstr "Erreur temporaire. Réenvoyez votre message plus tard."
-#: views.py:641
+#: views.py:624
msgid "No category available in this area."
msgstr "Pas de catégorie disponible sur cette zone."
-#: views.py:785
+#: views.py:768
msgid "Incorrect choice in the list"
msgstr "Choix incorrect dans la liste"
-#: widgets.py:229
+#: widgets.py:245
msgid "Street, City, Country"
msgstr "Rue, Commune, Pays"
-#: widgets.py:295
+#: widgets.py:312
msgid "Latitude"
msgstr "Latitude"
-#: widgets.py:295
+#: widgets.py:312
msgid "Longitude"
msgstr "Longitude"
-#: widgets.py:320
+#: widgets.py:337
msgid "Invalid point"
msgstr "Point invalide"
-#: widgets.py:370
+#: widgets.py:390
msgid "Creation mode"
msgstr "Mode création"
-#: widgets.py:371
+#: widgets.py:391
msgid "To start drawing the route click on the toggle button: \"Draw\"."
msgstr ""
"Pour commencer le dessin cliquez sur le bouton&nbsp;: «&nbsp;Tracer&nbsp;»."
-#: widgets.py:373
+#: widgets.py:393
msgid "Then click on the map to begin the drawing."
msgstr "Puis cliquez sur la carte pour commencer le dessin."
-#: widgets.py:374
+#: widgets.py:394
msgid "You can add points by clicking again."
msgstr "Vous pouvez ajouter des points en cliquant de nouveau."
-#: widgets.py:375
+#: widgets.py:395
msgid ""
"To finish the drawing double click. When the drawing is finished you can "
"edit it."
@@ -817,7 +868,7 @@ msgstr ""
"Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez "
"toujours l'éditer."
-#: widgets.py:377
+#: widgets.py:397
msgid ""
"While creating to undo a drawing click again on the toggle button \"Stop "
"drawing\"."
@@ -825,17 +876,17 @@ msgstr ""
"En mode création vous pouvez annuler un tracé en appuyant sur le bouton "
"«&nbsp;Arrêter le tracé&nbsp;»."
-#: widgets.py:382
+#: widgets.py:402
msgid "Modification mode"
msgstr "Mode modification"
-#: widgets.py:383
+#: widgets.py:403
msgid "To move a point click on it and drag it to the desired position."
msgstr ""
"Pour bouger un point, cliquez dessus, maintenez le click pour le déposer à "
"la position désirée."
-#: widgets.py:384
+#: widgets.py:404
msgid ""
"To delete a point move the mouse cursor over it and press the \"d\" or \"Del"
"\" key."
@@ -843,7 +894,7 @@ msgstr ""
"Pour supprimer un point, mettez le curseur de la souris sur celui-ci et "
"appuyez sur le touche «&nbsp;d&nbsp;» ou «&nbsp;Suppr&nbsp;»."
-#: widgets.py:386
+#: widgets.py:406
msgid ""
"To add a point click in the middle of a segment and drag the new point to "
"the desired position"
@@ -852,33 +903,39 @@ msgstr ""
"maintenez le bouton appuyé et déplacez le nouveau point à la position "
"désirée."
-#: widgets.py:393
+#: widgets.py:413
msgid "Give a name and set category before uploading a file."
msgstr ""
"Renseignez le nom et choisissez au moins une catégorie avant de déposer un "
"fichier."
-#: widgets.py:396
+#: widgets.py:416
msgid "Upload a route file (GPX or KML)"
msgstr "Déposer un trajet (fichier GPX ou KML)"
-#: widgets.py:397
+#: widgets.py:417
msgid "or"
msgstr "ou"
-#: widgets.py:402
+#: widgets.py:422
msgid "Start \"hand\" drawing"
msgstr "Commencer le tracé manuellement"
-#: widgets.py:425
+#: widgets.py:445
msgid "Move on the map"
msgstr "Se déplacer"
-#: widgets.py:425
+#: widgets.py:445
msgid "Draw"
msgstr "Tracer"
-#: widgets.py:550
+#: widgets.py:525
+msgid "Hold CTRL, click and drag to select area on the map"
+msgstr ""
+"Maintenir la touche Control, cliquez puis glissez pour sélectionner une zone "
+"sur la carte"
+
+#: widgets.py:591
msgid "Select..."
msgstr "Sélectionner..."
@@ -891,7 +948,7 @@ msgid "Internal server error"
msgstr "Erreur interne du serveur"
#: templates/admin/base_site.html:4 templates/admin/base_site.html.py:7
-msgid "Administration de Chimère"
+msgid "Chimère administration"
msgstr "Administration de Chimère"
#: templates/chimere/base.html:19
@@ -914,14 +971,26 @@ msgstr "Proposer"
msgid "Date:"
msgstr "Date :"
+#: templates/chimere/detail.html:25
+msgid "Source:"
+msgstr "Source :"
+
#: templates/chimere/detail.html:26
+msgid "License:"
+msgstr "Licence :"
+
+#: templates/chimere/detail.html:28
msgid "Show multimedia gallery"
msgstr "Montrer la galerie multimedia"
-#: templates/chimere/detail.html:30
-msgid "Propose a modification"
+#: templates/chimere/detail.html:32 templates/chimere/detail.html.py:33
+msgid "Propose amendment"
msgstr "Proposer une modification"
+#: templates/chimere/detail.html:32
+msgid "I would like to propose an amendment for this item:"
+msgstr "Je souhaiterai proposer une modification pour cet élément :"
+
#: templates/chimere/edit.html:20
msgid "Error"
msgstr "Erreur"
@@ -991,7 +1060,7 @@ msgstr "Merci pour votre proposition !"
msgid "Upload a file"
msgstr "Déposer un fichier"
-#: templates/chimere/upload_file.html:46
+#: templates/chimere/upload_file.html:47
msgid "Upload"
msgstr "Déposer"
@@ -1078,7 +1147,15 @@ msgstr "Carte"
msgid "Loading of the map in progress"
msgstr "Chargement de la carte en cours"
-#: templates/chimere/blocks/map.html:18
+#: templates/chimere/blocks/map.html:13
+msgid "Display options"
+msgstr "Options d'affichage"
+
+#: templates/chimere/blocks/map.html:15
+msgid "Map type"
+msgstr "Type de carte"
+
+#: templates/chimere/blocks/map.html:24
msgid "Permalink"
msgstr "Lien permanent"
@@ -1233,7 +1310,10 @@ msgstr "Description :"
msgid ":"
msgstr " :"
-#: templatetags/chimere_tags.py:65
+#: templatetags/chimere_tags.py:76
#, python-format
msgid "Welcome to the %s"
msgstr "Bienvenue sur %s"
+
+#~ msgid "Administration de Chimère"
+#~ msgstr "Administration de Chimère"
diff --git a/chimere/management/__init__.py b/chimere/management/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chimere/management/__init__.py
diff --git a/chimere/management/commands/__init__.py b/chimere/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chimere/management/commands/__init__.py
diff --git a/chimere/management/commands/chimere_export.py b/chimere/management/commands/chimere_export.py
new file mode 100644
index 0000000..4e91956
--- /dev/null
+++ b/chimere/management/commands/chimere_export.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import csv
+import datetime, time
+
+from django.core.management.base import BaseCommand, CommandError
+from django.core.exceptions import ObjectDoesNotExist
+
+from chimere import tasks
+from chimere.admin import export_to_csv, export_to_kml, export_to_shapefile
+from chimere.models import Category, SubCategory, Marker, Route
+
+EXPORTER = {'CSV':export_to_csv,
+ 'KML':export_to_kml,
+ 'SHP':export_to_shapefile}
+
+class Command(BaseCommand):
+ args = '<subcategory_id> <CSV|KML|SHP> <marker|route> <filename>'
+ help = "Export items from a subcategory in CSV, KML or ShapeFile"
+
+ def handle(self, *args, **options):
+ subcat = None
+ if args and args[0]:
+ try:
+ subcat = SubCategory.objects.get(pk=int(args[0]))
+ except (ValueError, ObjectDoesNotExist) as e:
+ raise CommandError("Sub-category with ID '%s' doesn't exist." %\
+ args[0])
+ while not subcat:
+ self.stdout.write('Choose a sub-category:\n')
+ for cat in Category.objects.order_by('order'):
+ self.stdout.write('* %s\n' % cat.name)
+ for subcat in cat.subcategories.order_by('order').all():
+ self.stdout.write(' %d - %s\n' % (subcat.pk, subcat.name))
+ self.stdout.write('\nSub-category ID: ')
+ self.stdout.flush()
+ v = raw_input()
+ try:
+ subcat = SubCategory.objects.get(pk=v)
+ except (ValueError, ObjectDoesNotExist) as e:
+ subcat = None
+ self.stdout.write("Sub-category with ID '%s' doesn't exist.\n\n"
+ % v)
+ frmat = None
+ if args and args[1]:
+ try:
+ assert(args[1] in ('CSV', 'KML', 'SHP'))
+ except AssertionError:
+ raise CommandError("'%s' format is not managed." % args[1])
+ frmat = args[1]
+ while frmat not in ('CSV', 'KML', 'SHP'):
+ self.stdout.write('Choose a format (CSV, KML or SHP): ')
+ frmat = raw_input().replace('\n', '')
+ exporter = EXPORTER[frmat]
+ cls = None
+ if args and args[2]:
+ try:
+ assert(args[2] in ('marker', 'route'))
+ except AssertionError:
+ raise CommandError("Exported item must be 'marker' or 'route'."
+ % args[1])
+ if args[2] == 'marker':
+ cls = Marker
+ elif args[2] == 'route':
+ cls = Route
+ while not cls:
+ self.stdout.write('Choose an item type:\n 1 - marker\n 2 - route\n')
+ self.stdout.write('Number: ')
+ v = raw_input()
+ if v == '1':
+ cls = Marker
+ elif v == '2':
+ cls = Route
+ filename = ''
+ if args and args[3]:
+ filename = args[3]
+ else:
+ self.stdout.write('Filename: ')
+ filename = raw_input()
+ response = exporter(None, None, cls.objects.filter(categories=subcat))
+ try:
+ with open(filename, 'w+') as fl:
+ fl.write(response.content)
+ except IOError as e:
+ raise CommandError(e)
diff --git a/chimere/management/commands/chimere_import.py b/chimere/management/commands/chimere_import.py
new file mode 100644
index 0000000..61ccd60
--- /dev/null
+++ b/chimere/management/commands/chimere_import.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import csv
+import datetime, time
+
+from django.core.management.base import BaseCommand, CommandError
+from django.core.exceptions import ObjectDoesNotExist
+
+from chimere.models import Importer
+from chimere import tasks
+
+class Command(BaseCommand):
+ args = '<import_id>'
+ help = "Launch import from an external source. Import configuration must "\
+ "be beforehand inserted in the database with the web admin."
+
+ def handle(self, *args, **options):
+ imports = dict([(imp.pk, imp)
+ for imp in Importer.objects.order_by('pk').all()])
+ imprt = None
+ if args and args[0]:
+ try:
+ imprt = Importer.objects.get(pk=int(args[0]))
+ except (ValueError, ObjectDoesNotExist):
+ raise CommandError("Import with ID '%s' doesn't exist." % \
+ args[0])
+ if not args:
+ while not imprt:
+ self.stdout.write('* Choose the import: \n')
+ for k in imports:
+ self.stdout.write(' %s\n' % unicode(imports[k]).encode(
+ 'ascii', 'ignore'))
+ self.stdout.flush()
+ self.stdout.write('\nImport ID: ')
+ v = raw_input()
+ try:
+ imprt = Importer.objects.get(pk=int(v))
+ except (ValueError, ObjectDoesNotExist):
+ self.stdout.write("Import with ID '%s' doesn't exist.\n\n" \
+ % v)
+ pending_state = unicode(tasks.IMPORT_MESSAGES['import_pending'][0])
+ imprt.state = pending_state
+ imprt.save()
+ tasks.importing(imprt.pk)
+ self.stdout.write("Import '%d' in progress...\n" % imprt.pk)
+ self.stdout.flush()
+ state = pending_state
+ while state == pending_state:
+ time.sleep(1)
+ state = Importer.objects.get(pk=int(imprt.pk)).state
+ self.stdout.write(state + '\n')
+
diff --git a/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py b/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py
index 430cc2e..2f81645 100644
--- a/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py
+++ b/chimere/migrations/0028_auto__add_field_picturefile_thumbnailfile__add_field_picturefile_thumb.py
@@ -23,7 +23,7 @@ class Migration(SchemaMigration):
self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
keep_default=False)
- from chimere. models import picturefile_post_save
+ from chimere.models import picturefile_post_save
for picture in orm.PictureFile.objects.all():
picturefile_post_save(orm.PictureFile, instance=picture,
created=False)
diff --git a/chimere/migrations/0041_auto__add_field_importer_source_file.py b/chimere/migrations/0041_auto__add_field_importer_source_file.py
index 54d7f10..788d12c 100644
--- a/chimere/migrations/0041_auto__add_field_importer_source_file.py
+++ b/chimere/migrations/0041_auto__add_field_importer_source_file.py
@@ -103,7 +103,6 @@ class Migration(SchemaMigration):
'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'}),
- 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
@@ -117,12 +116,6 @@ class Migration(SchemaMigration):
'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.multimediaextension': {
- 'Meta': {'object_name': 'MultimediaExtension'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'multimedia_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extensions'", 'to': "orm['chimere.MultimediaType']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '6'})
- },
'chimere.multimediafile': {
'Meta': {'object_name': 'MultimediaFile'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
@@ -148,18 +141,6 @@ class Migration(SchemaMigration):
'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'}),
- 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
- 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- 'chimere.page': {
- 'Meta': {'object_name': 'Page'},
- 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'content': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'mnemonic': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'default': '10', 'null': 'True', 'blank': 'True'}),
- 'template_path': ('django.db.models.fields.CharField', [], {'max_length': '150', 'null': 'True', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '150'})
},
'chimere.picturefile': {
@@ -193,13 +174,6 @@ class Migration(SchemaMigration):
'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.propertymodelchoice': {
- 'Meta': {'object_name': 'PropertyModelChoice'},
- 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': "orm['chimere.PropertyModel']"}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '150'})
- },
'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'}),
@@ -234,13 +208,9 @@ class Migration(SchemaMigration):
},
'chimere.subcategory': {
'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'},
- 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'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'}),
- 'dated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'hover_icon': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subcat_hovered'", 'null': 'True', 'to': "orm['chimere.Icon']"}),
'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'}),
diff --git a/chimere/migrations/0042_auto__add_field_importer_origin__add_field_importer_license__add_field.py b/chimere/migrations/0042_auto__add_field_importer_origin__add_field_importer_license__add_field.py
new file mode 100644
index 0000000..757deab
--- /dev/null
+++ b/chimere/migrations/0042_auto__add_field_importer_origin__add_field_importer_license__add_field.py
@@ -0,0 +1,274 @@
+# -*- 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 'Importer.origin'
+ db.add_column('chimere_importer', 'origin',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Importer.license'
+ db.add_column('chimere_importer', 'license',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Marker.origin'
+ db.add_column('chimere_marker', 'origin',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Marker.license'
+ db.add_column('chimere_marker', 'license',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Route.origin'
+ db.add_column('chimere_route', 'origin',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+ # Adding field 'Route.license'
+ db.add_column('chimere_route', 'license',
+ self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'Importer.origin'
+ db.delete_column('chimere_importer', 'origin')
+
+ # Deleting field 'Importer.license'
+ db.delete_column('chimere_importer', 'license')
+
+ # Deleting field 'Marker.origin'
+ db.delete_column('chimere_marker', 'origin')
+
+ # Deleting field 'Marker.license'
+ db.delete_column('chimere_marker', 'license')
+
+ # Deleting field 'Route.origin'
+ db.delete_column('chimere_route', 'origin')
+
+ # Deleting field 'Route.license'
+ db.delete_column('chimere_route', 'license')
+
+
+ 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'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'source_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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', [], {'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'thumbnailfile': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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': 'True'}),
+ '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', [], {'default': '1000'}),
+ 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ '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/migrations/0043_area_permissions.py b/chimere/migrations/0043_area_permissions.py
new file mode 100644
index 0000000..d396050
--- /dev/null
+++ b/chimere/migrations/0043_area_permissions.py
@@ -0,0 +1,230 @@
+# -*- 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):
+ from chimere.models import area_post_save
+ for area in orm.Area.objects.all():
+ area_post_save(orm.Area, instance=area, created=False)
+
+ def backwards(self, orm):
+ pass
+
+ 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'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'source_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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', [], {'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'thumbnailfile': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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': 'True'}),
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subcategories'", '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', [], {'default': '1000'}),
+ 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ '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']
diff --git a/chimere/migrations/0044_auto.py b/chimere/migrations/0044_auto.py
new file mode 100644
index 0000000..bb93496
--- /dev/null
+++ b/chimere/migrations/0044_auto.py
@@ -0,0 +1,238 @@
+# -*- 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 M2M table for field areas on 'News'
+ db.create_table('chimere_news_areas', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('news', models.ForeignKey(orm['chimere.news'], null=False)),
+ ('area', models.ForeignKey(orm['chimere.area'], null=False))
+ ))
+ db.create_unique('chimere_news_areas', ['news_id', 'area_id'])
+
+
+ def backwards(self, orm):
+ # Removing M2M table for field areas on 'News'
+ db.delete_table('chimere_news_areas')
+
+
+ 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'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'source_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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'},
+ 'areas': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.Area']", 'symmetrical': 'False'}),
+ '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', [], {'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'thumbnailfile': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'thumbnailfile_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ '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'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'not_for_osm': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ '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': 'True'}),
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subcategories'", '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', [], {'default': '1000'}),
+ 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ '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']
diff --git a/chimere/models.py b/chimere/models.py
index 37355de..357a32a 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -27,22 +27,25 @@ from PIL import Image
from subprocess import Popen, PIPE
from BeautifulSoup import BeautifulSoup
+from django import forms
from django.conf import settings
+from django.contrib import admin
+from django.contrib.auth.models import User, Permission, ContentType, Group
from django.contrib.gis.db import models
from django.contrib.gis.gdal import SpatialReference
-from django.contrib import admin
from django.core.files import File
-from django.core.exceptions import ValidationError
+from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.core.urlresolvers import reverse
+from django.db.models import Q
from django.db.models.signals import post_save, pre_save, m2m_changed
-from django import forms
from django.template import defaultfilters
from django.utils.translation import ugettext_lazy as _
from chimere.widgets import PointField, RouteField, SelectMultipleField, \
TextareaWidget, DatePickerWidget
from chimere.managers import BaseGeoManager
-from chimere.utils import KMLManager, OSMManager, ShapefileManager
+from chimere.utils import KMLManager, OSMManager, ShapefileManager, \
+ GeoRSSManager, CSVManager
class Page(models.Model):
"""Simple extra pages
@@ -102,6 +105,8 @@ class News(models.Model):
date = models.DateField(_(u"Date"), auto_now_add=True)
content = models.TextField()
url = models.URLField(_(u"Url"), max_length=200, blank=True, null=True)
+ areas = SelectMultipleField('Area', verbose_name=_(u"Associated areas"),
+ blank=True, null=True)
def __unicode__(self):
ordering = ["-date"]
return self.title
@@ -202,7 +207,8 @@ class Icon(models.Model):
class SubCategory(models.Model):
'''Sub-category
'''
- category = models.ForeignKey(Category, verbose_name=_(u"Category"))
+ category = models.ForeignKey(Category, verbose_name=_(u"Category"),
+ related_name='subcategories')
name = models.CharField(_(u"Name"), max_length=150)
available = models.BooleanField(_(u"Available"), default=True)
submission = models.BooleanField(_(u"Available for submission"),
@@ -284,14 +290,20 @@ class SubCategory(models.Model):
IMPORTERS = {'KML':KMLManager,
'OSM':OSMManager,
- 'SHP':ShapefileManager
+ 'SHP':ShapefileManager,
+ 'RSS':GeoRSSManager,
+ 'CSV':CSVManager
}
IMPORTER_CHOICES = (('KML', 'KML'),
('OSM', 'OSM'),
('SHP', 'Shapefile'),
+ ('RSS', 'GeoRSS'),
+ ('CSV', 'CSV')
)
+IMPORTER_CHOICES_DICT = dict(IMPORTER_CHOICES)
+
class Importer(models.Model):
'''
Data importer for a specific subcategory
@@ -301,20 +313,34 @@ class Importer(models.Model):
# URL of a KML file or a XAPI service for OSM
source = models.CharField(_(u"Source"), max_length=200,
blank=True, null=True)
+ source_file = models.FileField(_(u"Source file"),
+ upload_to='import_files', blank=True, null=True)
filtr = models.CharField(_(u"Filter"), max_length=200,
blank=True, null=True)
default_name = models.CharField(_(u"Name by default"), max_length=200,
blank=True, null=True)
+ srid = models.IntegerField(_(u"SRID"), blank=True, null=True)
+ zipped = models.BooleanField(_(u"Zipped file"), default=False)
+ origin = models.CharField(_(u"Origin"), max_length=100,
+ blank=True, null=True)
+ license = models.CharField(_(u"License"), max_length=100,
+ blank=True, null=True)
categories = SelectMultipleField(SubCategory,
verbose_name=_(u"Associated subcategories"))
state = models.CharField(_(u"State"), max_length=200,
blank=True, null=True)
- srid = models.IntegerField(_(u"SRID"), blank=True, null=True)
- zipped = models.BooleanField(_(u"Zipped file"), default=False)
class Meta:
verbose_name = _(u"Importer")
+ def __unicode__(self):
+ vals = [IMPORTER_CHOICES_DICT[self.importer_type],
+ self.source, self.source_file.name,
+ u", ".join([unicode(cat) for cat in self.categories.all()]),
+ self.default_name]
+ return u' %d: %s' % (self.pk, u" - ".join([unicode(v)
+ for v in vals if v]))
+
@property
def manager(self):
return IMPORTERS[self.importer_type](self)
@@ -351,6 +377,10 @@ class GeographicItem(models.Model):
default=False)
not_for_osm = models.BooleanField(_(u"Not to be imported inside OSM"),
default=False)
+ origin = models.CharField(_(u"Origin"), max_length=100,
+ blank=True, null=True)
+ license = models.CharField(_(u"License"), max_length=100,
+ blank=True, null=True)
if settings.CHIMERE_DAYS_BEFORE_EVENT:
start_date = models.DateField(_(u"Start date"), blank=True, null=True,
help_text=_(u"Not mandatory. Set it for dated item such as event. "\
@@ -388,6 +418,16 @@ class GeographicItem(models.Model):
def properties(cls):
return [pm for pm in PropertyModel.objects.filter(available=True)]
+def property_setter(cls, propertymodel):
+ def setter(self, value):
+ marker = self
+ if cls == Route:
+ if not self.associated_marker.objects.count():
+ return
+ marker = self.associated_marker.objects.all()[0]
+ marker.setProperty(propertymodel, value)
+ return setter
+
class Marker(GeographicItem):
'''Marker for a POI
'''
@@ -418,6 +458,9 @@ class Marker(GeographicItem):
if property:
val = property.python_value
setattr(self, attr_name, val)
+ if not hasattr(self, attr_name + '_set'):
+ setattr(self, attr_name + '_set',
+ property_setter(self.__class__, pm))
def get_init_multi(self):
multis = [forms.model_to_dict(multi)
@@ -495,31 +538,37 @@ class Marker(GeographicItem):
properties.append(property)
return properties
+ def setProperty(self, pm, value):
+ u"""
+ Set a property
+ """
+ properties = Property.objects.filter(marker=self,
+ propertymodel=pm).all()
+ # in case of multiple edition as the same time delete arbitrary
+ # the others
+ if len(properties) > 1:
+ for property in properties[1:]:
+ property.delete()
+ # new property
+ if not properties:
+ new_property = Property.objects.create(marker=self,
+ propertymodel=pm,
+ value=value)
+ new_property.save()
+ else:
+ property = properties[0]
+ property.value = value
+ property.save()
+
def saveProperties(self, values):
"""
Save properties
"""
for propertymodel in PropertyModel.objects.filter(available=True):
- properties = Property.objects.filter(marker=self,
- propertymodel=propertymodel).all()
- # in case of multiple edition as the same time delete arbitrary
- # the others
- if len(properties) > 1:
- for property in properties[1:]:
- property.delete()
val = u""
if unicode(propertymodel.id) in values:
val = values[unicode(propertymodel.id)]
- # new property
- if not properties:
- new_property = Property.objects.create(marker=self,
- propertymodel=propertymodel,
- value=val)
- new_property.save()
- else:
- property = properties[0]
- property.value = val
- property.save()
+ self.setProperty(propertymodel, val)
def getGeoJSON(self, categories_id=[]):
'''Return a GeoJSON string
@@ -559,6 +608,12 @@ class Marker(GeographicItem):
url = reverse('chimere:tiny', args=[area_name, urn])
return url
+
+PRE_ATTRS = {
+ 'Marker':('name', 'geometry', 'import_version'),
+ 'Route':('name', 'geometry', 'import_version'),
+ 'Area':('urn', 'name'),
+ }
def geometry_pre_save(cls, pre_save_geom_values):
def geom_pre_save(sender, **kwargs):
if not kwargs['instance'] or not kwargs['instance'].pk:
@@ -566,8 +621,8 @@ def geometry_pre_save(cls, pre_save_geom_values):
instance = kwargs['instance']
try:
instance = cls.objects.get(pk=instance.pk)
- pre_save_geom_values[instance.pk] = (instance.name,
- instance.geometry, instance.import_version)
+ pre_save_geom_values[instance.pk] = [getattr(instance, attr)
+ for attr in PRE_ATTRS[cls.__name__]]
except ObjectDoesNotExist:
pass
return geom_pre_save
@@ -826,7 +881,8 @@ post_save.connect(picturefile_post_save, sender=PictureFile)
class RouteFile(models.Model):
name = models.CharField(_(u"Name"), max_length=150)
- raw_file = models.FileField(_(u"Raw file (gpx or kml)"), upload_to='route_files')
+ raw_file = models.FileField(_(u"Raw file (gpx or kml)"),
+ upload_to='route_files')
simplified_file = models.FileField(_(u"Simplified file"),
upload_to='route_files', blank=True, null=True)
TYPE = (('K', _(u'KML')), ('G', _(u'GPX')))
@@ -894,7 +950,7 @@ class Route(GeographicItem):
null=True, height_field='height', width_field='width')
height = models.IntegerField(_(u"Height"), blank=True, null=True)
width = models.IntegerField(_(u"Width"), blank=True, null=True)
- objects = BaseGeoManager()
+ objects = models.GeoManager()
def __unicode__(self):
return self.name
@@ -903,9 +959,31 @@ class Route(GeographicItem):
ordering = ('status', 'name')
verbose_name = _(u"Route")
+ def __init__(self, *args, **kwargs):
+ super(Route, self).__init__(*args, **kwargs)
+ self.description = ''
+ try:
+ associated_marker = Marker.objects.get(route=self)
+ self.description = associated_marker.description
+ except:
+ associated_marker = None
+ # add read attributes for properties
+ for pm in self.properties():
+ attr_name = pm.getAttrName()
+ if not hasattr(self, attr_name):
+ val = ''
+ if associated_marker:
+ property = associated_marker.getProperty(pm)
+ if property:
+ val = property.python_value
+ setattr(self, attr_name, val)
+ if not hasattr(self, attr_name + '_set'):
+ setattr(self, attr_name + '_set',
+ property_setter(self.__class__, pm))
+
@property
def geometry(self):
- return self.point.wkt
+ return self.route.wkt
def get_init_multi(self):
if not self.associated_marker.count():
@@ -1175,20 +1253,34 @@ class Area(models.Model, SimpleArea):
'''
return cls.objects.filter(available=True)
- def getIncludeSql(self, geometry='"chimere_marker".point'):
- """
- Get the sql statement for the test if the point is included in the area
- """
- area = "ST_GeometryFromText('POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f"\
- "))', %d)" % (self.upper_left_corner.x, self.upper_left_corner.y,
+ def getWkt(self):
+ return "SRID=%d;POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f))" % (
+ settings.CHIMERE_EPSG_DISPLAY_PROJECTION,
+ self.upper_left_corner.x, self.upper_left_corner.y,
self.lower_right_corner.x, self.upper_left_corner.y,
self.lower_right_corner.x, self.lower_right_corner.y,
self.upper_left_corner.x, self.lower_right_corner.y,
self.upper_left_corner.x, self.upper_left_corner.y,
- settings.CHIMERE_EPSG_DISPLAY_PROJECTION
)
- sql = "ST_Contains(" + area + ", " + geometry + ")"
- return sql
+
+ def getIncludeMarker(self):
+ """
+ Get the sql statement for the test if the point is included in the area
+ """
+ return Q(point__contained=self.getWkt())
+
+ def getIncludeRoute(self):
+ """
+ Get the sql statement for the test if the route is included in the area
+ """
+ return Q(route__contained=self.getWkt())
+
+pre_save_area_values = {}
+def area_pre_save(sender, **kwargs):
+ if not kwargs['instance']:
+ return
+ geometry_pre_save(Area, pre_save_area_values)(sender, **kwargs)
+pre_save.connect(area_pre_save, sender=Area)
def area_post_save(sender, **kwargs):
if not kwargs['instance']:
@@ -1199,8 +1291,82 @@ def area_post_save(sender, **kwargs):
for default in defaults:
default.default = False
default.save()
+ # manage permissions
+ old_urn, old_name = area.urn, area.name
+ if area.pk in pre_save_area_values:
+ old_urn, old_name = pre_save_area_values[area.pk]
+ perm, old_groups, old_users = None, [], []
+ if area.urn != old_urn:
+ oldmnemo = 'change_area_' + old_urn
+ old_perm = Permission.objects.filter(codename=oldmnemo)
+ if old_perm.count():
+ perm = old_perm.all()[0]
+ perm.codename = 'change_area_' + area.urn
+ perm.save()
+ if not area.urn:
+ area.urn = defaultfilters.slugify(area.name)
+ area.save()
+ mnemo = 'change_area_' + area.urn
+ perm = Permission.objects.filter(codename=mnemo)
+ lbl = "Can change " + area.name
+ if not perm.count():
+ content_type = ContentType.objects.get(app_label="chimere",
+ model="area")
+ perm = Permission(name=lbl, content_type_id=content_type.id,
+ codename=mnemo)
+ perm.save()
+ else:
+ perm = perm.all()[0]
+ if old_name != area.name:
+ perm.name = lbl
+ perm.save()
+ # manage moderation group
+ groupname = area.name + " moderation"
+ if old_name != area.name:
+ old_groupname = old_name + " moderation"
+ old_gp = Group.objects.filter(name=old_groupname)
+ if old_gp.count():
+ old_gp = old_gp.all()[0]
+ old_gp.name = groupname
+ old_gp.save()
+ group = Group.objects.filter(name=groupname)
+ if not group.count():
+ group = Group.objects.create(name=groupname)
+ group.permissions.add(perm)
+ for app_label, model in (('chimere', 'marker'),
+ ('chimere', 'route'),
+ ('chimere', 'multimediafile'),
+ ('chimere', 'picturefile'),
+ ('chimere', 'routefile')):
+ ct = ContentType.objects.get(app_label=app_label, model=model)
+ for p in Permission.objects.filter(content_type=ct).all():
+ group.permissions.add(p)
+
post_save.connect(area_post_save, sender=Area)
+def get_areas_for_user(user):
+ """
+ Getting subcats for a specific user
+ """
+ perms = user.get_all_permissions()
+ areas = set()
+ prefix = 'chimere.change_area_'
+ for perm in perms:
+ if perm.startswith(prefix):
+ try:
+ area = Area.objects.get(urn=perm[len(prefix):])
+ areas.add(area)
+ except ObjectDoesNotExist:
+ pass
+ return areas
+
+def get_users_by_area(area):
+ if not area:
+ return []
+ perm = 'change_area_'+area.urn
+ return User.objects.filter(Q(groups__permissions__codename=perm)|
+ Q(user_permissions__codename=perm)).all()
+
class AreaLayers(models.Model):
area = models.ForeignKey(Area)
layer = models.ForeignKey(Layer)
diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css
index 120e062..43dc3c6 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -329,6 +329,11 @@ ul#action-2 {
max-width:280px;
}
+#detail_content p{
+ padding:0.2em 0;
+ margin:0;
+}
+
ul.share{
list-style-type:none;
margin:0;
@@ -577,6 +582,7 @@ ul.share li{
.simple #panel{
top:5px;
+ bottom:auto;
}
@@ -586,24 +592,30 @@ ul.share li{
z-index:5;
}
-/*.panel-minified {*/
#panel{
bottom:None;
+ height:auto;
}
#panel.panel-minified #categories > ul{
height:160px;
overflow:auto;
- /*width:285px;*/
}
+.simple #panel.panel-minified #categories > ul{
+ height:auto;
+}
+
+
#panel.panel-minified{
height:200px;
bottom:auto;
overflow:visible;
}
-
+.simple #panel.panel-minified{
+ height:auto;
+}
.simple #panel #categories{
display:None;
diff --git a/chimere/static/chimere/js/edit_area.js b/chimere/static/chimere/js/edit_area.js
index f22d6e3..9c3384f 100644
--- a/chimere/static/chimere/js/edit_area.js
+++ b/chimere/static/chimere/js/edit_area.js
@@ -18,12 +18,25 @@ See the file COPYING for details.
/* area edit */
+var bbox_style = {fill: true, fillColor: "#FFFFFF", fillOpacity: 0.5,
+ stroke: true, strokeOpacity: 0.8, strokeColor: "#FF0000", strokeWidth: 2};
+
var map;
+var box_layer;
+
+function initForm(bounds){
+
+}
-/* update form fields on zoom action */
-function updateForm(){
- var bounds = map.getExtent().transform(epsg_projection,
- epsg_display_projection);
+/* update form fields on select action */
+function updateForm(bounds){
+ if(!bounds.toGeometry) return;
+ var feature = new OpenLayers.Feature.Vector(
+ bounds.toGeometry(), {}, bbox_style);
+ box_layer.destroyFeatures()
+ box_layer.addFeatures(feature);
+ var bounds = bounds.clone().transform(epsg_projection,
+ epsg_display_projection);
document.getElementById('upper_left_lat').value = bounds.top;
document.getElementById('upper_left_lon').value = bounds.left;
document.getElementById('lower_right_lat').value = bounds.bottom;
@@ -34,15 +47,40 @@ function updateForm(){
function init(){
map = new OpenLayers.Map ('map_edit', {
controls:[new OpenLayers.Control.Navigation(),
- new OpenLayers.Control.PanPanel(),
- new OpenLayers.Control.ZoomPanel(),
- new OpenLayers.Control.Attribution()],
+ new OpenLayers.Control.SimplePanZoom()],
maxResolution: 156543.0399,
units: 'm',
projection: epsg_projection,
displayProjection: epsg_display_projection
} );
- map.addLayers([map_layer]);
+ box_layer = new OpenLayers.Layer.Vector("Box layer");
+ map.addLayers([map_layer, box_layer]);
+ var selectControl = new OpenLayers.Control();
+ OpenLayers.Util.extend(selectControl, {
+ draw: function() {
+ this.box = new OpenLayers.Handler.Box(selectControl,
+ {'done': this.notice},
+ {keyMask: navigator.platform.match(/Mac/) ?
+ OpenLayers.Handler.MOD_ALT :OpenLayers.Handler.MOD_CTRL});
+ this.box.activate();
+ },
+
+ notice: function(pxbounds) {
+ ltpixel = map.getLonLatFromPixel(
+ new OpenLayers.Pixel(pxbounds.left, pxbounds.top));
+ rbpixel = map.getLonLatFromPixel(
+ new OpenLayers.Pixel(pxbounds.right, pxbounds.bottom));
+ if (ltpixel.equals(rbpixel))
+ return;
+ if (!ltpixel || !rbpixel) return;
+ bounds = new OpenLayers.Bounds();
+ bounds.extend(ltpixel);
+ bounds.extend(rbpixel);
+ updateForm(bounds);
+ }
+ });
+ map.addControl(selectControl);
+
map.events.register('zoomend', map, updateForm);
map.events.register('moveend', map, updateForm);
/* zoom to the appropriate extent */
diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js
index 9889367..e2aa6b2 100644
--- a/chimere/static/chimere/js/jquery.chimere.js
+++ b/chimere/static/chimere/js/jquery.chimere.js
@@ -1348,6 +1348,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {
saveExtent: function(){
var extent_key = 'MAP_EXTENT';
//if (area_name){ extent_key = extent_key + '_' + area_name; }
+ if (!settings.map) return;
var extent = settings.map.getExtent().transform(EPSG_PROJECTION,
EPSG_DISPLAY_PROJECTION);
document.cookie = extent_key + "=" + extent.toArray().join('_')
diff --git a/chimere/static/chimere/js/menu-sort.js b/chimere/static/chimere/js/menu-sort.js
index ad1da39..37d0ddd 100644
--- a/chimere/static/chimere/js/menu-sort.js
+++ b/chimere/static/chimere/js/menu-sort.js
@@ -11,10 +11,14 @@ jQuery(function($) {
}
});
$('div.inline-group tbody tr').css('cursor', 'move');
- $('div.inline-group tbody tr td').each(function (idx){
- if($(this).is('*.field-order')){
- $(this).hide();
- $('div.inline-group thead th:nth-child('+idx+')').hide();
- }
+ $('div.inline-group').each(function(){
+ var par = $(this);
+ par.find('tbody tr td').each(
+ function (idx){
+ if($(this).is('*.field-order')){
+ $(this).hide();
+ par.find('thead th:nth-child('+idx+')').hide();
+ }
+ });
});
});
diff --git a/chimere/static/chimere/js/textareas.js b/chimere/static/chimere/js/textareas.js
index e15e7f2..22b68c8 100644
--- a/chimere/static/chimere/js/textareas.js
+++ b/chimere/static/chimere/js/textareas.js
@@ -16,13 +16,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
See the file COPYING for details.
*/
-
-tinyMCE.init({
- mode : "textareas",
- theme : "advanced",
- editor_selector : "mceEditor",
- relative_urls : false,
- theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,hr,separator,link,image",
- theme_advanced_buttons2 : "",
- theme_advanced_buttons3 : ""
-});
+if (!window.tinymce_init){
+ window.tinymce_init = true;
+ tinyMCE.init({
+ mode : "textareas",
+ theme : "advanced",
+ editor_selector : "mceEditor",
+ relative_urls : false,
+ theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,hr,separator,link",
+ theme_advanced_buttons2 : "",
+ theme_advanced_buttons3 : ""
+ })
+};
diff --git a/chimere/static/chimere/js/textareas_admin.js b/chimere/static/chimere/js/textareas_admin.js
new file mode 100644
index 0000000..7acec97
--- /dev/null
+++ b/chimere/static/chimere/js/textareas_admin.js
@@ -0,0 +1,30 @@
+/* base function shared by some pages */
+/* Copyright (C) 2009 É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.
+*/
+if (!window.tinymce_init){
+ window.tinymce_init = true;
+ tinyMCE.init({
+ mode : "textareas",
+ theme : "advanced",
+ editor_selector : "mceEditor",
+ relative_urls : false,
+ theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,hr,separator,link,image",
+ theme_advanced_buttons2 : "",
+ theme_advanced_buttons3 : ""
+ });
+};
diff --git a/chimere/templates/admin/base_site.html b/chimere/templates/admin/base_site.html
index fa537ef..d0cf4bf 100644
--- a/chimere/templates/admin/base_site.html
+++ b/chimere/templates/admin/base_site.html
@@ -1,10 +1,10 @@
{% extends "admin/base.html" %}
{% load i18n %}
-{% block title %}{{ title }} | {% trans 'Administration de Chimère' %}{% endblock %}
+{% block title %}{{ title }} | {% trans 'Chimère administration' %}{% endblock %}
{% block branding %}
-<h1 id="site-name">{% trans 'Administration de Chimère' %}</h1>
+<h1 id="site-name">{% trans 'Chimère administration' %}</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html
index b03dcf2..858a7ae 100644
--- a/chimere/templates/chimere/detail.html
+++ b/chimere/templates/chimere/detail.html
@@ -22,17 +22,18 @@
{% for property in marker.getProperties %}
<p id='{{property.propertymodel.getNamedId}}'>{{ property.value|sanitize:"p b i br hr strong em img:src:alt span:style a:href:target ul li ol h1 h2 h3 h4 table td tr th"|safe}}</p>
{% endfor %}
+ {% if marker.origin %}<p class='detail_source'><strong>{% trans "Source:" %}</strong> <span>{{marker.origin}}</span></p>{% endif %}
+ {% if marker.license %}<p class='detail_license'><strong>{% trans "License:" %}</strong> <span>{{marker.license}}</span></p>{% endif %}
{% if marker.multimedia_items %}
<a href='#' id='show_gallery_link'>{% trans "Show multimedia gallery" %}</a>
{% endif %}
</div>
+ {% if moderator_emails %}
+ <a href="mailto:?from={{moderator_emails}}&subject={% trans "Propose amendment" %}&body={% trans "I would like to propose an amendment for this item:"%} {{share_url}}">
+ {% trans "Propose amendment" %}
+ </a>{%endif%}
{% share_bar marker.name %}
- <a href="{{modif_by_email}}">{% trans "Propose a modification" %}</a>
- {% comment %}
- <a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'>
- {% trans "Submit a modification" %}
- </a>
- {% endcomment %}
+{% endif %}
</div>
{% if marker.multimedia_items %}
<div id='gallery-{{marker.pk}}' class='gallery'>
diff --git a/chimere/templates/chimere/export_marker.csv b/chimere/templates/chimere/export.csv
index 619b872..619b872 100644
--- a/chimere/templates/chimere/export_marker.csv
+++ b/chimere/templates/chimere/export.csv
diff --git a/chimere/templates/chimere/export.kml b/chimere/templates/chimere/export.kml
index 55d671d..b59bc7c 100644
--- a/chimere/templates/chimere/export.kml
+++ b/chimere/templates/chimere/export.kml
@@ -10,7 +10,8 @@
{% if location.description %}<description>
<![CDATA[{{ location.description|safe }}]]>
</description>{% endif %}
- {{location.point.kml|safe}}
+ {% if location.point %}{{location.point.kml|safe}}{% endif %}
+ {% if location.route %}{{location.route.kml|safe}}{% endif %}
</Placemark>
{% endfor %}
diff --git a/chimere/templates/chimere/upload_file.html b/chimere/templates/chimere/upload_file.html
index b0fbafc..91a1444 100644
--- a/chimere/templates/chimere/upload_file.html
+++ b/chimere/templates/chimere/upload_file.html
@@ -22,6 +22,7 @@
<div class="fieldWrapper">
{% if gpx_id %}
<script type="text/javascript"><!--
+jQuery(document).ready(function() {
jQuery.get("{% url chimere:process_route_file gpx_id %}", function(data) {
var data = eval(data);
var main_page = opener.document;
@@ -36,9 +37,9 @@
opener.focus();
self.close();
}).error(function (xhr, ajaxOptions, thrownError){
- alert(xhr.status);
- alert(thrownError);
+ alert(xhr.responseText);
} );
+});
// --></script>
{% else %}
<form enctype="multipart/form-data" method='post' action='.'>
diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py
index 78e148a..084904f 100644
--- a/chimere/templatetags/chimere_tags.py
+++ b/chimere/templatetags/chimere_tags.py
@@ -9,7 +9,7 @@ from django import template
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
-from django.db.models import Q
+from django.db.models import Q, Count
from django.template import defaultfilters
from django.utils.translation import ugettext as _
@@ -40,9 +40,12 @@ def submited(context):
return {"edit_url":reverse('chimere:edit'),
"index_url":reverse('chimere:index')}
-def get_news():
+def get_news(area=None):
# Retrieve news
- news = list(News.objects.filter(available=True, is_front_page=True))
+ news = News.objects.filter(available=True, is_front_page=True)
+ if area:
+ news = news.filter(Q(areas__isnull=True)|Q(areas__in=[area.pk]))
+ news = list(news.all())
if settings.CHIMERE_DAYS_BEFORE_EVENT:
# Retrieve active markers
today = date.today()
@@ -59,10 +62,7 @@ def display_welcome(context, display=False, title=''):
Welcome message and active news.
"""
context_data = {'display':display}
- context_data['news_lst'] = get_news()[:3]
- context_data['STATIC_URL'] = settings.STATIC_URL
- context_data['title'] = title if title \
- else _(u"Welcome to the %s") % settings.PROJECT_NAME
+ area = None
if "area_name" in context:
try:
area = Area.objects.get(urn=context["area_name"])
@@ -70,6 +70,10 @@ def display_welcome(context, display=False, title=''):
context_data['welcome_message'] = area.welcome_message
except ObjectDoesNotExist:
pass
+ context_data['news_lst'] = get_news(area)[:3]
+ context_data['STATIC_URL'] = settings.STATIC_URL
+ context_data['title'] = title if title \
+ else _(u"Welcome to the %s") % settings.PROJECT_NAME
return context_data
@register.inclusion_tag('chimere/blocks/news.html', takes_context=True)
@@ -77,7 +81,15 @@ def display_news(context, title=''):
"""
All news.
"""
- context_data = {'news_lst': get_news(),
+ area = None
+ if "area_name" in context:
+ try:
+ area = Area.objects.get(urn=context["area_name"])
+ context_data['area_name'] = context['area_name']
+ context_data['welcome_message'] = area.welcome_message
+ except ObjectDoesNotExist:
+ pass
+ context_data = {'news_lst': get_news(area),
'STATIC_URL':settings.STATIC_URL}
return context_data
diff --git a/chimere/tests.py b/chimere/tests.py
index b3ad3fb..ddd59b1 100644
--- a/chimere/tests.py
+++ b/chimere/tests.py
@@ -117,7 +117,7 @@ class KMLImporterTest(TestCase, ImporterTest):
source=test_dir_path+'tests/sample.kml.zip', zipped=True)
importer4.categories.add(subcategory_1)
- self.marker_importers = [(importer1, 1), (importer2, 2), (importer3, 0),
+ self.marker_importers = [(importer1, 1), (importer2, 3), (importer3, 0),
(importer4, 4)]
class ShapefileImporterTest(TestCase, ImporterTest):
@@ -152,6 +152,15 @@ class OSMImporterTest(TestCase, ImporterTest):
self.marker_importers = [(importer1, 19), (importer2, 8)]
+class GeoRSSImporterTest(TestCase, ImporterTest):
+ def setUp(self):
+ subcategory_1, subcategory_2 = subcategory_setup()
+ importer1 = Importer.objects.create(importer_type='RSS',
+ source=test_dir_path+'tests/georss.xml')
+ importer1.categories.add(subcategory_1)
+
+ self.marker_importers = [(importer1, 1)]
+
class FeedsTest(TestCase):
def setUp(self):
self.area = area_setup()
diff --git a/chimere/tests/georss.xml b/chimere/tests/georss.xml
new file mode 100644
index 0000000..8697f16
--- /dev/null
+++ b/chimere/tests/georss.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:georss="http://www.georss.org/georss">
+ <title>Earthquakes</title>
+ <subtitle>International earthquake observation labs</subtitle>
+ <link href="http://example.org/"/>
+ <updated>2005-12-13T18:30:02Z</updated>
+ <author>
+ <name>Dr. Thaddeus Remor</name>
+ <email>tremor@quakelab.edu</email>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <entry>
+ <title>M 3.2, Mona Passage</title>
+ <link href="http://example.org/2005/09/09/atom01"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2005-08-17T07:02:32Z</updated>
+ <summary>We just had a big one.</summary>
+ <georss:point>45.256 -71.92</georss:point>
+ </entry>
+</feed>
diff --git a/chimere/tests/sample.kml b/chimere/tests/sample.kml
index 665d861..cc9f108 100644
--- a/chimere/tests/sample.kml
+++ b/chimere/tests/sample.kml
@@ -35,6 +35,16 @@
<coordinates>-4.69242,48.57501,0</coordinates>
</Point>
</Placemark>
+ <Placemark id='4'>
+ <name>Place 22</name>
+ <Snippet>snippet</Snippet>
+ <description>Place 44 description</description>
+ <LineString>
+ <coordinates>-112.0814237830345,36.10677870477137,0
+ -112.0870267752693,36.0905099328766,0
+ </coordinates>
+ </LineString>
+ </Placemark>
</Folder>
</Folder>
<Folder>
diff --git a/chimere/utils.py b/chimere/utils.py
index 4cd6f45..75c0ad4 100644
--- a/chimere/utils.py
+++ b/chimere/utils.py
@@ -23,6 +23,7 @@ Utilitaries
import csv
import datetime
+import feedparser
import os
import re
import StringIO
@@ -69,16 +70,21 @@ class ImportManager:
def put(self):
pass
- def create_or_update_item(self, cls, values, import_key, version=None):
+ def create_or_update_item(self, cls, values, import_key, version=None,
+ key='', pk=None):
updated, created, item = False, False, None
- if import_key:
+ import_key = unicode(import_key).replace(':', '^')
+ if not key:
+ key = self.importer_instance.importer_type
+ if import_key or pk:
dct_import = {
- 'import_key__icontains':'%s:%s;' % (
- self.importer_instance.importer_type,
- import_key),
+ 'import_key__icontains':'%s:%s;' % (key, import_key),
'import_source':self.importer_instance.source}
try:
- item = cls.objects.get(**dct_import)
+ if pk:
+ item = cls.objects.get(pk=pk)
+ else:
+ item = cls.objects.get(**dct_import)
if version and item.import_version == int(version):
# no update since the last import
return item, None, None
@@ -103,8 +109,7 @@ class ImportManager:
return None, False, False
created = True
if import_key:
- item.set_key(self.importer_instance.importer_type,
- import_key)
+ item.set_key(key, import_key)
item.categories.clear()
for cat in self.importer_instance.categories.all():
item.categories.add(cat)
@@ -138,8 +143,9 @@ class ImportManager:
files.append(None)
return files
- def get_source_file(self, source, suffixes, dest_dir=None,
+ def get_source_file(self, suffixes, dest_dir=None,
extra_url=None):
+ source = self.importer_instance.source_file
if not hasattr(source, 'read'):
if not source:
source = self.importer_instance.source \
@@ -157,7 +163,7 @@ class ImportManager:
source = open(source)
except IOError, msg:
return (None, msg)
- except urllib2.URLError as error:
+ except (urllib2.URLError, AttributeError) as error:
return (None, error.message)
if self.importer_instance.zipped:
try:
@@ -182,21 +188,18 @@ class KMLManager(ImportManager):
self.importer_instance = importer_instance
self.ns = ns
- def get(self, source=None):
+ def get(self):
u"""
- Get data from the source
- Args:
- - source (None): input file if not provided get it from the distant
- source provided in the importer instance.
+ Get data from a KML source
Return a tuple with:
- number of new item ;
- number of item updated ;
- error detail on error
"""
- from models import Marker
+ from models import Marker, Route
new_item, updated_item, msg = 0, 0, ''
- source, msg = self.get_source_file(source, ['.kml'])
+ source, msg = self.get_source_file(['.kml'])
if msg:
return (0, 0, msg)
doc = source
@@ -207,7 +210,10 @@ class KMLManager(ImportManager):
if line.strip():
break
doc = StringIO.StringIO("\n".join(splitted[idx:]))
- tree = etree.parse(doc)
+ try:
+ tree = etree.parse(doc)
+ except:
+ return (0, 0, _(u"Bad XML file"))
# try to get default namespace
if not self.ns:
self.ns = tree.getroot().nsmap[None]
@@ -215,7 +221,7 @@ class KMLManager(ImportManager):
if self.importer_instance.filtr else self.DEFAULT_XPATH
for placemark in tree.xpath(xpath,
namespaces={'kml':self.ns}):
- name, point = None, None
+ name, point, line = None, None, None
pl_id = placemark.attrib.get('id')
pl_key = 'kml-%d' % self.importer_instance.pk
ns = '{%s}' % self.ns
@@ -232,34 +238,32 @@ class KMLManager(ImportManager):
if coord.tag == ns + 'coordinates':
x, y, z = coord.text.split(',')
point = 'SRID=4326;POINT(%s %s)' % (x, y)
+ elif item.tag == ns + 'LineString':
+ for coord in item:
+ if coord.tag == ns + 'coordinates':
+ points = coord.text.replace('\n', ' ').split(' ')
+ points = ",".join([" ".join(p.split(',')[:2])
+ for p in points if p])
+ line = 'SRID=4326;LINESTRING(%s)' % points
+ cls = None
+ dct = {'description':description,
+ 'name':name,
+ 'origin':self.importer_instance.origin,
+ 'license':self.importer_instance.license}
if point:
- dct = {'point':point,
- 'description':description,
- 'name':name,}
- m = None
- if pl_id:
- dct_import = {
- 'import_key__icontains':'%s:%s;' % (pl_key, pl_id),
- 'import_source':self.importer_instance.source}
- try:
- m = Marker.objects.get(**dct_import)
- for k in dct:
- setattr(m, k, dct[k])
- m.save()
- updated_item += 1
- except ObjectDoesNotExist:
- m = None
- dct.update({
- 'import_source':self.importer_instance.source})
- if not m:
- dct['status'] = 'I'
- m = Marker.objects.create(**dct)
+ dct['point'] = point
+ cls = Marker
+ if line:
+ dct['route'] = line
+ dct.pop('description')
+ cls = Route
+ if cls:
+ item, updated, created = self.create_or_update_item(
+ cls, dct, pl_id, key=pl_key)
+ if updated:
+ updated_item += 1
+ if created:
new_item += 1
- if pl_id:
- m.set_key(pl_key, pl_id)
- m.categories.clear()
- for cat in self.importer_instance.categories.all():
- m.categories.add(cat)
return (new_item, updated_item, msg)
@classmethod
@@ -277,12 +281,9 @@ class ShapefileManager(ImportManager):
u"""
Shapefile importer
"""
- def get(self, source=None):
+ def get(self):
u"""
- Get data from the source
- Args:
- - source (None): input file if not provided get it from the distant
- source provided in the importer instance.
+ Get data from a Shapefile source
Return a tuple with:
- number of new item ;
@@ -292,8 +293,7 @@ class ShapefileManager(ImportManager):
from models import Marker, Route
new_item, updated_item, msg = 0, 0, ''
tmpdir = tempfile.mkdtemp()
- sources, msg = self.get_source_file(source,
- ['.shp', '.dbf', '.prj', '.shx'],
+ sources, msg = self.get_source_file(['.shp', '.dbf', '.prj', '.shx'],
dest_dir=tmpdir)
if msg:
return (0, 0, msg)
@@ -350,13 +350,18 @@ class ShapefileManager(ImportManager):
name.decode(settings.CHIMERE_SHAPEFILE_ENCODING))
except:
continue
- geoms = [feat.geom.wkt]
+ try:
+ geoms = [feat.geom.wkt]
+ except:
+ return (0, 0, _(u"Bad Shapefile"))
if feat.geom.geom_type == 'MultiLineString':
geoms = [geom.wkt for geom in feat.geom]
import_key = feat.get(id_name) if id_name and len(geoms) == 1 else ''
for geom in geoms:
dct = {geom_key:'SRID=%s;%s' % (srid, geom),
- 'name':name
+ 'name':name,
+ 'origin':self.importer_instance.origin,
+ 'license':self.importer_instance.license
}
item, updated, created = self.create_or_update_item(
geom_cls, dct, import_key)
@@ -441,26 +446,91 @@ class CSVManager(ImportManager):
u"""
CSV importer
"""
- _COLS = [("Id", 'pk'), (_(u"Name"), 'name'),
+ @classmethod
+ def set_categories(value):
+ return
+
+ # (label, getter, setter)
+ COLS = [("Id", 'pk', 'pk'), (_(u"Name"), 'name', 'name'),
(_(u"Categories"), lambda obj:", ".join(
- [c.name for c in obj.categories.all()])),
- (_(u"State"), 'status')]
- COLS = {'marker':_COLS+[(_(u"Description"), 'description'),
- (_(u"Localisation"), lambda obj: obj.point.wkt)],
- 'route':_COLS+[(_(u"Localisation"), lambda obj: obj.route.wkt)]}
+ [c.name for c in obj.categories.all()]),
+ set_categories),
+ (_(u"State"), 'status', lambda x: x),
+ (_(u"Description"), 'description', 'description'),
+ (_(u"Localisation"), 'geometry', 'geometry')]
+
+ def get(self):
+ u"""
+ Get data from a CSV source
+
+ Return a tuple with:
+ - number of new item ;
+ - number of item updated ;
+ - error detail on error
+ """
+ from models import Marker, Route
+ new_item, updated_item, msg = 0, 0, ''
+ source, msg = self.get_source_file(['.csv'])
+ if msg:
+ return (0, 0, msg)
+ reader = csv.reader(source, delimiter=';', quotechar='"')
+ prop_cols = []
+ for pm in Marker.properties():
+ prop_cols.append((pm.name, pm.getAttrName(),
+ pm.getAttrName()+'_set'))
+ cols = self.COLS + prop_cols
+ datas = []
+ for idx, row in enumerate(reader):
+ if not idx: # first row
+ try:
+ assert(len(row) >= len(cols))
+ except AssertionError:
+ return (0, 0, _(u"Invalid CSV format"))
+ continue
+ if len(row) < len(cols):
+ continue
+ pk, name, cats, state = row[0], row[1], row[2], row[3]
+ description, geom = row[4], row[5]
+ COL_INDEX = 6
+ dct = {'description':description,
+ 'name':name,
+ 'origin':self.importer_instance.origin,
+ 'license':self.importer_instance.license}
+ cls = None
+ if 'POINT' in geom:
+ cls = Marker
+ dct['point'] = geom
+ elif 'LINE' in geom:
+ cls = Route
+ dct['route'] = geom
+ else:
+ continue
+ import_key = pk if pk else name
+ item, updated, created = self.create_or_update_item(cls, dct,
+ import_key, pk=pk)
+ if updated:
+ updated_item += 1
+ if created:
+ new_item += 1
+ for idx, col in enumerate(cols[COL_INDEX:]):
+ name, getter, setter_val = col
+ setter = getattr(item, setter_val)
+ val = row[idx+COL_INDEX]
+ setter(item, val)
+ return (new_item, updated_item, msg)
@classmethod
def export(cls, queryset):
dct = {'description':unicode(datetime.date.today()), 'data':[]}
cls_name = queryset.model.__name__.lower()
- cols = cls.COLS[cls_name][:]
+ cols = cls.COLS
for pm in queryset.model.properties():
- cols.append((pm.name, pm.getAttrName()))
- header = [lbl for lbl, attr in cols]
+ cols.append((pm.name, pm.getAttrName(), pm.getAttrName()+'_set'))
+ header = [col[0] for col in cols]
dct['data'].append(header)
for item in queryset.all():
data = []
- for lbl, attr in cols:
+ for (lbl, attr, setr) in cols:
if callable(attr):
data.append(attr(item))
else:
@@ -468,9 +538,66 @@ class CSVManager(ImportManager):
dct['data'].append(data)
filename = unicode_normalize(settings.PROJECT_NAME + dct['description']\
+ '.csv')
- result = render_to_response('chimere/export_%s.csv' % cls_name, dct)
+ result = render_to_response('chimere/export.csv', dct)
return filename, result
+class GeoRSSManager(ImportManager):
+ u"""
+ RSS importer.
+ This manager only gets and do not produce GeoRSSFeed
+ """
+
+ def get(self):
+ u"""
+ Get data from a GeoRSS simple source
+
+ Return a tuple with:
+ - number of new item ;
+ - number of item updated ;
+ - error detail on error
+ """
+ from models import Marker
+ new_item, updated_item, msg = 0, 0, ''
+ feed = feedparser.parse(self.importer_instance.source)
+ if feed['bozo']:
+ return (0, 0, _(u"RSS feed is not well formed"))
+ for item in feed['items']:
+ if "georss_point" not in item and 'georss_line' not in item:
+ continue
+ cls = None
+ dct = {'origin':self.importer_instance.origin,
+ 'license':self.importer_instance.license}
+ if 'georss_point' in item:
+ cls = Marker
+ try:
+ y, x = item['georss_point'].split(' ')
+ except ValueError:
+ continue
+ dct['point'] = 'SRID=4326;POINT(%s %s)' % (x, y)
+ for k in ['description', 'summary', 'value']:
+ if k in item:
+ dct['description'] = item[k]
+ break
+ else:
+ cls = Route
+ points = item['georss_line'].split(' ')
+ reordered_points = []
+ # lat, lon -> x, y
+ for idx in xrange(len(points)/2):
+ reordered_points.append("%s %s" % (points[idx*2+1],
+ points[idx*2]))
+ dct['route'] = 'SRID=4326;LINESTRING(%s)' % \
+ ",".join(reordered_points)
+
+ dct['name'] = item['title']
+ pl_id = item['id'] if 'id' in item else item['title']
+ it, updated, created = self.create_or_update_item(cls, dct, pl_id)
+ if updated:
+ updated_item += 1
+ if created:
+ new_item += 1
+ return (new_item, updated_item, msg)
+
RE_HOOK = re.compile('\[([^\]]*)\]')
# TODO: manage deleted item from OSM
@@ -483,19 +610,16 @@ class OSMManager(ImportManager):
"""
default_source = settings.CHIMERE_XAPI_URL
- def get(self, source=None):
+ def get(self):
u"""
Get data from the source
- Args:
- - source (None): input file if not provided get it from the distant
- source provided in the importer instance.
Return a tuple with:
- new items;
- updated items;
- error detail on error.
"""
- source, msg = self.get_source_file(source, ['.osm'],
+ source, msg = self.get_source_file(['.osm'],
extra_url=self.importer_instance.filtr)
if not source:
return (0, 0, msg)
@@ -538,6 +662,10 @@ class OSMManager(ImportManager):
for point_id in points if point_id in nodes])
dct = {'route':wkt,
'name':name,
+ 'origin':self.importer_instance.origin \
+ or u'OpenStreetMap.org',
+ 'license':self.importer_instance.license \
+ or u'ODbL',
'import_version':version}
item, updated, created = self.create_or_update_item(
Route, dct, node_id, version)
@@ -567,6 +695,10 @@ class OSMManager(ImportManager):
node.get('lat'))
dct = {'point':point,
'name':name,
+ 'origin':self.importer_instance.origin \
+ or u'OpenStreetMap.org',
+ 'license':self.importer_instance.license \
+ or u'ODbL',
'import_version':version}
item, updated, created = self.create_or_update_item(
Marker, dct, node_id, version)
diff --git a/chimere/views.py b/chimere/views.py
index 7c983a3..fdc4da0 100644
--- a/chimere/views.py
+++ b/chimere/views.py
@@ -294,6 +294,9 @@ def edit(request, area_name="", item_id=None, submited=False):
declared_fields = PropertyModel.objects.filter(available=True).all()
filtered_properties = PropertyModel.objects.filter(available=True,
subcategories__id__isnull=False).all()
+ point_value = init_item.point if init_item else None
+ if request.POST and request.POST.get('point'):
+ point_value = request.POST.get('point')
response_dct.update({
'actions':actions(response_dct['area_name']),
'action_selected':('contribute', 'edit'),
@@ -306,7 +309,7 @@ def edit(request, area_name="", item_id=None, submited=False):
'marker_id':item_id,
'sub_categories':sub_categories,
'point_widget':PointChooserWidget().render('point',
- init_item.point if init_item else None,
+ point_value,
area_name=response_dct['area_name']),
'properties':declared_fields,
'filtered_properties':filtered_properties,
@@ -377,8 +380,8 @@ def processRouteFile(request, area_name='', file_id=None):
return HttpResponse('('+simplejson.dumps({'wkt':route,
'file_id':file_id})+')',
'application/javascript', status=200)
- except:
- return HttpResponse(status=500)
+ except OSError as e:
+ return HttpResponse(e.strerror, status=500)
else:
return HttpResponse(status=400)
@@ -399,6 +402,9 @@ def editRoute(request, area_name="", item_id=None, submited=False):
declared_fields = form.declared_fields.keys()
if 'description' in declared_fields:
declared_fields.pop(declared_fields.index('description'))
+ route_value = init_item.route if init_item else None
+ if request.POST and request.POST.get('route'):
+ route_value = request.POST.get('route')
response_dct.update({
'actions':actions(response_dct['area_name']),
'action_selected':('contribute', 'edit-route'),
@@ -410,8 +416,7 @@ def editRoute(request, area_name="", item_id=None, submited=False):
'dated':settings.CHIMERE_DAYS_BEFORE_EVENT,
'extra_head':form.media,
'sub_categories':sub_categories,
- 'route_widget':RouteChooserWidget().render('route',
- init_item.route if init_item else None,
+ 'route_widget':RouteChooserWidget().render('route', route_value,
area_name=response_dct['area_name'], routefile_id='',),
'properties':declared_fields,
'submited':submited
@@ -422,28 +427,6 @@ def editRoute(request, area_name="", item_id=None, submited=False):
return render_to_response('chimere/edit_route.html', response_dct,
context_instance=RequestContext(request))
-def welcome(request, display=None):
- """
- Welcome string
- """
- response_dct = {'display':display}
- news = list(News.objects.filter(available=True, is_front_page=True).all())
- if settings.CHIMERE_DAYS_BEFORE_EVENT:
- q = checkDate(Q(status='A', start_date__isnull=False,
- is_front_page=True))
- news += list(Marker.objects.filter(q).all())
- news.sort(key=lambda x:x.date, reverse=True)[:3]
- response_dct['news_lst'] = news
- if "area_name" in context:
- try:
- area = Area.objects.get(urn=context["area_name"])
- context_data['area_name'] = context['area_name']
- context_data['welcome_message'] = area.welcome_message
- except ObjectDoesNotExist:
- pass
- return loader.render_to_string('chimere/blocks/welcome.html', response_dct,
- context_instance=RequestContext(request))
-
def submited(request, area_name="", action=""):
"""
Successful submission page
diff --git a/chimere/widgets.py b/chimere/widgets.py
index 01a4bdb..41b2f92 100644
--- a/chimere/widgets.py
+++ b/chimere/widgets.py
@@ -22,13 +22,14 @@ Extra widgets and fields
"""
from django import conf
from django import forms
-from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.contrib.gis.db import models
from django.contrib.gis.geos import fromstr
-from django.utils.html import conditional_escape
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.urlresolvers import reverse
from django.forms.widgets import RadioInput, RadioFieldRenderer
from django.utils.encoding import force_unicode
+from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
@@ -143,13 +144,10 @@ class ButtonSelectWidget(forms.RadioSelect):
u"</script>\n</div>\n" % kwargs['attrs']['id']
return mark_safe(rendered)
-class TextareaWidget(forms.Textarea):
+class TextareaWidgetBase(forms.Textarea):
"""
Manage the edition of a text using TinyMCE
"""
- class Media:
- js = ["%stiny_mce.js" % settings.TINYMCE_URL]
-
def render(self, *args, **kwargs):
if 'attrs' not in kwargs:
kwargs['attrs'] = {}
@@ -173,7 +171,7 @@ tinyMCE.init({
"""
return mark_safe(rendered)
-class FullTextareaWidget(forms.Textarea):
+class FullTextareaWidget(TextareaWidgetBase):
"""
Manage the edition of a text using TinyMCE
"""
@@ -200,6 +198,19 @@ tinyMCE.init({
"""
return mark_safe(rendered)
+class TextareaWidget(TextareaWidgetBase):
+ """
+ Manage the edition of a text using TinyMCE
+ """
+ class Media:
+ js = ["%stiny_mce.js" % settings.TINYMCE_URL,
+ "%schimere/js/textareas.js" % settings.STATIC_URL,]
+
+class TextareaAdminWidget(TextareaWidgetBase):
+ class Media:
+ js = ["%stiny_mce.js" % settings.TINYMCE_URL,
+ "%schimere/js/textareas_admin.js" % settings.STATIC_URL,]
+
class DatePickerWidget(forms.TextInput):
"""
Manage the edition of dates.
@@ -347,6 +358,7 @@ class RouteChooserWidget(forms.TextInput):
map_layers, default_area = get_map_layers(area_name)
map_layers = [js for name, js, default in map_layers]
js = """
+ var extra_url = "%s";
OpenLayers.ImgPath = '%schimere/img/';
var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:%s');
var EPSG_PROJECTION = epsg_projection = new OpenLayers.Projection('EPSG:%s');
@@ -358,7 +370,8 @@ class RouteChooserWidget(forms.TextInput):
chimere_init_options['edition'] = true;
chimere_init_options['edition_type_is_route'] = true;
chimere_init_options["checked_categories"] = [];
- """ % (settings.STATIC_URL, settings.CHIMERE_EPSG_DISPLAY_PROJECTION,
+ """ % ( reverse("chimere:index"), settings.STATIC_URL,
+ settings.CHIMERE_EPSG_DISPLAY_PROJECTION,
settings.CHIMERE_EPSG_PROJECTION, settings.CHIMERE_DEFAULT_CENTER,
settings.CHIMERE_DEFAULT_ZOOM, ", ".join(map_layers))
if default_area:
@@ -463,9 +476,11 @@ class AreaWidget(forms.TextInput):
"""
class Media:
css = {
- "all": settings.OSM_CSS_URLS + ["%schimere/css/forms.css" % settings.STATIC_URL,]
+ "all": settings.OSM_CSS_URLS + \
+ ["%schimere/css/forms.css" % settings.STATIC_URL,]
}
- js = settings.OSM_JS_URLS + ["%schimere/js/edit_area.js" % settings.STATIC_URL,
+ js = settings.OSM_JS_URLS + [
+ "%schimere/js/edit_area.js" % settings.STATIC_URL,
"%schimere/js/base.js" % settings.STATIC_URL,]
def render(self, name, value, attrs=None):
@@ -480,11 +495,24 @@ class AreaWidget(forms.TextInput):
lower_right = value[1]
if hasattr(upper_left, 'x') and hasattr(upper_left, 'y'):
upper_left_lon, upper_left_lat = upper_left.x, upper_left.y
+ elif len(upper_left) == 2:
+ try:
+ upper_left_lon = float(upper_left[0])
+ upper_left_lat = float(upper_left[1])
+ except ValueError:
+ pass
if hasattr(lower_right, 'x') and hasattr(lower_right, 'y'):
lower_right_lon, lower_right_lat = lower_right.x, \
lower_right.y
+ elif len(lower_right) == 2:
+ lower_right_lon, lower_right_lat = lower_right
+ try:
+ lower_right_lon = float(lower_right[0])
+ lower_right_lat = float(lower_right[1])
+ except ValueError:
+ pass
tpl = getMapJS()
- tpl += u"<div id='map_edit'></div>\n"\
+ tpl += u"</div>\n"\
u"<input type='hidden' name='upper_left_lat' id='upper_left_lat' "\
u"value='%f'/>\n"\
u"<input type='hidden' name='upper_left_lon' id='upper_left_lon' "\
@@ -494,13 +522,19 @@ class AreaWidget(forms.TextInput):
u"<input type='hidden' name='lower_right_lon' id='lower_right_lon' "\
u"value='%f'/>\n" % (
upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon)
- tpl += u"<script type='text/javascript'>\ninit();"
+ help_msg = _(u"Hold CTRL, click and drag to select area on the map")
+ tpl += u"<p>%s</p>\n" % help_msg
+ tpl += u"<script type='text/javascript'>\n"
+ tpl += u"$(document).ready(function($) {\ninit();\n"
if value:
tpl += u"var extent = new OpenLayers.Bounds(%f, %f, %f, %f);\n"\
u"extent.transform(epsg_display_projection, epsg_projection);\n"\
- u"map.zoomToExtent(extent, true);""" % (upper_left_lon,
- upper_left_lat, lower_right_lon, lower_right_lat)
- tpl += u"</script>\n<hr class='spacer'/>\n"
+ u"updateForm(extent);\n"\
+ u"map.zoomToExtent(extent, true);\n"\
+ u"map.zoomOut();" % (upper_left_lon, upper_left_lat,
+ lower_right_lon, lower_right_lat)
+ tpl += u"});\n</script>\n<hr class='spacer'/>\n"
+ tpl += u"<div id='map_edit'>\n"
return mark_safe(tpl)
def value_from_datadict(self, data, files, name):