summaryrefslogtreecommitdiff
path: root/chimere
diff options
context:
space:
mode:
Diffstat (limited to 'chimere')
-rw-r--r--chimere/actions.py65
-rw-r--r--chimere/admin.py156
-rw-r--r--chimere/locale/fr/LC_MESSAGES/django.po886
-rw-r--r--chimere/migrations/0010_auto__add_field_subcategory_keywords.py291
-rw-r--r--chimere/migrations/0011_auto__add_field_importer_default_status.py292
-rw-r--r--chimere/migrations/0012_auto__chg_field_importer_filtr.py290
-rw-r--r--chimere/models.py397
-rw-r--r--chimere/settings.sample.py4
-rw-r--r--chimere/static/chimere/css/styles.css23
-rw-r--r--chimere/static/chimere/js/importer_interface.js35
-rw-r--r--chimere/static/chimere/js/jquery.chimere-ol.js77
-rw-r--r--chimere/tasks.py37
-rw-r--r--chimere/templates/chimere/blocks/map_menu.html2
-rw-r--r--chimere/templates/chimere/blocks/news.html2
-rw-r--r--chimere/templates/chimere/category_directory.html35
-rw-r--r--chimere/templates/chimere/category_directory_detail.html25
-rw-r--r--chimere/templates/chimere/category_item_detail.html38
-rw-r--r--chimere/templates/search/indexes/chimere/marker_text.txt2
-rw-r--r--chimere/templates/search/indexes/chimere/route_text.txt2
-rw-r--r--chimere/templates/search/search.html5
-rw-r--r--chimere/templatetags/chimere_tags.py10
-rw-r--r--chimere/tests.py16
-rw-r--r--chimere/tests/test.json57
-rw-r--r--chimere/urls.py68
-rw-r--r--chimere/utils.py516
-rw-r--r--chimere/views.py474
26 files changed, 2456 insertions, 1349 deletions
diff --git a/chimere/actions.py b/chimere/actions.py
index 824b14f..e83d8c3 100644
--- a/chimere/actions.py
+++ b/chimere/actions.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2008-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2008-2010 É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
@@ -22,60 +22,53 @@ Actions available in the main interface
"""
from django.conf import settings
from django.contrib.auth import models
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, NoReverseMatch
from django.utils.translation import ugettext_lazy as _
-from chimere.models import Page, Map
+from models import Page
class Action:
- def __init__(self, id, path, label, extra_url_args=[],
- condition=None):
+ def __init__(self, id, path, label, extra_url_args=[]):
self.id, self.path, self.label = id, path, label
self.extra_url_args, self.url = extra_url_args, None
- self.condition = condition
- def update_url(self, map_name):
- self.url = reverse(self.path,
- args=[map_name + '/' if map_name else ''] + self.extra_url_args)
+ def update_url(self, area_name):
+ try:
+ self.url = reverse(self.path,
+ args=[area_name if area_name else ''] + self.extra_url_args)
+ except NoReverseMatch:
+ # backward url management
+ self.url = reverse(self.path,
+ args=[area_name + '/' if area_name else ''] + self.extra_url_args)
-DEFAULT_ACTIONS = [[Action('view', 'chimere:index', _('View')), []],
- [Action('contribute', 'chimere:edit', _('Contribute'),
- condition=lambda user, map_name:bool(
- Map.getAvailable(user=user, urn=map_name, single=True,
- propose=True))),
+default_actions = [(Action('view', 'chimere:index', _('View')), []),
+ (Action('contribute', 'chimere:edit', _('Contribute')),
(Action('edit', 'chimere:edit', _('Add a new point of interest')),
Action('edit-route', 'chimere:editroute', _('Add a new route'))),
- ],
- ]
+ ),]
+
+if hasattr(settings, 'CHIMERE_DIRECTORY') and settings.CHIMERE_DIRECTORY:
+ default_actions.append((Action('categories', 'chimere:category-directory',
+ _('Directory')), []))
if settings.CHIMERE_FEEDS:
- DEFAULT_ACTIONS.append([Action('rss', 'chimere:feeds-form',
- _('RSS feeds')), []])
+ default_actions.append((Action('rss', 'chimere:feeds-form',
+ _('RSS feeds')), []))
if settings.EMAIL_HOST:
- DEFAULT_ACTIONS.append([Action('contact', 'chimere:contact',
- _('Contact us')), []],)
+ default_actions.append((Action('contact', 'chimere:contact',
+ _('Contact us')), []),)
+
-def actions(user, map_name='', default_actions=DEFAULT_ACTIONS):
- acts, idx = [], -1
+def actions(area_name=''):
+ acts = default_actions[:]
for act, childs in default_actions:
- if act.id not in settings.CHIMERE_DEFAULT_ACTIONS:
- continue
- idx += 1
- if act.condition:
- if not act.condition(user, map_name):
- continue
- act.update_url(map_name)
+ act.update_url(area_name)
for child_act in childs:
- child_act.update_url(map_name)
- if "CHIMERE_DEFAULT_ACTION_LABEL" in dir(settings):
- if len(settings.CHIMERE_DEFAULT_ACTION_LABEL) > idx:
- act.label = settings.CHIMERE_DEFAULT_ACTION_LABEL[idx]
- acts.append((act, childs))
+ child_act.update_url(area_name)
for page in Page.objects.filter(available=True).order_by('order'):
act = Action(page.mnemonic, 'chimere:extra_page', page.title,
[page.mnemonic])
- act.update_url(map_name)
+ act.update_url(area_name)
acts.append((act, []))
-
return acts
diff --git a/chimere/admin.py b/chimere/admin.py
index 2672306..60d1141 100644
--- a/chimere/admin.py
+++ b/chimere/admin.py
@@ -25,8 +25,7 @@ import datetime
from django import forms
from django.conf import settings
from django.contrib import admin, messages
-from django.contrib.auth.models import User, Group
-from django.contrib.auth.admin import GroupAdmin
+from django.contrib.admin import SimpleListFilter
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
@@ -38,30 +37,18 @@ try:
except ImportError:
pass
-from chimere.forms import MarkerAdminForm, RouteAdminForm, MapAdminForm,\
+from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\
NewsAdminForm, CategoryAdminForm, ImporterAdminForm, OSMForm, \
PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm
+from chimere import models
from chimere.models import Category, Icon, SubCategory, Marker, \
- PropertyModel, News, Route, Map, ColorTheme, Color, \
- MultimediaFile, PictureFile, Importer, Layer, MapLayers,\
- PropertyModelChoice, MultimediaExtension, Page, MapUsers, MapGroups,\
- get_maps_for_user, get_users_by_map, ImporterKeyCategories
+ PropertyModel, News, Route, Area, ColorTheme, Color, \
+ MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\
+ PropertyModelChoice, MultimediaExtension, Page,\
+ get_areas_for_user, get_users_by_area, ImporterKeyCategories
from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\
CSVManager
-admin.site.unregister(Group)
-
-class UserInline(admin.StackedInline):
- model = User.groups.through
- verbose_name = _(u'User')
- verbose_name_plural = _(u'User')
- extra = 1
-
-class GroupAdmin(GroupAdmin):
- inlines = [ UserInline, ]
-
-admin.site.register(Group, GroupAdmin)
-
def disable(modeladmin, request, queryset):
for item in queryset:
item.status = 'D'
@@ -99,18 +86,14 @@ def export_to_shapefile(modeladmin, request, queryset):
return response
export_to_shapefile.short_description = _(u"Export to Shapefile")
-def _export_to_csv(cols=[]):
- def func(modeladmin, request, queryset):
- u"""
- Export data to CSV
- """
- filename, result = CSVManager.export(queryset, cols=cols)
- response = HttpResponse(result, mimetype='text/csv')
- response['Content-Disposition'] = 'attachment; filename=%s' % filename
- return response
- return func
-
-export_to_csv = _export_to_csv()
+def export_to_csv(modeladmin, request, queryset):
+ u"""
+ Export data to CSV
+ """
+ filename, result = CSVManager.export(queryset)
+ response = HttpResponse(result, mimetype='text/csv')
+ response['Content-Disposition'] = 'attachment; filename=%s' % filename
+ return response
export_to_csv.short_description = _(u"Export to CSV")
def managed_modified(modeladmin, request, queryset):
@@ -195,13 +178,53 @@ class MultimediaInline(admin.TabularInline):
ordering = ('order',)
form = MultimediaFileAdminForm
+class AreaMarkerListFilter(admin.SimpleListFilter):
+ title = _('area')
+ parameter_name = 'area'
+
+ def lookups(self, request, model_admin):
+ return [(area.urn, area.name) for area in models.Area.objects.all()]
+
+ def queryset(self, request, queryset):
+ try:
+ area = models.Area.objects.get(urn=self.value())
+ except models.Area.DoesNotExist:
+ return queryset
+ return queryset.filter(area.getIncludeMarker())
+
+class AreaRouteListFilter(AreaMarkerListFilter):
+ def queryset(self, request, queryset):
+ try:
+ area = models.Area.objects.get(urn=self.value())
+ except models.Area.DoesNotExist:
+ return queryset
+ return queryset.filter(area.getIncludeRoute())
+
+class HasCategoriesListFilter(SimpleListFilter):
+ title = _('Has categories')
+ parameter_name = 'has_category'
+
+ def lookups(self, request, model_admin):
+ return (
+ ('true', _('Yes')),
+ ('false', _('No')),
+ )
+
+ def queryset(self, request, queryset):
+ if self.value() == 'false':
+ return queryset.filter(categories__isnull=True)
+ elif self.value() == 'true':
+ return queryset.exclude(categories__isnull=True)
+ return queryset
+
class MarkerAdmin(admin.ModelAdmin):
"""
Specialized the Point field.
"""
search_fields = ("name",)
list_display = ('name', 'status', 'start_date', 'end_date')
- list_filter = ('status', 'categories', 'start_date', 'end_date')
+ list_filter = ('status', AreaMarkerListFilter, 'categories',
+ HasCategoriesListFilter, 'start_date', 'end_date')
actions = [validate, disable, managed_modified, export_to_kml,
export_to_shapefile, export_to_csv]
exclude = ['submiter_session_key', 'import_key', 'import_version',
@@ -211,7 +234,7 @@ class MarkerAdmin(admin.ModelAdmin):
form = MarkerAdminForm
fieldsets = ((None, {
'fields': ['point', 'name', 'status', 'categories',
- 'description', 'weight', 'keywords', 'start_date', 'end_date']
+ 'description', 'keywords', 'start_date', 'end_date']
}),
(_(u"Submitter"), {
'classes':('collapse',),
@@ -247,10 +270,10 @@ class MarkerAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = self.model._default_manager.get_query_set()
if not request.user.is_superuser:
- maps = get_maps_for_user(request.user)
+ areas = get_areas_for_user(request.user)
contained = Q()
- for map in maps:
- contained = contained | map.getIncludeMarker()
+ for area in areas:
+ contained = contained | area.getIncludeMarker()
qs = qs.filter(contained)
ordering = self.ordering or ()
if ordering:
@@ -280,7 +303,7 @@ class RouteAdmin(MarkerAdmin):
"""
search_fields = ("name",)
list_display = ('name', 'status')
- list_filter = ('status', 'categories')
+ list_filter = ('status', AreaRouteListFilter, 'categories')
exclude = ['height', 'width']
form = RouteAdminForm
readonly_fields = ('associated_file', 'ref_item', 'has_associated_marker')
@@ -312,10 +335,10 @@ class RouteAdmin(MarkerAdmin):
def queryset(self, request):
qs = self.model._default_manager.get_query_set()
if not request.user.is_superuser:
- maps = get_maps_for_user(request.user)
+ areas = get_areas_for_user(request.user)
contained = Q()
- for map in maps:
- contained = contained | map.getIncludeRoute()
+ for area in areas:
+ contained = contained | area.getIncludeRoute()
qs = qs.filter(contained)
ordering = self.ordering or ()
if ordering:
@@ -330,24 +353,16 @@ class RouteAdmin(MarkerAdmin):
Route.objects.filter(pk=item_id))
class LayerInline(admin.TabularInline):
- model = MapLayers
- extra = 1
-
-class UserInline(admin.TabularInline):
- model = MapUsers
- extra = 1
-
-class GroupInline(admin.TabularInline):
- model = MapGroups
+ model = AreaLayers
extra = 1
-class MapAdmin(admin.ModelAdmin):
+class AreaAdmin(admin.ModelAdmin):
"""
- Specialized the map field.
+ Specialized the area field.
"""
- form = MapAdminForm
+ form = AreaAdminForm
exclude = ['upper_left_corner', 'lower_right_corner']
- inlines = [UserInline, GroupInline, LayerInline]
+ inlines = [LayerInline]
list_display = ['name', 'order', 'available', 'default']
def importing(modeladmin, request, queryset):
@@ -422,6 +437,7 @@ class ImporterAdmin(admin.ModelAdmin):
readonly_fields = ('state',)
actions = [importing, cancel_import, export_to_osm, cancel_export]
inlines = [ImporterKeyInline]
+admin.site.register(Importer, ImporterAdmin)
class PageAdmin(admin.ModelAdmin):
"""
@@ -466,25 +482,15 @@ class PropertyModelChoiceInline(admin.TabularInline):
class PropertyModelAdmin(admin.ModelAdmin):
inlines = [PropertyModelChoiceInline]
-# only register if not yet registered: this mecanism allow to specialized admin
-# in projects
-registered_models = admin.site._registry.keys()
-for model, modeladmin in ((Importer, ImporterAdmin),
- (Page, PageAdmin),
- (News, NewsAdmin),
- (Category, CategoryAdmin),
- (Icon, IconAdmin),
- (Marker, MarkerAdmin),
- (Route, RouteAdmin),
- (Map, MapAdmin),
- (ColorTheme, ColorThemeAdmin),
- (Layer, None)):
- if model not in registered_models:
- if modeladmin:
- admin.site.register(model, modeladmin)
- else:
- admin.site.register(model)
-
-if PropertyModel not in registered_models and \
- not settings.CHIMERE_HIDE_PROPERTYMODEL:
+# register of differents database fields
+admin.site.register(Page, PageAdmin)
+admin.site.register(News, NewsAdmin)
+admin.site.register(Category, CategoryAdmin)
+admin.site.register(Icon, IconAdmin)
+admin.site.register(Marker, MarkerAdmin)
+admin.site.register(Route, RouteAdmin)
+if not settings.CHIMERE_HIDE_PROPERTYMODEL:
admin.site.register(PropertyModel, PropertyModelAdmin)
+admin.site.register(Area, AreaAdmin)
+admin.site.register(ColorTheme, ColorThemeAdmin)
+admin.site.register(Layer)
diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po
index 913997d..0c5e884 100644
--- a/chimere/locale/fr/LC_MESSAGES/django.po
+++ b/chimere/locale/fr/LC_MESSAGES/django.po
@@ -1,5 +1,5 @@
# Chimère
-# Copyright (C) 2008-2013
+# Copyright (C) 2008-2015
# This file is distributed under the same license as the Chimère package.
# Étienne Loks <etienne.loks@peacefrogs.net>, 2008-2011.
#
@@ -7,18 +7,18 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-10-27 20:17+0100\n"
+"POT-Creation-Date: 2015-04-20 09:15+0200\n"
"PO-Revision-Date: 2010-03-20 20:00+0100\n"
"Last-Translator: Étienne Loks <etienne.loks@peacefrogs.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: actions.py:41
+#: actions.py:44
msgid "View"
msgstr "Voir"
-#: actions.py:42
+#: actions.py:45
msgid "Contribute"
msgstr "Participer"
@@ -30,106 +30,110 @@ msgstr "Ajout d'un point remarquable"
msgid "Add a new route"
msgstr "Ajout d'un nouveau trajet"
-#: actions.py:53
+#: actions.py:52
+msgid "Directory"
+msgstr "Annuaire"
+
+#: actions.py:56
msgid "RSS feeds"
msgstr "Flux RSS"
-#: actions.py:57
+#: actions.py:60
msgid "Contact us"
msgstr "Nous contacter"
-#: admin.py:56 admin.py:57
-msgid "User"
-msgstr "Utilisateur"
-
-#: admin.py:69
+#: admin.py:55
msgid "Disable"
msgstr "Désactiver"
-#: admin.py:75 templates/admin/chimere/managed_modified.html:44
+#: admin.py:61 templates/admin/chimere/managed_modified.html:44
#: templates/chimere/feeds/rss.html:70
msgid "Validate"
msgstr "Valider"
-#: admin.py:86
+#: admin.py:72
msgid "Export to KML"
msgstr "Exporter en KML"
-#: admin.py:100
+#: admin.py:86
msgid "Export to Shapefile"
msgstr "Exporter en Shapefile"
-#: admin.py:114
+#: admin.py:96
msgid "Export to CSV"
msgstr "Exporter en CSV"
-#: admin.py:121
+#: admin.py:103
msgid "Only one item can be managed at a time."
msgstr "Seul un élément à la fois peut-être géré."
-#: admin.py:131
+#: admin.py:113
msgid "No modified item associated to the selected item."
msgstr "Pas d'élément modifié associé à l'élément sélectionné."
-#: admin.py:177
+#: admin.py:159
msgid "Modified item traited."
msgstr "Élément modifié traité."
-#: admin.py:182
+#: admin.py:164
msgid "Managed modified items"
msgstr "Gérer les éléments modifiés"
-#: admin.py:216 admin.py:292
+#: admin.py:181
+msgid "area"
+msgstr "zone"
+
+#: admin.py:221 admin.py:298
msgid "Submitter"
msgstr "Demandeur"
-#: admin.py:221 admin.py:297 admin.py:357
+#: admin.py:226 admin.py:303 admin.py:355
msgid "Import"
msgstr "Import"
-#: admin.py:226 admin.py:302
+#: admin.py:231 admin.py:308
msgid "Associated items"
msgstr "Éléments associés"
-#: admin.py:363
+#: admin.py:361
msgid "Cancel import"
msgstr "Annuler l'import"
-#: admin.py:369
+#: admin.py:367
msgid "Cancel export"
msgstr "Annuler l'export"
-#: admin.py:373
+#: admin.py:371
msgid "Can manage only one OSM export at a time."
-msgstr "Ne peut gérer qu'un seul export OSM à la fois."
+msgstr "Ne peux gérer qu'un seul export OSM à la fois."
-#: admin.py:378
+#: admin.py:376
msgid ""
"You must treat all item with the status \"imported\" before exporting to OSM."
msgstr ""
"Vous devez traiter tous les éléments avec le status « importé » avant "
"d'exporter vers OSM."
-#: admin.py:382
+#: admin.py:380
msgid "Only OSM importer are managed for export."
msgstr "Seul les imports de type OSM peuvent être gérés pour les exports."
-#: admin.py:389
+#: admin.py:387
msgid "No point of interest are concerned by this export."
msgstr "Aucun point d'intérêt n'est concerné par cet export."
-#: admin.py:401
+#: admin.py:399
msgid "Export launched."
msgstr "Export lancé."
-#: admin.py:405
+#: admin.py:403
#, python-format
msgid ""
"%s point(s) of interest concerned by this export before bounding box filter."
msgstr ""
"%s point(s) d'intérêt concerné par cet export (avant le filtre sur la zone)"
-#: admin.py:410
+#: admin.py:408
msgid "Export to osm"
msgstr "Exporter vers osm"
@@ -145,50 +149,50 @@ msgstr "Nouveaux points d'intérêt de "
msgid "Last points of interest by area"
msgstr "Nouveaux points d'intérêt par zone"
-#: forms.py:83
+#: forms.py:87
msgid "New submission for"
msgstr "Nouvelle proposition pour"
-#: forms.py:84
+#: forms.py:88
#, 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:86
+#: forms.py:90
msgid "To valid, precise or unvalid this item: "
msgstr "Pour valider, préciser ou rejeter cet élément : "
-#: forms.py:96
+#: forms.py:100
msgid "Email (optional)"
msgstr "Courriel (optionnel) "
-#: forms.py:97
+#: forms.py:101
msgid "Object"
msgstr "Objet"
-#: forms.py:117
+#: forms.py:121
msgid "OSM user"
msgstr "Utilisateur OSM"
-#: forms.py:118 models.py:1635
+#: forms.py:122 models.py:1552
msgid "Password"
msgstr "Mot de passe"
-#: forms.py:122
+#: forms.py:126
msgid "API"
msgstr "API"
-#: forms.py:125
+#: forms.py:129
#, python-format
msgid "Test API - %s"
msgstr "API de test - %s"
-#: forms.py:127
+#: forms.py:131
#, python-format
msgid "Main API - %s"
msgstr "API principale - %s"
-#: forms.py:158 forms.py:162
+#: forms.py:162 forms.py:166
msgid ""
"For OSM import you must be provide a filter. Select an area and node/way "
"filter."
@@ -196,30 +200,30 @@ msgstr ""
"Pour les imports OSM vous devez fournir un filtre. Sélectionnez une zone et "
"un filtre sur les nœuds/routes."
-#: forms.py:166
+#: forms.py:170
msgid "Shapefiles must be provided in a zipped archive."
msgstr ""
"Les fichiers Shapefiles doivent être fournis regroupés dans une archive zip."
-#: forms.py:170
+#: forms.py:175
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:175
+#: forms.py:180
msgid "You have to set \"source\" or \"source file\"."
msgstr "Vous devez spécifier le champ « Source » ou « Fichier source »."
-#: forms.py:236
+#: forms.py:241
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:240
+#: forms.py:245
msgid "End date can't be before start date"
msgstr "La date de fin ne peut pas être antérieure à la date de début"
-#: forms.py:250
+#: forms.py:255
msgid "This field is mandatory for the selected categories"
msgstr "Ce champ est obligatoire pour les catégories sélectionnées"
@@ -231,16 +235,16 @@ msgstr "Fichier"
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:518 models.py:53 models.py:101 models.py:163 models.py:185
-#: models.py:198 models.py:213 models.py:378 models.py:752 models.py:808
-#: models.py:867 models.py:985 models.py:1343 models.py:1355 models.py:1624
-#: utils.py:487 templates/admin/chimere/managed_modified.html:23
-#: templates/chimere/edit.html:44 templates/chimere/edit_route.html:39
+#: forms.py:518 models.py:54 models.py:102 models.py:164 models.py:185
+#: models.py:198 models.py:213 models.py:424 models.py:773 models.py:829
+#: models.py:888 models.py:1006 models.py:1356 models.py:1368 models.py:1542
+#: utils.py:490 templates/admin/chimere/managed_modified.html:23
+#: templates/chimere/edit.html:40 templates/chimere/edit_route.html:37
#: templates/chimere/blocks/alternate_multimedia.html:39
msgid "Name"
msgstr "Nom"
-#: forms.py:527
+#: forms.py:527 models.py:1405
msgid "Area"
msgstr "Zone"
@@ -266,62 +270,62 @@ msgstr "Arrivée"
msgid "Speed"
msgstr "Vitesse"
-#: models.py:54
+#: models.py:55
msgid "Mnemonic"
msgstr "Mnémonique"
-#: models.py:56 models.py:102 models.py:186 models.py:214 models.py:371
-#: models.py:756 models.py:1356 models.py:1626 models.py:1673
+#: models.py:57 models.py:103 models.py:186 models.py:214 models.py:417
+#: models.py:777 models.py:1374 models.py:1544 models.py:1587
msgid "Available"
msgstr "Disponible"
-#: models.py:57 models.py:173 models.py:187 models.py:233 models.py:810
-#: models.py:882 models.py:1362 models.py:1613 models.py:1625
+#: models.py:58 models.py:174 models.py:187 models.py:231 models.py:831
+#: models.py:903 models.py:1373 models.py:1531 models.py:1543
msgid "Order"
msgstr "Ordre"
-#: models.py:58
+#: models.py:59
msgid "Template path"
msgstr "Chemin du patron"
-#: models.py:65 models.py:66
+#: models.py:66 models.py:67
msgid "Page"
msgstr "Page"
-#: models.py:103 models.py:474
+#: models.py:104 models.py:520
msgid "Is front page"
msgstr "Est en page principale"
-#: models.py:105 models.py:1636
+#: models.py:106 models.py:1553
msgid "Date"
msgstr "Date"
-#: models.py:107 models.py:809
+#: models.py:108 models.py:830
msgid "Url"
msgstr "Url"
-#: models.py:108
-msgid "Associated maps"
-msgstr "Cartes associées"
+#: models.py:109
+msgid "Associated areas"
+msgstr "Zones associées"
-#: models.py:114 models.py:115 templates/chimere/blocks/news.html:3
+#: models.py:115 models.py:116 templates/chimere/blocks/news.html:3
#: templates/chimere/blocks/news.html:5
msgid "News"
-msgstr "Nouvelle"
+msgstr "Actualités"
-#: models.py:124
+#: models.py:125
msgid "Parameters"
msgstr "Paramètres"
-#: models.py:128
+#: models.py:129
msgid "TinyUrl"
msgstr "Mini-url"
-#: models.py:167 models.py:174 models.py:228
+#: models.py:168 models.py:175 models.py:226
msgid "Color theme"
msgstr "Thème de couleur"
-#: models.py:172
+#: models.py:173
msgid "Code"
msgstr "Code"
@@ -329,24 +333,24 @@ msgstr "Code"
msgid "Color"
msgstr "Couleur"
-#: models.py:193 models.py:211
+#: models.py:193 models.py:211 models.py:410
msgid "Category"
msgstr "Catégorie"
-#: models.py:199 models.py:748 models.py:868 models.py:1051
+#: models.py:199 models.py:769 models.py:889 models.py:1072
#: templates/chimere/blocks/alternate_multimedia.html:43
msgid "Image"
msgstr "Image"
-#: models.py:201 models.py:870 models.py:1053
+#: models.py:201 models.py:891 models.py:1074
msgid "Height"
msgstr "Hauteur"
-#: models.py:202 models.py:871 models.py:1054
+#: models.py:202 models.py:892 models.py:1075
msgid "Width"
msgstr "Largeur"
-#: models.py:206 models.py:225
+#: models.py:206 models.py:223
msgid "Icon"
msgstr "Icône"
@@ -355,42 +359,42 @@ msgid "Available for submission"
msgstr "Disponible pour soumission"
#: models.py:217
-msgid "Has an associated quantity"
-msgstr "A une quantité associée"
-
-#: models.py:219
msgid "Marker"
msgstr "Point d'intérêt"
-#: models.py:220 models.py:1047 models.py:1064
-#: templates/chimere/edit_route.html:30
+#: models.py:218 models.py:1068 models.py:1085
+#: templates/chimere/edit_route.html:28
msgid "Route"
msgstr "Trajet"
-#: models.py:221
+#: models.py:219
msgid "Both"
msgstr "Mixte"
-#: models.py:222
+#: models.py:220
msgid "Item type"
msgstr "Type d'élément"
-#: models.py:223
+#: models.py:221
msgid "Is dated"
msgstr "Est daté"
-#: models.py:226
+#: models.py:224
msgid "Hover icon"
msgstr "Icône en survol"
-#: models.py:230
+#: models.py:228
msgid "Displayed in the layer menu"
msgstr "Apparaît dans le menu des couches ?"
-#: models.py:232
+#: models.py:230
msgid "Routing warn"
msgstr "Avertissement sur les itinéraires"
+#: models.py:232 models.py:435 templates/chimere/edit.html:56
+msgid "Keywords"
+msgstr "Mots clés"
+
#: models.py:238
msgid "Sub-category"
msgstr "Sous-catégorie"
@@ -399,335 +403,351 @@ msgstr "Sous-catégorie"
msgid "Sub-categories"
msgstr "Sous-catégories"
-#: models.py:323
+#: models.py:336
msgid "Importer type"
msgstr "Type d'import"
-#: models.py:325
+#: models.py:338
msgid "Filter"
msgstr "Filtre"
-#: models.py:327 templates/chimere/blocks/alternate_multimedia.html:49
+#: models.py:340 templates/chimere/blocks/alternate_multimedia.html:49
msgid "Web address"
msgstr "Adresse web"
-#: models.py:329
+#: models.py:342
+msgid "Don't forget the trailing slash"
+msgstr "N'oubliez pas la barre oblique (« / ») finale"
+
+#: models.py:343
msgid "Source file"
msgstr "Fichier source"
-#: models.py:331
+#: models.py:345
+msgid "Alt source file"
+msgstr "Fichier source alternatif"
+
+#: models.py:347
msgid "Name by default"
msgstr "Nom par défaut"
-#: models.py:333
+#: models.py:349
msgid "SRID"
msgstr "SRID"
-#: models.py:334
+#: models.py:350
msgid "Zipped file"
msgstr "Fichier zippé"
-#: models.py:335
+#: models.py:351
msgid "Overwrite existing data"
msgstr "Écraser les données existantes"
-#: models.py:337
+#: models.py:353
msgid "Get description from source"
msgstr "Obtenir une description depuis la source"
-#: models.py:339
+#: models.py:355
msgid "Default description"
msgstr "Description par défaut"
-#: models.py:341 models.py:399
+#: models.py:357 models.py:447
msgid "Origin"
msgstr "Origine"
-#: models.py:343 models.py:401
+#: models.py:359 models.py:449
msgid "License"
msgstr "Licence"
-#: models.py:346
+#: models.py:362
msgid "Associated subcategories"
msgstr "Sous-catégories associées"
-#: models.py:347 utils.py:491
+#: models.py:363 utils.py:494
msgid "State"
msgstr "État"
-#: models.py:349
+#: models.py:364
msgid "Automatically associate a marker to a way"
msgstr "Associer automatiquement un marqueur à une route"
-#: models.py:353
+#: models.py:366
+msgid "Automatically updated"
+msgstr "Mis à jour automatiquement"
+
+#: models.py:368
+msgid "Default localisation"
+msgstr "Localisation par défaut"
+
+#: models.py:374 models.py:408
msgid "Importer"
msgstr "Import"
-#: models.py:370
+#: models.py:411 models.py:437
+msgid "Import key"
+msgstr "Clé d'import"
+
+#: models.py:414
+msgid "Importer - Key categories"
+msgstr "Importeur - clés / catégories"
+
+#: models.py:416
msgid "Submited"
msgstr "Soumis"
-#: models.py:372
+#: models.py:418
msgid "Modified"
msgstr "Modifié"
-#: models.py:373
+#: models.py:419
msgid "Disabled"
msgstr "Désactivé"
-#: models.py:374
+#: models.py:420
msgid "Imported"
msgstr "Importé"
-#: models.py:380
+#: models.py:426
msgid "Submitter session key"
msgstr "Clé de session du demandeur"
-#: models.py:382
+#: models.py:428
msgid "Submitter name or nickname"
msgstr "Nom ou pseudo du demandeur"
-#: models.py:384
+#: models.py:430
msgid "Submitter email"
msgstr "Courriel du demandeur"
-#: models.py:386
+#: models.py:432
msgid "Submitter comment"
msgstr "Commentaire du demandeur"
-#: models.py:388 models.py:1234
+#: models.py:434 models.py:1248
msgid "Status"
msgstr "État"
-#: models.py:389
-msgid "Import key"
-msgstr "Clé d'import"
-
-#: models.py:391
+#: models.py:439
msgid "Import version"
msgstr "Version de l'import"
-#: models.py:393
+#: models.py:441
msgid "Source"
msgstr "Source"
-#: models.py:395
+#: models.py:443
msgid "Modified since last import"
msgstr "Modifié depuis le dernier import"
-#: models.py:397
+#: models.py:445
msgid "Not to be exported to OSM"
msgstr "À ne pas exporter vers OSM"
-#: models.py:403 templates/chimere/edit.html:61
-#: templates/chimere/edit_route.html:55
+#: models.py:451 templates/chimere/edit.html:63
+#: templates/chimere/edit_route.html:53
msgid "Start date"
msgstr "Date de début"
-#: models.py:404
+#: models.py:452
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:406 templates/chimere/edit.html:67
-#: templates/chimere/edit_route.html:61
+#: models.py:454 templates/chimere/edit.html:69
+#: templates/chimere/edit_route.html:59
msgid "End date"
msgstr "Date de fin"
-#: models.py:407
+#: models.py:455
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:464
+#: models.py:512
msgid "Reference marker"
msgstr "Point d'intérêt de référence"
-#: models.py:465 utils.py:493
+#: models.py:513 utils.py:496
msgid "Localisation"
msgstr "Localisation"
-#: models.py:467
+#: models.py:515
msgid "Available Date"
msgstr "Date de mise en disponibilité"
-#: models.py:471
-msgid "Quantity"
-msgstr "Quantité"
-
-#: models.py:473 utils.py:492 templates/admin/chimere/managed_modified.html:31
-#: templates/chimere/edit.html:54 templates/chimere/edit_route.html:49
+#: models.py:519 utils.py:495 templates/admin/chimere/managed_modified.html:31
+#: templates/chimere/edit.html:50 templates/chimere/edit_route.html:47
msgid "Description"
msgstr "Description"
-#: models.py:548 models.py:1683
+#: models.py:590 models.py:1597
msgid "Point of interest"
msgstr "Point d'intérêt"
-#: models.py:746
+#: models.py:767
msgid "Audio"
msgstr "Audio"
-#: models.py:747
+#: models.py:768
msgid "Video"
msgstr "Vidéo"
-#: models.py:749
+#: models.py:770
msgid "Other"
msgstr "Autre"
-#: models.py:750
+#: models.py:771
msgid "Media type"
msgstr "Type de media"
-#: models.py:753
+#: models.py:774
msgid "Mime type"
msgstr "Type mime"
-#: models.py:755
+#: models.py:776
msgid "Inside an iframe"
msgstr "À l'intérieur d'un iframe"
-#: models.py:759
+#: models.py:780
msgid "Multimedia type"
msgstr "Type de multimedia"
-#: models.py:760
+#: models.py:781
msgid "Multimedia types"
msgstr "Types de multimedia"
-#: models.py:769
+#: models.py:790
msgid "Automatic recognition"
msgstr "Reconnaissance automatique"
-#: models.py:795
+#: models.py:816
msgid "Extension name"
msgstr "Nom de l'extension"
-#: models.py:797
+#: models.py:818
msgid "Associated multimedia type"
msgstr "Type de multimedia associé"
-#: models.py:801
+#: models.py:822
msgid "Multimedia extension"
msgstr "Extension multimedia"
-#: models.py:802
+#: models.py:823
msgid "Multimedia extensions"
msgstr "Extensions multimedia"
-#: models.py:812 models.py:872
+#: models.py:833 models.py:893
msgid "Display inside the description?"
msgstr "Apparaît dans la description ?"
-#: models.py:817
+#: models.py:838
msgid "Multimedia file"
msgstr "Fichier multimedia"
-#: models.py:818
+#: models.py:839
msgid "Multimedia files"
msgstr "Fichiers multimedias"
-#: models.py:874
+#: models.py:895
msgid "Thumbnail"
msgstr "Miniature"
-#: models.py:878
+#: models.py:899
msgid "Thumbnail height"
msgstr "Hauteur de la miniature"
-#: models.py:880
+#: models.py:901
msgid "Thumbnail width"
msgstr "Largeur de la miniature"
-#: models.py:889
+#: models.py:910
msgid "Picture file"
msgstr "Fichier d'image"
-#: models.py:890
+#: models.py:911
msgid "Picture files"
msgstr "Fichiers d'image"
-#: models.py:986
+#: models.py:1007
msgid "Raw file (gpx or kml)"
msgstr "Fichier brut (gpx ou kml)"
-#: models.py:988
+#: models.py:1009
msgid "Simplified file"
msgstr "Fichier simplifié"
-#: models.py:990
+#: models.py:1011
msgid "KML"
msgstr "KML"
-#: models.py:990
+#: models.py:1011
msgid "GPX"
msgstr "GPX"
-#: models.py:995
+#: models.py:1016
msgid "Route file"
msgstr "Fichier de trajet"
-#: models.py:996
+#: models.py:1017
msgid "Route files"
msgstr "Fichiers de trajet"
-#: models.py:1046
+#: models.py:1067
msgid "Reference route"
msgstr "Trajet de référence"
-#: models.py:1050
+#: models.py:1071
msgid "Associated file"
msgstr "Fichier associé"
-#: models.py:1055
+#: models.py:1076
msgid "Has an associated marker"
msgstr "Dispose d'un marqueur associé"
-#: models.py:1344
+#: models.py:1357
msgid "Layer code"
msgstr "Code pour la couche"
-#: models.py:1350
+#: models.py:1363
msgid "Layer"
msgstr "Couche"
-#: models.py:1358
-msgid "Map urn"
-msgstr "Urn de la carte"
+#: models.py:1369
+msgid "Area urn"
+msgstr "Urn de la zone"
-#: models.py:1360 templates/chimere/blocks/welcome.html:3
+#: models.py:1371 templates/chimere/blocks/welcome.html:3
msgid "Welcome message"
msgstr "Message d'accueil"
-#: models.py:1363
+#: models.py:1375
msgid "Upper left corner"
msgstr "Coin en haut à gauche"
-#: models.py:1365
+#: models.py:1377
msgid "Lower right corner"
msgstr "Coin en bas à droite"
-#: models.py:1367
-msgid "Default map"
-msgstr "Carte par défaut"
+#: models.py:1379
+msgid "Default area"
+msgstr "Zone par défaut"
-#: models.py:1368
-msgid "Only one map is set by default"
-msgstr "Seule une carte est définie par défaut"
+#: models.py:1380
+msgid "Only one area is set by default"
+msgstr "Seule une zone est définie par défaut"
-#: models.py:1372
+#: models.py:1384
msgid "Sub-categories checked by default"
msgstr "Sous-catégories cochées par défaut"
-#: models.py:1374
+#: models.py:1386
msgid "Sub-categories dynamicaly displayed"
msgstr "Sous-categories affichées dynamiquement"
-#: models.py:1375
+#: models.py:1387
msgid ""
"If checked, categories are only displayed in the menu if they are available "
"on the current extent."
@@ -735,146 +755,106 @@ msgstr ""
"Si coché, les catégories sont disponibles sur le menu seulement si elles "
"apparaissent sur la zone affichée."
-#: models.py:1379 models.py:1630
+#: models.py:1391 models.py:1547
msgid "Restricted to theses sub-categories"
msgstr "Restreindre à ces sous-categories"
-#: models.py:1380
+#: models.py:1392
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:1382
+#: models.py:1394
msgid "Link to an external CSS"
msgstr "Lien vers une feuille de style externe"
-#: models.py:1386
-msgid "Public can read the map"
-msgstr "Carte lisible publiquement"
-
-#: models.py:1387
-msgid "Public can propose item to the map"
-msgstr "Des propositions de modification peuvent être faites publiquement"
-
-#: models.py:1388
-msgid "Public can write without moderation to the map"
-msgstr "Des modifications peuvent être faites publiquement"
-
-#: models.py:1389
+#: models.py:1396
msgid "Restrict to the area extent"
msgstr "Restreindre à l'étendue de la zone"
-#: models.py:1398 templates/chimere/blocks/footer.html:2
-msgid "Map"
-msgstr "Carte"
-
-#: models.py:1593 models.py:1603
-msgid "Can read the map"
-msgstr "Peut lire la carte"
-
-#: models.py:1594 models.py:1604
-msgid "Can propose item to the map"
-msgstr "Peut proposer des éléments sur la carte"
-
-#: models.py:1595 models.py:1605
-msgid "Can write without moderation to the map"
-msgstr "Peut écrire sans modération sur la carte"
-
-#: models.py:1597
-msgid "Map - user"
-msgstr "Carte - Utilisateur"
-
-#: models.py:1598
-msgid "Map - users"
-msgstr "Cartes - Utilisateurs"
-
-#: models.py:1607
-msgid "Map - group"
-msgstr "Carte - Groupe"
-
-#: models.py:1608
-msgid "Map - groups"
-msgstr "Carte - Groupes"
-
-#: models.py:1614 widgets.py:89
+#: models.py:1532 widgets.py:89
msgid "Default layer"
msgstr "Couche par défaut"
-#: models.py:1618 models.py:1619
+#: models.py:1536 models.py:1537
msgid "Layers"
msgstr "Couches"
-#: models.py:1627
+#: models.py:1545
msgid "Mandatory"
msgstr "Obligatoire"
-#: models.py:1631
+#: models.py:1548
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:1633
+#: models.py:1550
msgid "Text"
msgstr "Texte"
-#: models.py:1634
+#: models.py:1551
msgid "Long text"
msgstr "Texte long"
-#: models.py:1637
+#: models.py:1554
msgid "Choices"
msgstr "Choix"
-#: models.py:1645
+#: models.py:1555
+msgid "Boolean"
+msgstr "Booléen"
+
+#: models.py:1564
msgid "Type"
msgstr "Type"
-#: models.py:1650 models.py:1671 models.py:1685
+#: models.py:1569 models.py:1585 models.py:1599
msgid "Property model"
msgstr "Modèle de propriété"
-#: models.py:1672 models.py:1686
+#: models.py:1586 models.py:1600
msgid "Value"
msgstr "Valeur"
-#: models.py:1678
+#: models.py:1592
msgid "Model property choice"
msgstr "Choix pour les modèles de propriété"
-#: models.py:1701
+#: models.py:1611
msgid "Property"
msgstr "Propriété"
-#: settings.sample.py:86
+#: settings.sample.py:94
msgid "Foot"
-msgstr "À pied"
+msgstr "À pieds"
-#: settings.sample.py:87
+#: settings.sample.py:95
msgid "Bicycle"
msgstr "À vélo"
-#: settings.sample.py:88
+#: settings.sample.py:96
msgid "Motorcar"
msgstr "En voiture"
-#: settings.sample.py:91
+#: settings.sample.py:99
msgid "You are walking slowly"
msgstr "Vous marchez lentement"
-#: settings.sample.py:92
+#: settings.sample.py:100
msgid "You are walking pretty quickly"
-msgstr "Vous marchez assez rapidement"
+msgstr "Vous marchez plutôt rapidement"
-#: settings.sample.py:93
+#: settings.sample.py:101
msgid "You are riding pretty slowly"
-msgstr "Vous roulez plutôt lentement"
+msgstr "Vous conduisez plutôt lentement"
-#: settings.sample.py:94
+#: settings.sample.py:102
msgid "You are riding pretty quickly"
-msgstr "Vous roulez plutôt rapidement"
+msgstr "Vous conduisez plutôt rapidement"
#: tasks.py:63
msgid "Import pending"
@@ -926,28 +906,28 @@ msgstr "Export échoué"
msgid "Export canceled"
msgstr "Export annulé"
-#: utils.py:150 utils.py:199
+#: utils.py:153 utils.py:202
msgid "Bad zip file"
msgstr "Mauvais fichier zip"
-#: utils.py:202
+#: utils.py:205
msgid "Missing file(s) inside the zip file"
msgstr "Fichier(s) manquant(s) dans l'archive zip"
-#: utils.py:243
+#: utils.py:246
msgid "Bad XML file"
msgstr "Mauvais fichier XML"
-#: utils.py:330
+#: utils.py:333
msgid "Error while reading the data source."
msgstr "Erreur lors de la lecture de la source."
-#: utils.py:348
+#: utils.py:351
#, python-format
msgid "SRID cannot be guessed. The default SRID (%s) has been used."
msgstr "Le SRID n'a pu être trouvé. Le SRID par défaut (%s) a été utilisé."
-#: utils.py:369
+#: utils.py:372
#, python-format
msgid ""
"Type of geographic item (%s) of this shapefile is not managed by Chimère."
@@ -955,44 +935,42 @@ msgstr ""
"Les types des éléments géographiques (%s) de ce fichier Shapefile ne sont "
"pas gérés par Chimère."
-#: utils.py:389
+#: utils.py:392
msgid "Bad Shapefile"
msgstr "Mauvais fichier Shapefile"
-#: utils.py:431
+#: utils.py:434
msgid "Could not create file!"
msgstr "Ne peut pas créer le fichier !"
-#: utils.py:442
+#: utils.py:445
msgid "Failed to create field"
msgstr "Ne peut pas créer un champ"
-#: utils.py:488 templates/admin/chimere/managed_modified.html:25
-#: templates/chimere/edit.html:49 templates/chimere/edit_route.html:44
-#: templates/chimere/main_map.html:26
+#: utils.py:491 templates/admin/chimere/managed_modified.html:25
+#: templates/chimere/edit.html:45 templates/chimere/edit_route.html:42
+#: templates/chimere/main_map.html:16
#: templates/chimere/main_map_simple.html:10
msgid "Categories"
msgstr "Catégories"
-#: utils.py:529
-msgid "Invalid CSV format - not enough columns check a reference CSV file"
-msgstr ""
-"Format CSV invalide - pas assez de colonnes - vérifiez sur un fichier CSV de "
-"référence"
+#: utils.py:524
+msgid "Invalid CSV format"
+msgstr "Fichier CSV non valide"
-#: utils.py:630
+#: utils.py:603
msgid "RSS feed is not well formed"
msgstr "Flux RSS non valide"
-#: utils.py:706
+#: utils.py:679
msgid "Nothing to import"
msgstr "Rien à importer"
-#: utils.py:790
+#: utils.py:763
msgid "New items imported - validate them before exporting"
msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter"
-#: utils.py:792
+#: utils.py:765
msgid ""
"There are items from a former import not yet validated - validate them "
"before exporting"
@@ -1000,19 +978,19 @@ msgstr ""
"Il y a des éléments d'un import précédent pas encore validé - Validez les "
"avant d'exporter"
-#: utils.py:804
+#: utils.py:777
msgid "Bad params - programming error"
msgstr "Mauvais paramètres - erreur de programmation"
-#: utils.py:814
+#: utils.py:787
msgid "Bad param"
msgstr "Mauvais paramètre"
-#: utils.py:829
+#: utils.py:802
msgid "No non ambigious tag is defined in the XAPI request"
msgstr "Pas de tag non ambigü définis dans la requête XAPI"
-#: utils.py:831
+#: utils.py:804
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"
@@ -1021,23 +999,40 @@ msgstr ""
"vouloir lancer la requête sur la planète entière fixez la « bounding box » "
"à -180,-90,180,90"
-#: views.py:161
-msgid "Invalid user or password."
-msgstr "Nom d'utilisateur ou mot de passe incorrect"
+#: utils.py:933
+msgid "Source page is unreachable."
+msgstr "La page source est inatteignable"
+
+#: utils.py:949
+msgid "The source file is not a valid XSLT file."
+msgstr "Le fichier source n'est pas un fichier XSLT valide"
+
+#: utils.py:961
+msgid "The alt source file is not a valid XSLT file."
+msgstr "Le fichier source alternatif n'est pas un fichier XSLT valide"
-#: views.py:315
+#: utils.py:1005
+#, python-format
+msgid ""
+"Names \"%s\" doesn't match existing categories. Modify the import to match "
+"theses names with categories."
+msgstr ""
+"Les noms \"%s\" ne correspondent pas à des catégories existantes. Modifiez "
+"l'import pour faire correspondre ces noms avec des catégories."
+
+#: views.py:302
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:405
+#: views.py:387
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:521
+#: views.py:502
msgid "Comments/request on the map"
msgstr "Commentaires/requètes sur la carte"
-#: views.py:524
+#: views.py:505
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."
@@ -1046,52 +1041,60 @@ msgstr ""
"laissé votre courriel vous serez peut-être contacté bientôt pour plus de "
"détails."
-#: views.py:528
+#: views.py:509
msgid "Temporary error. Renew your message later."
msgstr "Erreur temporaire. Réenvoyez votre message plus tard."
-#: views.py:722
+#: views.py:715
msgid "No category available in this area."
msgstr "Pas de catégorie disponible sur cette zone."
-#: views.py:822
+#: views.py:842
+msgid "Category does not exist"
+msgstr "Cette catégorie n'existe pas"
+
+#: views.py:900
msgid "Bad geometry"
msgstr "Géométrie incorrecte"
-#: views.py:911
+#: views.py:985
msgid "Incorrect choice in the list"
msgstr "Choix incorrect dans la liste"
-#: widgets.py:272
+#: widgets.py:243
+msgid "Street, City, Country"
+msgstr "Rue, Commune, Pays"
+
+#: widgets.py:281
msgid "Latitude"
msgstr "Latitude"
-#: widgets.py:274
+#: widgets.py:283
msgid "Longitude"
msgstr "Longitude"
-#: widgets.py:302
+#: widgets.py:326
msgid "Invalid point"
msgstr "Point invalide"
-#: widgets.py:359
+#: widgets.py:382
msgid "Creation mode"
msgstr "Mode création"
-#: widgets.py:360
+#: widgets.py:383
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:362
+#: widgets.py:385
msgid "Then click on the map to begin the drawing."
msgstr "Puis cliquez sur la carte pour commencer le dessin."
-#: widgets.py:363
+#: widgets.py:386
msgid "You can add points by clicking again."
msgstr "Vous pouvez ajouter des points en cliquant de nouveau."
-#: widgets.py:364
+#: widgets.py:387
msgid ""
"To finish the drawing double click. When the drawing is finished you can "
"edit it."
@@ -1099,7 +1102,7 @@ msgstr ""
"Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez "
"toujours l'éditer."
-#: widgets.py:366
+#: widgets.py:389
msgid ""
"While creating to undo a drawing click again on the toggle button \"Stop "
"drawing\"."
@@ -1107,17 +1110,17 @@ msgstr ""
"En mode création vous pouvez annuler un tracé en appuyant sur le bouton "
"«&nbsp;Arrêter le tracé&nbsp;»."
-#: widgets.py:371
+#: widgets.py:394
msgid "Modification mode"
msgstr "Mode modification"
-#: widgets.py:372
+#: widgets.py:395
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:373
+#: widgets.py:396
msgid ""
"To delete a point move the mouse cursor over it and press the \"d\" or \"Del"
"\" key."
@@ -1125,7 +1128,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:375
+#: widgets.py:398
msgid ""
"To add a point click in the middle of a segment and drag the new point to "
"the desired position"
@@ -1134,51 +1137,51 @@ msgstr ""
"maintenez le bouton appuyé et déplacez le nouveau point à la position "
"désirée."
-#: widgets.py:382
+#: widgets.py:405
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:385
+#: widgets.py:408
msgid "Upload a route file (GPX or KML)"
msgstr "Déposer un trajet (fichier GPX ou KML)"
-#: widgets.py:386
+#: widgets.py:409
msgid "or"
msgstr "ou"
-#: widgets.py:391
+#: widgets.py:414
msgid "Start \"hand\" drawing"
msgstr "Commencer le tracé manuellement"
-#: widgets.py:414
+#: widgets.py:437
msgid "Move on the map"
msgstr "Se déplacer"
-#: widgets.py:414
+#: widgets.py:437
msgid "Draw"
msgstr "Tracer"
-#: widgets.py:504
+#: widgets.py:527
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:561
+#: widgets.py:584
msgid "Type:"
msgstr "Type :"
-#: widgets.py:561
+#: widgets.py:584
msgid "Node"
msgstr "Nœud"
-#: widgets.py:562
+#: widgets.py:585
msgid "Way"
msgstr "Route"
-#: widgets.py:573
+#: widgets.py:596
msgid ""
"Enter an OSM \"tag=value\" string such as \"amenity=pub\". A list of common "
"tag is available <a href='https://wiki.openstreetmap.org/wiki/Map_Features' "
@@ -1188,39 +1191,39 @@ msgstr ""
"liste des clés est disponible <a href='https://wiki.openstreetmap.org/wiki/"
"FR:Map_Features' target='_blank'>ici</a>."
-#: widgets.py:580
+#: widgets.py:603
msgid "Tag:"
msgstr "Clé/valeur :"
-#: widgets.py:584
+#: widgets.py:607
msgid "You have to select an area."
msgstr "Vous devez sélectionner une zone."
-#: widgets.py:586
+#: widgets.py:609
msgid "You have to select a type."
msgstr "Vous devez sélectionner un type."
-#: widgets.py:588
+#: widgets.py:611
msgid "You have to insert a filter tag."
msgstr "Vous devez saisir une clé=valeur."
-#: widgets.py:590
+#: widgets.py:613
msgid "If you change the above form don't forget to refresh before submit!"
msgstr ""
"Si vous modifiez le formulaire ci-dessus n'oubliez pas de rafraîchir avant "
"de valider !"
-#: widgets.py:593
+#: widgets.py:616
msgid "You can put a Folder name of the KML file to filter on it."
msgstr ""
"Vous pouvez saisir le nom d'un « Folder » du fichier KML pour filter sur "
"celui-ci."
-#: widgets.py:601
+#: widgets.py:624
msgid "Refresh"
msgstr "Rafraîchir"
-#: widgets.py:667
+#: widgets.py:690
msgid "Select..."
msgstr "Sélectionner..."
@@ -1315,92 +1318,94 @@ msgstr ""
"Après ajout/modification de modèle de propriété vous aurez à recharger le "
"serveur web."
-#: templates/chimere/base.html:12
+#: templates/chimere/base.html:15
msgid "You must enable JavaScript in your browser to display Chimère."
msgstr ""
"Vous devez activer le JavaScript dans votre navigateur pour afficher Chimère."
-#: templates/chimere/contactus.html:16
-msgid ""
-"If you have some requests or remarks about this site you can leave them here."
-msgstr ""
-"Si vous avez des requètes, des remarques à propos de ce site vous pouvez "
-"nous laisser un commentaire ici."
-
-#: templates/chimere/contactus.html:19
-msgid "Submit"
-msgstr "Proposer"
+#: templates/chimere/category_directory.html:15
+msgid "No category defined!"
+msgstr "Pas de catégorie existante !"
-#: templates/chimere/detail.html:16
+#: templates/chimere/category_item_detail.html:17
+#: templates/chimere/detail.html:17
msgid "Date:"
msgstr "Date :"
-#: templates/chimere/detail.html:25
+#: templates/chimere/category_item_detail.html:26
+#: templates/chimere/detail.html:26
msgid "Source:"
msgstr "Source :"
-#: templates/chimere/detail.html:26
+#: templates/chimere/category_item_detail.html:27
+#: templates/chimere/detail.html:27
msgid "License:"
msgstr "Licence :"
-#: templates/chimere/detail.html:28
-msgid "Show multimedia gallery"
-msgstr "Montrer la galerie multimedia"
-
-#: templates/chimere/detail.html:33
-msgid "Edit"
-msgstr "Modifier"
+#: templates/chimere/category_item_detail.html:29
+msgid "See on the map"
+msgstr "Voir sur la carte"
+#: templates/chimere/category_item_detail.html:31
#: templates/chimere/detail.html:34
msgid "Submit an amendment"
msgstr "Proposer une modification"
-#: templates/chimere/detail.html:38 templates/chimere/detail.html.py:39
+#: templates/chimere/category_item_detail.html:34
+#: templates/chimere/category_item_detail.html:35
+#: templates/chimere/detail.html:37 templates/chimere/detail.html.py:38
msgid "Propose amendment"
msgstr "Proposer une modification"
-#: templates/chimere/detail.html:38
+#: templates/chimere/category_item_detail.html:34
+#: templates/chimere/detail.html:37
msgid "I would like to propose an amendment for this item:"
msgstr "Je souhaiterais proposer une modification pour cet élément :"
-#: templates/chimere/edit.html:22
+#: templates/chimere/contactus.html:16
+msgid ""
+"If you have some requests or remarks about this site you can leave them here."
+msgstr ""
+"Si vous avez des requètes, des remarques à propos de ce site vous pouvez "
+"nous laisser un commentaire ici."
+
+#: templates/chimere/contactus.html:19
+msgid "Submit"
+msgstr "Proposer"
+
+#: templates/chimere/detail.html:29
+msgid "Show multimedia gallery"
+msgstr "Montrer la galerie multimedia"
+
+#: templates/chimere/edit.html:20
msgid "Error"
msgstr "Erreur"
-#: templates/chimere/edit.html:25
+#: templates/chimere/edit.html:23 templates/chimere/edit_route.html:20
msgid ""
-"You have write rights for this map. Your modifications will be taking into "
+"You are logged as an administrator. Your modifications will be taking into "
"account immediately."
msgstr ""
-"Vous avez les droits d'écriture sur cette carte. Vos modifications vont être "
-"prises en compte immédiatement."
+"Vous êtes connecté comme administrateur. Vos modifications vont être prises "
+"en compte immédiatement."
-#: templates/chimere/edit.html:27
+#: templates/chimere/edit.html:25
msgid "Modify a point of interest"
msgstr "Modifier un point d'intérêt"
-#: templates/chimere/edit.html:27
+#: templates/chimere/edit.html:25
msgid "Add a point of interest"
msgstr "Ajout d'un point d'intérêt"
-#: templates/chimere/edit.html:29 templates/chimere/edit.html.py:180
-msgid "Add/modify"
-msgstr "Ajouter - Modifier"
-
-#: templates/chimere/edit.html:29 templates/chimere/edit.html.py:180
-#: templates/chimere/edit_route.html:103
-msgid "Propose"
-msgstr "Proposez"
-
-#: templates/chimere/edit.html:34
+#: templates/chimere/edit.html:31
msgid "Point"
msgstr "Point"
-#: templates/chimere/edit.html:35 templates/chimere/edit_route.html:31
+#: templates/chimere/edit.html:32 templates/chimere/edit_route.html:29
msgid "Select a location for this new site"
msgstr "Choisissez une localisation pour ce nouveau site"
-#: templates/chimere/edit.html:42 templates/chimere/edit_route.html:37
+#: templates/chimere/edit.html:38 templates/chimere/edit_route.html:35
msgid "indicates a mandatory field"
msgstr "indique un champ obligatoire"
@@ -1433,46 +1438,22 @@ msgstr "Commentaires au sujet de votre proposition"
msgid "Upload in progress. Please wait..."
msgstr "Dépôt en cours. Veuillez patienter..."
-#: templates/chimere/edit_route.html:22
-msgid ""
-"You are logged as an administrator. Your modifications will be taking into "
-"account immediately."
-msgstr ""
-"Vous êtes connecté comme administrateur. Vos modifications vont être prises "
-"en compte immédiatement."
+#: templates/chimere/edit.html:159 templates/chimere/edit_route.html:78
+msgid "Propose"
+msgstr "Proposez"
-#: templates/chimere/edit_route.html:24
+#: templates/chimere/edit_route.html:22
msgid "Modify a route"
msgstr "Modifier un trajet"
-#: templates/chimere/edit_route.html:24
+#: templates/chimere/edit_route.html:22
msgid "Add a route"
msgstr "Ajout d'un nouveau trajet"
-#: templates/chimere/main_map.html:22 templates/chimere/no_map.html:21
-msgid "Identified as: "
-msgstr "Identifié en tant que : "
-
-#: templates/chimere/main_map.html:22 templates/chimere/no_map.html:21
-msgid "Logout"
-msgstr "Se déconnecter"
-
-#: templates/chimere/main_map.html:48
+#: templates/chimere/main_map.html:38
msgid "Simple map"
msgstr "Carte simple"
-#: templates/chimere/no_map.html:31
-msgid "No map are currently available for your account."
-msgstr "Aucune carte n'est disponible actuellement pour votre compte."
-
-#: templates/chimere/no_map.html:33
-msgid ""
-"No map are currently available for public access. If you have an account "
-"identify yourself."
-msgstr ""
-"Aucune carte n'est disponible actuellement en accès public. Si vous avez un "
-"compte identifiez vous."
-
#: templates/chimere/upload_file.html:13
msgid "Thank you for your submission!"
msgstr "Merci pour votre proposition !"
@@ -1533,13 +1514,17 @@ msgstr "Vous devez renseigner un fichier ou une adresse web."
msgid "You must provide a web address."
msgstr "Vous devez fournir une adresse web."
-#: templates/chimere/blocks/areas.html:5 templates/chimere/blocks/maps.html:5
-msgid "Maps:"
-msgstr "Cartes :"
+#: templates/chimere/blocks/areas.html:4
+msgid "Maps"
+msgstr "Cartes"
+
+#: templates/chimere/blocks/areas_alternative.html:4
+msgid "Shortcuts"
+msgstr "Raccourcis"
+#: templates/chimere/blocks/areas_alternative.html:7
#: templates/chimere/blocks/categories.html:8
#: templates/chimere/blocks/categories.html:17
-#: templates/chimere/blocks/maps_alternative.html:7
msgid "Zoom to"
msgstr "Zoomer sur"
@@ -1556,19 +1541,23 @@ msgstr ""
msgid "This site uses Chimère"
msgstr "Ce site utilise Chimère"
-#: templates/chimere/blocks/map.html:9
+#: templates/chimere/blocks/footer.html:2
+msgid "Map"
+msgstr "Carte"
+
+#: templates/chimere/blocks/map.html:15
msgid "Loading of the map in progress"
msgstr "Chargement de la carte en cours"
-#: templates/chimere/blocks/map.html:13
+#: templates/chimere/blocks/map.html:19
msgid "Display options"
msgstr "Options d'affichage"
-#: templates/chimere/blocks/map.html:15
+#: templates/chimere/blocks/map.html:21
msgid "Map type"
msgstr "Type de carte"
-#: templates/chimere/blocks/map.html:25
+#: templates/chimere/blocks/map.html:32
msgid "Permalink"
msgstr "Lien permanent"
@@ -1604,10 +1593,6 @@ msgstr "Zoomer en arrière"
msgid "Center the map here"
msgstr "Centrer la carte ici"
-#: templates/chimere/blocks/maps_alternative.html:4
-msgid "Shortcuts"
-msgstr "Raccourcis"
-
#: templates/chimere/blocks/multimedia_file.html:19
msgid "Please use a modern browser or install the non free Flash-Plugin."
msgstr ""
@@ -1619,14 +1604,6 @@ msgstr ""
msgid "See it on the map"
msgstr "Voir sur la carte"
-#: templates/chimere/blocks/nominatim_widget.html:5
-msgid "Search:"
-msgstr "Rechercher :"
-
-#: templates/chimere/blocks/nominatim_widget.html:10
-msgid "Street, City, Country"
-msgstr "Rue, Commune, Pays"
-
#: templates/chimere/blocks/routing.html:5
msgid "Itinerary"
msgstr "Itinéraire"
@@ -1635,7 +1612,7 @@ msgstr "Itinéraire"
msgid "Add a step"
msgstr "Ajouter une étape"
-#: templates/chimere/blocks/routing.html:17
+#: templates/chimere/blocks/routing.html:17 templates/search/search.html:33
msgid "Search"
msgstr "Rechercher"
@@ -1667,43 +1644,27 @@ msgstr "Partager sur"
msgid "Share"
msgstr "Partager"
-#: templates/chimere/blocks/submited.html:6
-msgid "Your modification has been taken into account."
-msgstr "Votre modification a été prise en compte."
-
-#: templates/chimere/blocks/submited.html:8
-msgid ""
-"Your modification has been submited. A moderator will treat your submission "
-"shortly. Thanks!"
-msgstr ""
-"Votre proposition a été soumise. Un modérateur va traiter votre "
-"proposition sous peu. Merci !"
-
-#: templates/chimere/blocks/submited.html:12
-msgid "Your new proposition has been added."
-msgstr "Votre nouvelle proposition a été ajoutée."
-
-#: templates/chimere/blocks/submited.html:14
+#: templates/chimere/blocks/submited.html:3
msgid ""
-"Your new proposition has been submited. A moderator will treat your "
-"submission shortly. Thanks!"
+"Your new proposition/modification has been submited. A moderator will treat "
+"your submission shortly. Thanks!"
msgstr ""
-"Votre proposition a été soumise. Un modérateur va traiter votre "
+"Votre proposition/modification a été soumise. Un modérateur va traiter votre "
"proposition sous peu. Merci !"
-#: templates/chimere/blocks/submited.html:21
+#: templates/chimere/blocks/submited.html:8
msgid "Thank you"
msgstr "Merci"
-#: templates/chimere/blocks/submited.html:25
+#: templates/chimere/blocks/submited.html:12
msgid "Add a new item"
msgstr "Ajout d'un nouvel élément"
-#: templates/chimere/blocks/submited.html:29
+#: templates/chimere/blocks/submited.html:16
msgid "Continue edition of this item"
msgstr "Continuer l'édition de cet élément"
-#: templates/chimere/blocks/submited.html:33
+#: templates/chimere/blocks/submited.html:20
msgid "Return to the map"
msgstr "Retourner à la carte"
@@ -1736,8 +1697,8 @@ msgid "Choose a category"
msgstr "Choisir une catégorie"
#: templates/chimere/feeds/rss.html:51
-msgid "Choose a pre-defined map"
-msgstr "Choisir une carte pré-définie"
+msgid "Choose a pre-defined areas"
+msgstr "Choisir une zone pré-définie"
#: templates/chimere/feeds/rss.html:65
msgid "Or select the area by zooming and panning this map"
@@ -1751,17 +1712,35 @@ msgstr "Description :"
msgid ":"
msgstr " :"
-#: templatetags/chimere_tags.py:72
+#: templates/search/search.html:3
+msgid "Do you mean: "
+msgstr "Voulez-vous dire :"
+
+#: templates/search/search.html:4
+msgid "?"
+msgstr " ?"
+
+#: templates/search/search.html:15
+msgid "No results found."
+msgstr "Pas de résultats trouvés."
+
+#: templates/search/search.html:23
+msgid "Previous"
+msgstr "Précédent"
+
+#: templates/search/search.html:24
+msgid "More results..."
+msgstr "Plus de résultats..."
+
+#: templates/search/search.html:38
+msgid "No exact match."
+msgstr "Pas de correspondance exacte."
+
+#: templatetags/chimere_tags.py:93
#, python-format
msgid "Welcome to the %s"
msgstr "Bienvenue sur %s"
-#~ msgid "Invalid CSV format"
-#~ msgstr "Fichier CSV non valide"
-
-#~ msgid "Associated areas"
-#~ msgstr "Zones associées"
-
#~ msgid "Areas:"
#~ msgstr "Zones :"
@@ -1777,6 +1756,9 @@ msgstr "Bienvenue sur %s"
#~ msgid "Administration de Chimère"
#~ msgstr "Administration de Chimère"
+#~ msgid "Add/modify a site"
+#~ msgstr "Ajouter ou modifier un site"
+
#~ msgid "Categorys"
#~ msgstr "Catégories"
diff --git a/chimere/migrations/0010_auto__add_field_subcategory_keywords.py b/chimere/migrations/0010_auto__add_field_subcategory_keywords.py
new file mode 100644
index 0000000..3a05ac7
--- /dev/null
+++ b/chimere/migrations/0010_auto__add_field_subcategory_keywords.py
@@ -0,0 +1,291 @@
+# -*- 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 'SubCategory.keywords'
+ db.add_column('chimere_subcategory', 'keywords',
+ self.gf('django.db.models.fields.TextField')(max_length=200, null=True, blank=True),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'SubCategory.keywords'
+ db.delete_column('chimere_subcategory', 'keywords')
+
+
+ models = {
+ 'chimere.aggregatedroute': {
+ 'Meta': {'object_name': 'AggregatedRoute', 'db_table': "'chimere_aggregated_routes'", 'managed': 'False'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'route': ('django.contrib.gis.db.models.fields.MultiLineStringField', [], {}),
+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"})
+ },
+ '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', [], {'unique': 'True'}),
+ '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'},
+ 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'automatic_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'to': "orm['chimere.SubCategory']", 'null': 'True', 'blank': 'True'}),
+ 'default_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_localisation': ('chimere.widgets.PointField', [], {'null': 'True', 'blank': 'True'}),
+ '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'}),
+ 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'source_file_alt': ('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.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'chimere.importerkeycategories': {
+ 'Meta': {'object_name': 'ImporterKeyCategories'},
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'importer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_categories'", 'to': "orm['chimere.Importer']"}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ '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'}),
+ 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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.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'}),
+ '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']", 'null': 'True', 'blank': 'True'}),
+ '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', [], {'symmetrical': 'False', 'to': "orm['chimere.Area']", 'null': 'True', 'blank': 'True'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'date': ('django.db.models.fields.DateField', [], {}),
+ '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': {
+ '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.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'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'has_associated_marker': ('django.db.models.fields.BooleanField', [], {'default': '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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'},
+ 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}),
+ 'routing_warn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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/0011_auto__add_field_importer_default_status.py b/chimere/migrations/0011_auto__add_field_importer_default_status.py
new file mode 100644
index 0000000..bb36e42
--- /dev/null
+++ b/chimere/migrations/0011_auto__add_field_importer_default_status.py
@@ -0,0 +1,292 @@
+# -*- 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.default_status'
+ db.add_column('chimere_importer', 'default_status',
+ self.gf('django.db.models.fields.CharField')(default='I', max_length=1),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'Importer.default_status'
+ db.delete_column('chimere_importer', 'default_status')
+
+
+ models = {
+ 'chimere.aggregatedroute': {
+ 'Meta': {'object_name': 'AggregatedRoute', 'db_table': "'chimere_aggregated_routes'", 'managed': 'False'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'route': ('django.contrib.gis.db.models.fields.MultiLineStringField', [], {}),
+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"})
+ },
+ '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', [], {'unique': 'True'}),
+ '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'},
+ 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'automatic_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'to': "orm['chimere.SubCategory']", 'null': 'True', 'blank': 'True'}),
+ 'default_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_localisation': ('chimere.widgets.PointField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'default_status': ('django.db.models.fields.CharField', [], {'default': "'I'", 'max_length': '1'}),
+ 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'source_file_alt': ('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.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'chimere.importerkeycategories': {
+ 'Meta': {'object_name': 'ImporterKeyCategories'},
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'importer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_categories'", 'to': "orm['chimere.Importer']"}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ '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'}),
+ 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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.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'}),
+ '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']", 'null': 'True', 'blank': 'True'}),
+ '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', [], {'symmetrical': 'False', 'to': "orm['chimere.Area']", 'null': 'True', 'blank': 'True'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'date': ('django.db.models.fields.DateField', [], {}),
+ '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': {
+ '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.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'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'has_associated_marker': ('django.db.models.fields.BooleanField', [], {'default': '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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'},
+ 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}),
+ 'routing_warn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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/0012_auto__chg_field_importer_filtr.py b/chimere/migrations/0012_auto__chg_field_importer_filtr.py
new file mode 100644
index 0000000..84e4c72
--- /dev/null
+++ b/chimere/migrations/0012_auto__chg_field_importer_filtr.py
@@ -0,0 +1,290 @@
+# -*- 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):
+
+ # Changing field 'Importer.filtr'
+ db.alter_column('chimere_importer', 'filtr', self.gf('django.db.models.fields.TextField')(null=True))
+
+ def backwards(self, orm):
+
+ # Changing field 'Importer.filtr'
+ db.alter_column('chimere_importer', 'filtr', self.gf('django.db.models.fields.CharField')(max_length=200, null=True))
+
+ models = {
+ 'chimere.aggregatedroute': {
+ 'Meta': {'object_name': 'AggregatedRoute', 'db_table': "'chimere_aggregated_routes'", 'managed': 'False'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'route': ('django.contrib.gis.db.models.fields.MultiLineStringField', [], {}),
+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"})
+ },
+ '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', [], {'unique': 'True'}),
+ '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'},
+ 'associate_marker_to_way': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'automatic_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'to': "orm['chimere.SubCategory']", 'null': 'True', 'blank': 'True'}),
+ 'default_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_localisation': ('chimere.widgets.PointField', [], {'null': 'True', 'blank': 'True'}),
+ 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'default_status': ('django.db.models.fields.CharField', [], {'default': "'I'", 'max_length': '1'}),
+ 'filtr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'get_description': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ 'source_file_alt': ('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.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'chimere.importerkeycategories': {
+ 'Meta': {'object_name': 'ImporterKeyCategories'},
+ 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.SubCategory']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'importer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_categories'", 'to': "orm['chimere.Importer']"}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ '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'}),
+ 'is_front_page': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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.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'}),
+ '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']", 'null': 'True', 'blank': 'True'}),
+ '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', [], {'symmetrical': 'False', 'to': "orm['chimere.Area']", 'null': 'True', 'blank': 'True'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'date': ('django.db.models.fields.DateField', [], {}),
+ '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': {
+ '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.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'}),
+ 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}),
+ 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'has_associated_marker': ('django.db.models.fields.BooleanField', [], {'default': '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', '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': 'True'}),
+ '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'},
+ 'as_layer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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'}),
+ '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'}),
+ 'keywords': ('django.db.models.fields.TextField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}),
+ 'routing_warn': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ '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/models.py b/chimere/models.py
index 15d264b..9a91a74 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -46,7 +46,8 @@ from chimere.widgets import HiddenPointChooserWidget, PointField, RouteField, \
DatePickerWidget
from chimere.managers import BaseGeoManager
from chimere.utils import KMLManager, OSMManager, ShapefileManager, \
- GeoRSSManager, CSVManager, HtmlXsltManager, XMLXsltManager
+ GeoRSSManager, CSVManager, HtmlXsltManager, XMLXsltManager, JsonManager
+
class Page(models.Model):
"""Simple extra pages
@@ -106,7 +107,7 @@ class News(models.Model):
date = models.DateField(_(u"Date"))
content = models.TextField()
url = models.URLField(_(u"Url"), max_length=200, blank=True, null=True)
- maps = SelectMultipleField('Map', verbose_name=_(u"Associated maps"),
+ areas = SelectMultipleField('Area', verbose_name=_(u"Associated areas"),
blank=True, null=True)
def __unicode__(self):
ordering = ["-date"]
@@ -172,8 +173,7 @@ class Color(models.Model):
"""
code = models.CharField(_(u"Code"), max_length=6)
order = models.IntegerField(_(u"Order"))
- color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"),
- related_name='colors')
+ color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"))
def __unicode__(self):
return self.code
class Meta:
@@ -184,7 +184,6 @@ class Category(models.Model):
"""Category of Point Of Interest (POI)
"""
name = models.CharField(_(u"Name"), max_length=150)
- slug = models.SlugField()
available = models.BooleanField(_(u"Available"))
order = models.IntegerField(_(u"Order"))
description = models.TextField(blank=True, null=True)
@@ -213,12 +212,9 @@ class SubCategory(models.Model):
category = models.ForeignKey(Category, verbose_name=_(u"Category"),
related_name='subcategories')
name = models.CharField(_(u"Name"), max_length=150)
- slug = models.SlugField()
available = models.BooleanField(_(u"Available"), default=True)
submission = models.BooleanField(_(u"Available for submission"),
default=True)
- weighted = models.BooleanField(_(u"Has an associated quantity"),
- default=False)
TYPE = (('M', _(u'Marker')),
('R', _(u'Route')),
('B', _(u'Both')),)
@@ -234,6 +230,8 @@ class SubCategory(models.Model):
default=False)
routing_warn = models.BooleanField(_(u"Routing warn"), default=False)
order = models.IntegerField(_(u"Order"), default=1000)
+ keywords = models.TextField(_(u"Keywords"), max_length=200,
+ blank=True, null=True)
def __unicode__(self):
return u"%s / %s" % (self.category.name, self.name)
class Meta:
@@ -242,7 +240,7 @@ class SubCategory(models.Model):
verbose_name_plural = _(u"Sub-categories")
@classmethod
- def getAvailable(cls, item_types=None, map_name=None, public=False):
+ def getAvailable(cls, item_types=None, area_name=None, public=False):
'''Get list of tuples with first the category and second the associated
subcategories
'''
@@ -255,14 +253,14 @@ class SubCategory(models.Model):
if public:
subcategories = subcategories.filter(submission=True)
selected_cats = []
- if map_name:
- map = Map.objects.get(urn=map_name)
+ if area_name:
+ area = Area.objects.get(urn=area_name)
# if there some restrictions with categories limit them
- if map.subcategories.count():
- sub_ids = [sub.id for sub in map.subcategories.all()]
+ if area.subcategories.count():
+ sub_ids = [sub.id for sub in area.subcategories.all()]
subcategories = subcategories.filter(id__in=sub_ids)
selected_cats = [subcat.pk
- for subcat in map.default_subcategories.all()]
+ for subcat in area.default_subcategories.all()]
for sub_category in subcategories.order_by('order'):
if sub_category.category not in sub_categories:
sub_categories[sub_category.category] = []
@@ -278,10 +276,10 @@ class SubCategory(models.Model):
return subcategories
@classmethod
- def getAvailableTuples(cls, item_types=None, map_name=None):
+ def getAvailableTuples(cls, item_types=None, area_name=None):
cats = []
for cat, subcats in cls.getAvailable(item_types=item_types,
- map_name=map_name):
+ area_name=area_name):
cats.append((unicode(cat),
[(subcat.pk, subcat.name) for subcat in subcats]))
return cats
@@ -304,13 +302,29 @@ class SubCategory(models.Model):
json_string = json.dumps(self.getJSONDict())
return json_string
-IMPORTERS = {'KML':KMLManager,
- 'OSM':OSMManager,
- 'SHP':ShapefileManager,
- 'RSS':GeoRSSManager,
- 'CSV':CSVManager,
- 'XSLT':HtmlXsltManager,
- 'XXLT':XMLXsltManager
+ @property
+ def slug(self):
+ return defaultfilters.slugify(self.name)
+
+ @property
+ def item_nb(self):
+ return Marker.objects.filter(categories=self).count()
+
+STATUS = (('S', _(u'Submited')),
+ ('A', _(u'Available')),
+ ('M', _(u'Modified')),
+ ('D', _(u'Disabled')),
+ ('I', _(u'Imported')))
+STATUS_DCT = dict(STATUS)
+
+IMPORTERS = {'KML': KMLManager,
+ 'OSM': OSMManager,
+ 'SHP': ShapefileManager,
+ 'RSS': GeoRSSManager,
+ 'CSV': CSVManager,
+ 'JSON': JsonManager,
+ 'XSLT': HtmlXsltManager,
+ 'XXLT': XMLXsltManager
}
IMPORTER_CHOICES = (('KML', 'KML'),
@@ -318,20 +332,21 @@ IMPORTER_CHOICES = (('KML', 'KML'),
('SHP', 'Shapefile'),
('RSS', 'GeoRSS'),
('CSV', 'CSV'),
+ ('JSON', 'JSON'),
('XSLT', 'HTML-XSLT'),
('XXLT', 'XML-XSLT'),
)
IMPORTER_CHOICES_DICT = dict(IMPORTER_CHOICES)
+
class Importer(models.Model):
'''
Data importer for a specific subcategory
'''
importer_type = models.CharField(_(u"Importer type"), max_length=4,
choices=IMPORTER_CHOICES)
- filtr = models.CharField(_(u"Filter"), max_length=200,
- blank=True, null=True)
+ filtr = models.TextField(_(u"Filter"), blank=True, null=True)
source = models.CharField(_(u"Web address"), max_length=200,
blank=True, null=True,
help_text=_(u"Don't forget the trailing slash"))
@@ -360,6 +375,8 @@ class Importer(models.Model):
u"a marker to a way"), default=False)
automatic_update = models.BooleanField(_(u"Automatically updated"),
default=False)
+ default_status = models.CharField(_(u"Default status"), max_length=1,
+ choices=STATUS, default='I')
default_localisation = PointField(_(u"Default localisation"),
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION,
blank=True, null=True,
@@ -396,6 +413,7 @@ class Importer(models.Model):
dct[key_cat.key] = key_cat.category
return dct
+
class ImporterKeyCategories(models.Model):
"""
Association between key and categories
@@ -408,13 +426,6 @@ class ImporterKeyCategories(models.Model):
class Meta:
verbose_name = _(u"Importer - Key categories")
-STATUS = (('S', _(u'Submited')),
- ('A', _(u'Available')),
- ('M', _(u'Modified')),
- ('D', _(u'Disabled')),
- ('I', _(u'Imported')))
-STATUS_DCT = dict(STATUS)
-
class GeographicItem(models.Model):
name = models.CharField(_(u"Name"), max_length=150)
categories = SelectMultipleField(SubCategory)
@@ -473,7 +484,12 @@ class GeographicItem(models.Model):
if not _set:
new_keys += '%s:%s;' % (key, value)
self.import_key = new_keys
+ modified_since_import = self.modified_since_import
self.save()
+ # preserve modified_since_import
+ if modified_since_import != self.modified_since_import:
+ self.modified_since_import = modified_since_import
+ self.save()
def has_modified(self):
if (self.ref_item and self.ref_item != self) \
@@ -511,8 +527,6 @@ class Marker(GeographicItem):
null=True) # used by feeds
route = models.ForeignKey(u"Route", blank=True, null=True,
related_name='associated_marker')
- weight = models.IntegerField(_(u"Quantity"), blank=True, null=True,
- default=0)
description = models.TextField(_(u"Description"), blank=True, null=True)
is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True,
null=True)
@@ -582,10 +596,6 @@ class Marker(GeographicItem):
def geom_attr(self):
return 'point'
- @property
- def has_weight(self):
- return bool(self.categories.filter(weighted=True).count())
-
class Meta:
ordering = ('status', 'name')
verbose_name = _(u"Point of interest")
@@ -667,32 +677,6 @@ class Marker(GeographicItem):
val = values[unicode(propertymodel.id)]
self.setProperty(propertymodel, val)
- PROPERTIES_KEYS = ['point', 'pk', 'name', 'weight']
- @classmethod
- def _getJson(cls, values, base_dct={"properties":{}}):
- item = base_dct.copy()
- item["geometry"] = {"type": "Point",
- "coordinates": [values['point'].x,
- values['point'].y]}
- item["properties"]['pk'] = values['pk']
- item["properties"]['name'] = values['name']
- if values['weight']:
- item["properties"]['weight'] = values['weight']
- return item
-
- def _getItems(self, base_dct={"properties":{}}):
- '''Return a dict representation for json
- '''
- item = base_dct.copy()
- item["geometry"] = {"type": "Point",
- "coordinates": [ self.point.x, self.point.y ]
- }
- item["properties"]['pk'] = self.pk
- item["properties"]['name'] = self.name
- if self.weight:
- item["properties"]['weight'] = self.weight
- return item
-
def getGeoJSON(self, categories_id=[]):
'''Return a GeoJSON string
'''
@@ -707,31 +691,14 @@ class Marker(GeographicItem):
'pk':self.id,
'name':self.name,
'icon_path':unicode(cat.icon.image),
- 'icon_hover_path':cat.hover_icon.image \
+ 'icon_hover_path':unicode(cat.hover_icon.image) \
if cat.hover_icon else '',
'category_name':cat.name})
- items['weight'] = ''
- if cat.weighted:
- if not self.weight:
- continue
- items['weight'] = self.weight
- if cat.color_theme and cat.color_theme.colors.count():
- items['colors'] += ["#%s"] % '", "#'.join(
- [color.code for color in cat.color_theme.colors.\
- order_by('order').all()])
try:
items['properties'].update({'icon_width':cat.icon.image.width,
'icon_height':cat.icon.image.height,})
except IOError:
pass
- if cat.weighted:
- if not self.weight:
- continue
- items['weight'] = u', "weight":%d' % self.weight
- if cat.color_theme and cat.color_theme.colors.count():
- items['weight'] += u', "colors":["#%s"]' % '", "#'.join(
- [color.code for color in cat.color_theme.colors.\
- order_by('order').all()])
jsons.append(items)
@@ -745,20 +712,20 @@ class Marker(GeographicItem):
if cats.count():
return cats.all()[0]
- def get_absolute_url(self, map_name=''):
+ def get_absolute_url(self, area_name=''):
parameters = 'current_feature=%d' % self.id
if self.default_category:
parameters += '&checked_categories=%s' % self.default_category.pk
urn = TinyUrl.getUrnByParameters(parameters)
- map_name = map_name + '/' if map_name else ''
- url = reverse('chimere:tiny', args=[map_name, urn])
+ area_name = area_name + '/' if area_name else ''
+ url = reverse('chimere:tiny', args=[area_name, urn])
return url
-
PRE_ATTRS = {
- 'Marker':('name', 'geometry', 'import_version', 'modified_since_import'),
+ 'Marker':('name', 'description', 'start_date', 'geometry', 'import_version',
+ 'modified_since_import'),
'Route':('name', 'geometry', 'import_version', 'modified_since_import'),
- 'Map':('urn', 'name'),
+ 'Area':('urn', 'name'),
}
def geometry_pre_save(cls, pre_save_geom_values):
def geom_pre_save(sender, **kwargs):
@@ -767,8 +734,9 @@ 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] = [getattr(instance, attr)
- for attr in PRE_ATTRS[cls.__name__]]
+ pre_save_geom_values[instance.pk] = dict(
+ [(attr, getattr(instance, attr))
+ for attr in PRE_ATTRS[cls.__name__]])
except ObjectDoesNotExist:
pass
return geom_pre_save
@@ -786,24 +754,25 @@ def geometry_post_save(pre_save_geom_values):
or kwargs['instance'].pk not in pre_save_geom_values:
return
instance = kwargs['instance']
- name, geometry, import_version, modified_since_import = \
- pre_save_geom_values[instance.pk]
+ pre = pre_save_geom_values[instance.pk]
# force the reinit of modified_since_import
- if modified_since_import != instance.modified_since_import:
+ if pre['modified_since_import'] != instance.modified_since_import:
return
- if (instance.import_version != import_version
+ if (instance.import_version != pre['import_version']
and instance.modified_since_import):
instance.modified_since_import = False
instance.save()
return
if instance.modified_since_import:
return
- if instance.name != name or instance.geometry != geometry:
+ if [key for key in pre if pre not in ('import_version',
+ 'modified_since_import') and
+ getattr(instance, key) != pre[key]]:
instance.modified_since_import = True
instance.save()
return geom_post_save
def marker_post_save(sender, **kwargs):
- if not kwargs['instance']:
+ if not kwargs['instance'] or kwargs['created']:
return
geometry_post_save(pre_save_marker_values)(sender, **kwargs)
post_save.connect(marker_post_save, sender=Marker)
@@ -1196,13 +1165,6 @@ class Route(GeographicItem):
properties.append(property)
return properties
- def _getItems(self, dct={'properties':{}}):
- dct['geometry'] = { "type": "LineString",
- "coordinates": [[point.x, point.y]
- for point in self.route]}
- dct['properties'].update({'id':self.id, 'name':self.name})
- return dct
-
def getGeoJSON(self, color="#000"):
'''Return a GeoJSON string
'''
@@ -1343,14 +1305,14 @@ class SimpleArea:
return True
return False
- def getCategories(self, status='A', filter_available=True, map_name=None):
+ def getCategories(self, status='A', filter_available=True, area_name=None):
"""
- Get categories for this map
+ Get categories for this area
"""
wheres = []
- if map_name:
+ if area_name:
subcategory_pks = []
- for cat, subcats in SubCategory.getAvailable(map_name=map_name):
+ for cat, subcats in SubCategory.getAvailable(area_name=area_name):
for subcat in subcats:
subcategory_pks.append(unicode(subcat.pk))
if filter_available:
@@ -1414,43 +1376,37 @@ class Layer(models.Model):
class Meta:
verbose_name = _("Layer")
-class Map(models.Model, SimpleArea):
- """A map
+class Area(models.Model, SimpleArea):
+ """Rectangular area of the map
"""
name = models.CharField(_(u"Name"), max_length=150)
- available = models.BooleanField(_(u"Available"))
- users = models.ManyToManyField(User, through='MapUsers')
- urn = models.SlugField(_(u"Map urn"), max_length=50, blank=True,
+ urn = models.SlugField(_(u"Area urn"), max_length=50, blank=True,
unique=True)
welcome_message = models.TextField(_(u"Welcome message"), blank=True,
null=True)
order = models.IntegerField(_(u"Order"), unique=True)
+ available = models.BooleanField(_(u"Available"))
upper_left_corner = models.PointField(_(u"Upper left corner"),
default='POINT(0 0)', srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
lower_right_corner = models.PointField(_(u"Lower right corner"),
default='POINT(0 0)', srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
- default = models.BooleanField(_(u"Default map"), default=False,
- help_text=_(u"Only one map is set by default"))
- layers = SelectMultipleField(Layer, related_name='maps',
- through='MapLayers', blank=True)
+ default = models.NullBooleanField(_(u"Default area"),
+ help_text=_(u"Only one area is set by default"))
+ layers = SelectMultipleField(Layer, related_name='areas',
+ through='AreaLayers', blank=True)
default_subcategories = SelectMultipleField(SubCategory, blank=True,
verbose_name=_(u"Sub-categories checked by default"))
dynamic_categories = models.NullBooleanField(
_(u"Sub-categories dynamicaly displayed"),
help_text=_(u"If checked, categories are only displayed in the menu if "
u"they are available on the current extent."))
- subcategories = SelectMultipleField(SubCategory, related_name='maps',
- blank=True, db_table='chimere_subcategory_maps',
+ subcategories = SelectMultipleField(SubCategory, related_name='areas',
+ blank=True, db_table='chimere_subcategory_areas',
verbose_name=_(u"Restricted to theses sub-categories"),
help_text=_(u"If no sub-category is set all sub-categories are "
u"available"))
external_css = models.URLField(_(u"Link to an external CSS"), blank=True,
null=True)
- cluster = models.BooleanField(u"Clustering map (weight of items are added)",
- default=False)
- public_read = models.BooleanField(_(u"Public can read the map"))
- public_propose = models.BooleanField(_(u"Public can propose item to the map"))
- public_write = models.BooleanField(_(u"Public can write without moderation to the map"))
restrict_to_extent = models.BooleanField(_(u"Restrict to the area extent"),
default=False)
objects = models.GeoManager()
@@ -1460,72 +1416,13 @@ class Map(models.Model, SimpleArea):
class Meta:
ordering = ('order', 'name')
- verbose_name = _("Map")
-
- def can_write(self, user=None):
- return bool(self.getAvailable(user=user, urn=self.urn, single=True,
- edit=True))
-
- def can_propose(self, user=None):
- return bool(self.getAvailable(user=user, urn=self.urn, single=True,
- propose=True))
+ verbose_name = _("Area")
@classmethod
- def getAvailable(cls, user=None, urn=None, single=False, edit=False,
- propose=False):
- '''Get available maps
+ def getAvailable(cls):
+ '''Get available areas
'''
- map_filter = {'available':True}
- if urn:
- map_filter['urn'] = urn
- elif single:
- map_filter['default'] = True
- filters = []
- if not propose and not edit:
- filters = [{'public_write':True},
- {'public_propose':True},
- {'public_read':True}]
- elif propose:
- filters = [{'public_write':True},
- {'public_propose':True}]
- elif edit:
- filters = [{'public_write':True}]
- if user and user.is_authenticated():
- if not propose and not edit:
- filters += [
- {'mapusers__user':user, 'mapusers__read':True},
- {'mapusers__user':user, 'mapusers__write':True},
- {'mapusers__user':user, 'mapusers__propose':True},
- {'mapgroups__group__user':user, 'mapgroups__read':True},
- {'mapgroups__group__user':user, 'mapgroups__write':True},
- {'mapgroups__group__user':user, 'mapgroups__propose':True}
- ]
- elif propose:
- filters += [
- {'mapusers__user':user, 'mapusers__write':True},
- {'mapusers__user':user, 'mapusers__propose':True},
- {'mapgroups__group__user':user, 'mapgroups__write':True},
- {'mapgroups__group__user':user, 'mapgroups__propose':True}
- ]
- elif edit:
- filters += [
- {'mapusers__user':user, 'mapusers__write':True},
- {'mapgroups__group__user':user, 'mapgroups__write':True},
- ]
- query = None
- for fltr in filters:
- fltr.update(map_filter)
- if not query:
- query = Q(**fltr)
- else:
- query = query | Q(**fltr)
- maps = cls.objects.filter(query).distinct()
- if single:
- if not maps.count():
- return
- return maps.all()[0]
- else:
- return maps.all()
+ return cls.objects.filter(available=True)
def getWkt(self):
return "SRID=%d;POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f))" % (
@@ -1549,66 +1446,54 @@ class Map(models.Model, SimpleArea):
"""
return Q(route__contained=self.getWkt())
-pre_save_map_values = {}
-def map_pre_save(sender, **kwargs):
+pre_save_area_values = {}
+def area_pre_save(sender, **kwargs):
if not kwargs['instance']:
return
- geometry_pre_save(Map, pre_save_map_values)(sender, **kwargs)
-pre_save.connect(map_pre_save, sender=Map)
+ geometry_pre_save(Area, pre_save_area_values)(sender, **kwargs)
+pre_save.connect(area_pre_save, sender=Area)
-def map_post_save(sender, **kwargs):
+def area_post_save(sender, **kwargs):
if not kwargs['instance']:
return
- map = kwargs['instance']
- if map.default:
- defaults = Map.objects.filter(default=True).exclude(pk=map.pk)
+ area = kwargs['instance']
+ if area.default:
+ defaults = Area.objects.filter(default=True).exclude(pk=area.pk)
for default in defaults:
default.default = False
default.save()
# manage permissions
- old_urn, old_name = map.urn, map.name
- if map.pk in pre_save_map_values:
- old_urn, old_name = pre_save_map_values[map.pk]
+ 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 map.urn != old_urn:
- oldmnemo = 'change_map_' + old_urn
+ 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]
- codename = 'change_map_' + map.urn
- if not Permission.objects.filter(codename=codename).count():
- perm.codename = codename
- perm.save()
- if not map.urn:
- map.urn = defaultfilters.slugify(map.name)
- map.save()
-
- # fix old mnemo
- oldmnemo = 'change_area_' + old_urn
- old_perm = Permission.objects.filter(codename=oldmnemo)
- if old_perm.count():
- perm = old_perm.all()[0]
- perm.codename = 'change_map_' + map.urn
- perm.save()
-
- mnemo = 'change_map_' + map.urn
+ 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 " + map.name
+ lbl = "Can change " + area.name
if not perm.count():
content_type, created = ContentType.objects.get_or_create(
- app_label="chimere", model="map")
+ 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 != map.name:
+ if old_name != area.name:
perm.name = lbl
perm.save()
# manage moderation group
- groupname = map.name + " moderation"
- if old_name != map.name:
+ 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():
@@ -1629,56 +1514,36 @@ def map_post_save(sender, **kwargs):
for p in Permission.objects.filter(content_type=ct).all():
group.permissions.add(p)
-post_save.connect(map_post_save, sender=Map)
+post_save.connect(area_post_save, sender=Area)
-def get_maps_for_user(user):
+def get_areas_for_user(user):
"""
- Getting maps for a specific user
+ Getting subcats for a specific user
"""
perms = user.get_all_permissions()
- maps = set()
- prefix = 'chimere.change_map_'
+ areas = set()
+ prefix = 'chimere.change_area_'
for perm in perms:
if perm.startswith(prefix):
try:
- map = Map.objects.get(urn=perm[len(prefix):])
- maps.add(map)
+ area = Area.objects.get(urn=perm[len(prefix):])
+ areas.add(area)
except ObjectDoesNotExist:
pass
- return maps
+ return areas
-def get_users_by_map(map):
- if not map:
+def get_users_by_area(area):
+ if not area:
return []
- perm = 'change_map_'+map.urn
+ perm = 'change_area_'+area.urn
return User.objects.filter(Q(groups__permissions__codename=perm)|
Q(user_permissions__codename=perm)).all()
-class MapUsers(models.Model):
- map = models.ForeignKey(Map, related_name='mapusers')
- user = models.ForeignKey(User, related_name='mapusers')
- read = models.BooleanField(_(u"Can read the map"))
- propose = models.BooleanField(_(u"Can propose item to the map"))
- write = models.BooleanField(_(u"Can write without moderation to the map"))
- class Meta:
- verbose_name = _("Map - user")
- verbose_name_plural = _("Map - users")
-
-class MapGroups(models.Model):
- map = models.ForeignKey(Map, related_name='mapgroups')
- group = models.ForeignKey(Group, related_name='mapgroups')
- read = models.BooleanField(_(u"Can read the map"))
- propose = models.BooleanField(_(u"Can propose item to the map"))
- write = models.BooleanField(_(u"Can write without moderation to the map"))
- class Meta:
- verbose_name = _("Map - group")
- verbose_name_plural = _("Map - groups")
-
-class MapLayers(models.Model):
- map = models.ForeignKey(Map)
+class AreaLayers(models.Model):
+ area = models.ForeignKey(Area)
layer = models.ForeignKey(Layer)
order = models.IntegerField(_(u"Order"))
- default = models.BooleanField(_(u"Default layer"), default=False)
+ default = models.NullBooleanField(_(u"Default layer"))
class Meta:
ordering = ('order',)
@@ -1692,7 +1557,6 @@ class PropertyModel(models.Model):
order = models.IntegerField(_(u"Order"))
available = models.BooleanField(_(u"Available"))
mandatory = models.BooleanField(_(u"Mandatory"))
- slug = models.SlugField()
subcategories = SelectMultipleField(SubCategory, related_name='properties',
blank=True, verbose_name=_(u"Restricted to theses sub-categories"),
help_text=_(u"If no sub-category is set all the property applies to all "
@@ -1701,7 +1565,6 @@ class PropertyModel(models.Model):
('L', _('Long text')),
('P', _('Password')),
('D', _("Date")),
- ('B', _("Boolean")),
('C', _("Choices")),
('B', _("Boolean")),
)
@@ -1720,7 +1583,8 @@ class PropertyModel(models.Model):
verbose_name = _("Property model")
def getAttrName(self):
- attr_name = self.slug.replace('-', '_')
+ attr_name = defaultfilters.slugify(self.name)
+ attr_name = re.sub(r'-','_', attr_name)
return attr_name
def getNamedId(self):
@@ -1728,11 +1592,6 @@ class PropertyModel(models.Model):
'''
return 'property_%d_%d' % (self.order, self.id)
- def save(self, *args, **kwargs):
- if not self.slug:
- self.slug = defaultfilters.slugify(self.name)
- super(PropertyModel, self).save(*args, **kwargs)
-
class PropertyModelChoice(models.Model):
'''Choices for property model
'''
@@ -1753,9 +1612,10 @@ class Property(models.Model):
propertymodel = models.ForeignKey(PropertyModel,
verbose_name=_(u"Property model"))
value = models.TextField(_(u"Value"))
-
def __unicode__(self):
- if self.value and self.propertymodel.type == 'C':
+ if self.propertymodel.type == 'C':
+ if not self.value:
+ return ''
try:
return unicode(PropertyModelChoice.objects.get(
pk=self.value).value)
@@ -1763,9 +1623,6 @@ class Property(models.Model):
return ""
return unicode(self.value)
- def label(self):
- return unicode(self)
-
class Meta:
verbose_name = _(u"Property")
@@ -1779,7 +1636,7 @@ class Property(models.Model):
if self.propertymodel.type == 'C' and self.value:
try:
return PropertyModelChoice.objects.get(pk=self.value)
- except self.DoesNotExist:
+ except (self.DoesNotExist, ValueError):
return None
else:
return self.value
diff --git a/chimere/settings.sample.py b/chimere/settings.sample.py
index 1ddeca6..357ccef 100644
--- a/chimere/settings.sample.py
+++ b/chimere/settings.sample.py
@@ -57,6 +57,8 @@ CHIMERE_DAYS_BEFORE_EVENT = 30
CHIMERE_ALL_DATED_ARE_FRONT = False
# allow feeds
CHIMERE_FEEDS = True
+# display a directory of items
+CHIMERE_DIRECTORY = False
CHIMERE_ICON_WIDTH = 21
CHIMERE_ICON_HEIGHT = 25
@@ -132,6 +134,8 @@ HAYSTACK_CONNECTIONS = {
'URL': 'http://127.0.0.1:8080/solr'
},
}
+HAYSTACK_SEARCH_RESULTS_PER_PAGE = 12
+HAYSTACK_AUTOCOMPLETE = False
CHIMERE_CSV_ENCODING = 'ISO-8859-1'
diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css
index dd27d95..52832b0 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -501,6 +501,11 @@ ul.share li{
margin:0;
}
+span.icon{
+ display:inline-block;
+ width:70px;
+}
+
#frm_categories{
padding:0;
margin:0;
@@ -837,6 +842,7 @@ table.inline-table td input[type=file]{
list-style-type:none;
margin:0;
padding:4px;
+ padding-bottom: 70px;
}
#search-listing ul li{
@@ -1138,11 +1144,25 @@ div.pp_default .pp_expand{
padding:0 6px;
}
+#category-directory ul{
+ padding:0;
+}
+
+.category-directory-category{
+ font-variant: small-caps;
+ font-weight: bold;
+}
+
.olControlSimplePanZoom {
top: 20px;
right: 10px;
}
+.olControlSimplePanZoom #zoombar,
+.olControlSimplePanZoom #slider{
+ display: none;
+}
+
.olControlSimplePanZoom .button {
background-image: url('../img/map_sprite.png');
position:absolute;
@@ -1189,11 +1209,12 @@ div.pp_default .pp_expand{
}
.olControlSimplePanZoom #zoomout {
- top:210px;
+ top:70px;
width:25px;
height:20px;
left:10px;
background-position: -15px -220px;
+ border-top:1px solid #ccc;
}
.olControlSimplePanZoom #slider {
diff --git a/chimere/static/chimere/js/importer_interface.js b/chimere/static/chimere/js/importer_interface.js
index 65bcf8c..1b95fb0 100644
--- a/chimere/static/chimere/js/importer_interface.js
+++ b/chimere/static/chimere/js/importer_interface.js
@@ -2,35 +2,42 @@ django.jQuery(function($) {
var importer_form_filter = {
OSM:new Array('field-filtr', 'field-default_name', 'field-categories',
'field-source', 'field-overwrite',
- 'field-automatic_update'),
+ 'field-automatic_update', 'field-default_status'),
KML:new Array('field-source', 'field-source_file', 'field-default_name',
'field-filtr', 'field-zipped', 'field-origin',
'field-license', 'field-categories', 'field-overwrite',
- 'field-get_description', 'field-automatic_update'),
+ 'field-get_description', 'field-automatic_update',
+ 'field-default_status'),
SHP:new Array('field-source', 'field-source_file', 'field-default_name',
'field-zipped', 'field-origin', 'field-srid',
'field-license', 'field-categories', 'field-overwrite',
- 'field-automatic_update'),
+ 'field-automatic_update', 'field-default_status'),
RSS:new Array('field-source', 'field-default_name', 'field-origin',
'field-srid', 'field-license', 'field-categories',
'field-overwrite', 'field-get_description',
- 'field-automatic_update'),
+ 'field-automatic_update', 'field-default_status'),
CSV:new Array('field-source', 'field-source_file', 'field-default_name',
'field-origin', 'field-srid', 'field-license',
'field-categories', 'field-overwrite',
- 'field-get_description', 'field-automatic_update'),
+ 'field-get_description', 'field-automatic_update',
+ 'field-default_status'),
XSLT:new Array('field-source', 'field-source_file',
'field-source_file_alt', 'field-default_name',
'field-origin', 'field-srid', 'field-license',
'field-categories', 'field-overwrite',
'field-get_description', 'field-default_localisation',
- 'field-automatic_update'),
+ 'field-automatic_update', 'field-default_status'),
XXLT:new Array('field-source', 'field-source_file',
'field-source_file_alt', 'field-default_name',
'field-origin', 'field-srid', 'field-license',
'field-categories', 'field-overwrite',
'field-get_description', 'field-default_localisation',
- 'field-automatic_update')
+ 'field-automatic_update', 'field-default_status'),
+ JSON:new Array('field-source', 'field-source_file', 'field-default_name',
+ 'field-filtr', 'field-zipped', 'field-origin',
+ 'field-license', 'field-categories', 'field-overwrite',
+ 'field-get_description', 'field-automatic_update',
+ 'field-default_status', 'field-default_localisation')
}
var osm_map_initialized;
var edit_map_initialized;
@@ -63,13 +70,17 @@ django.jQuery(function($) {
osm_map_initialized = true;
}
}
- else if (importer_val == 'XSLT' || importer_val == 'XXLT'){
+ else if (importer_val == 'XSLT' || importer_val == 'XXLT'
+ || importer_val == 'JSON'){
$('#importerkeycategories_set-group').show();
$('#key_categories-group').show();
$('#importerkeycategories_set-group .form-row').show();
$('#key_categories-group .form-row').show();
$('.form-row.field-filtr').addClass('field-map');
$('#map_edit').show();
+ $('#map_edit_area').hide();
+ $('.help-osm').hide();
+ $('.input-osm').hide();
if (!edit_map_initialized){
init_map_edit();
edit_map_initialized = true;
@@ -118,10 +129,10 @@ django.jQuery(function($) {
value = $('input[name=id_filtr_type]:checked').val();
value += '[' + $("#id_filtr_tag").val() + ']';
value += '[bbox=';
- value += $('#upper_left_lon').val() + ',';
- value += $('#lower_right_lat').val() + ',';
- value += $('#lower_right_lon').val() + ',';
- value += $('#upper_left_lat').val();
+ value += Number($('#upper_left_lon').val()).toFixed(6) + ',';
+ value += Number($('#lower_right_lat').val()).toFixed(6) + ',';
+ value += Number($('#lower_right_lon').val()).toFixed(6) + ',';
+ value += Number($('#upper_left_lat').val()).toFixed(6);
value += ']';
$('#id_filtr').val(value);
return false;
diff --git a/chimere/static/chimere/js/jquery.chimere-ol.js b/chimere/static/chimere/js/jquery.chimere-ol.js
index 9346964..1599e1d 100644
--- a/chimere/static/chimere/js/jquery.chimere-ol.js
+++ b/chimere/static/chimere/js/jquery.chimere-ol.js
@@ -45,7 +45,6 @@ if (typeof(OpenLayers) != 'undefined'){
else
return v; };
})( jQuery );
-
(function ($) {
/*
* Chimere jQuery plugin
@@ -84,6 +83,7 @@ if (typeof(OpenLayers) != 'undefined'){
// Provide this function for overriding the getSubcategories default
get_subcategories_fx: null,
hide_popup_fx: null,
+ open_dialog_fx: null,
// if leave to false every click on the map hide the pop-up
explicit_popup_hide: false,
controls:null,
@@ -594,6 +594,7 @@ if (typeof(OpenLayers) != 'undefined'){
content += "</ul></div>";
$('#cluster_list').html(content);
$('#cluster_list').dialog('open');
+ $("#cluster_list").on("dialogclose", methods.cleanCluster);
settings.map.setCenter(
feature.geometry.getBounds().getCenterLonLat());
// register after the display
@@ -687,8 +688,16 @@ if (typeof(OpenLayers) != 'undefined'){
});
},
razMap: function() {
+ methods.hidePopup();
+ methods.uncheckCategories();
settings.layerMarkers.clearMarkers();
settings.layerVectors.removeAllFeatures();
+ if (settings.enable_clustering){
+ settings.layerCluster.removeAllFeatures();
+ settings.cluster_array = [];
+ settings.layerCluster.addFeatures(settings.cluster_array);
+ methods.cleanCluster();
+ }
},
/*
* Update the categories div in ajax
@@ -714,7 +723,7 @@ if (typeof(OpenLayers) != 'undefined'){
_init_categories();
_reCheckCategories();
if (settings.current_category) {
- // TODO : add a force mode
+ // TODO : add a force mode
// (in case the category is yet visible in HTML...)
methods.toggle_category();
}
@@ -774,7 +783,6 @@ if (typeof(OpenLayers) != 'undefined'){
} else {
par.removeClass('selected');
}
- methods.hidePopup(e);
methods.loadGeoObjects();
_toggle_categories($(this));
settings.permalink.updateLink();
@@ -782,6 +790,7 @@ if (typeof(OpenLayers) != 'undefined'){
$('#layer_cat_'+c_name).prop("checked",
this.checked);
}
+ methods.hidePopup(e);
});
$('#display_submited_check').bind("click", function () {
methods.loadGeoObjects();
@@ -796,8 +805,8 @@ if (typeof(OpenLayers) != 'undefined'){
var id = this.id.substr(this.id.lastIndexOf("_")+1);
helpers.zoom_to_subcategories([id]);
});
- $(".toggle_category").bind("click", function (e) {
- var item = $(this);
+ $(".toggle_category").parent().bind("click", function (e) {
+ var item = $(this).children('.toggle_category');
var id = item.attr('id').substr(item.attr('id').lastIndexOf("_")+1);
methods.toggle_category(id);
});
@@ -823,6 +832,18 @@ if (typeof(OpenLayers) != 'undefined'){
}
},
/*
+ *
+ */
+ uncheckCategories: function (){
+ $('#frm_categories .subcategories input:checkbox').each(function(index){
+ $(this).attr("checked", false);
+ $(this).removeAttr("checked", false);
+ });
+ $('#frm_categories .selected').each(function(index){
+ $(this).removeClass("selected");
+ });
+ },
+ /*
* Hide clusterized markers
*/
cleanCluster: function (){
@@ -1046,6 +1067,28 @@ if (typeof(OpenLayers) != 'undefined'){
cleanRoute: function(){
settings.layerVectors.removeAllFeatures();
},
+ // add json layer
+ addJSON: function(json_url){
+ var jsonStyle = new OpenLayers.Style({
+ 'strokeWidth':1,
+ 'fillColor':'#BBBBBB',
+ 'strokeColor':'#AAAAAA'
+ });
+
+ var jsonStyleMap = new OpenLayers.StyleMap({'default': jsonStyle});
+ settings.layerJson = new OpenLayers.Layer.Vector("GeoJSON", {
+ projection: EPSG_DISPLAY_PROJECTION,
+ strategies: [new OpenLayers.Strategy.Fixed()],
+ protocol: new OpenLayers.Protocol.HTTP({
+ url: json_url,
+ format: new OpenLayers.Format.GeoJSON()
+ }),
+ styleMap: jsonStyleMap
+ });
+ settings.map.addLayer(settings.layerJson);
+ settings.map.setLayerIndex(settings.layerJson, 0);
+ settings.layerJson.setOpacity(0.4);
+ },
// Put a route on the map
addRoute: function(route) {
var polyline = route.geometry;
@@ -1441,16 +1484,23 @@ if (typeof(OpenLayers) != 'undefined'){
helpers.zoom_to_area(options["area"]);
}
},
+ open_dialog: function(title, content){
+ if(settings.open_dialog_fx){
+ settings.open_dialog_fx(title, content);
+ } else {
+ $("#category_description").html(content).dialog();
+ $("#category_description").dialog("option", "title", title);
+ $('#category_description').dialog('open');
+ }
+ },
category_detail: function (category_id) {
/* show the detail of a category */
var uri = extra_url + "getDescriptionDetail/" + category_id;
$.ajax({url:uri,
- success: function (data) {
- $("#category_description").html(data).dialog();
- $("#category_description").dialog( "option", "title",
- $("#category_title").html());
- }
- });
+ success: function (data) {
+ methods.open_dialog($("#category_title").html(), data);
+ }
+ });
},
/*
* Load the subcategory description if available
@@ -1462,10 +1512,7 @@ if (typeof(OpenLayers) != 'undefined'){
dataType: "json",
success: function (data) {
if (!data.description){return}
- $('#category_description').html(data.description);
- $("#category_description").dialog("option", "title",
- data.name);
- $('#category_description').dialog('open');
+ methods.open_dialog(data.name, data.description);
},
error: function (data) {
// fail silently
diff --git a/chimere/tasks.py b/chimere/tasks.py
index 9c94f43..9eff7f5 100644
--- a/chimere/tasks.py
+++ b/chimere/tasks.py
@@ -60,19 +60,20 @@ else:
return task_exc
IMPORT_MESSAGES = {
- 'import_pending':[_(u"Import pending")],
- 'import_process':[_(u"Import processing")],
- 'import_done':[_(u"Import successfuly done"),
+ 'import_pending': [_(u"Import pending")],
+ 'import_process': [_(u"Import processing")],
+ 'import_done': [_(u"Import successfuly done"),
_(u" %(new)d new item(s), %(updated)d updated item(s)")],
- 'import_failed':[_(u"Import failed"), "%s"],
- 'import_cancel':[_(u"Import canceled")],
- 'export_pending':[_(u"Export pending")],
- 'export_process':[_(u"Export processing")],
- 'export_done':[_(u"Export successfuly done"),
+ 'import_failed': [_(u"Import failed"), "%s"],
+ 'import_cancel': [_(u"Import canceled")],
+ 'export_pending': [_(u"Export pending")],
+ 'export_process': [_(u"Export processing")],
+ 'export_done': [_(u"Export successfuly done"),
_(u" %(updated)d updated item(s)")],
- 'export_failed':[_(u"Export failed"), "%s"],
- 'export_cancel':[_(u"Export canceled")]
- }
+ 'export_failed': [_(u"Export failed"), "%s"],
+ 'export_cancel': [_(u"Export canceled")]
+}
+
@task()
def importing(importer_pk):
@@ -89,15 +90,16 @@ def importing(importer_pk):
new_item, updated_item, error = importer.manager.get()
importer.state = error + '\n' if error else ''
importer.state += unicode(IMPORT_MESSAGES['import_done'][0])
- importer.state += u" - " \
- + unicode(IMPORT_MESSAGES['import_done'][1]) % {'new':new_item,
- 'updated':updated_item}
+ importer.state += \
+ u" - " + unicode(IMPORT_MESSAGES['import_done'][1]) % {
+ 'new': new_item, 'updated': updated_item}
importer.state = importer.state
importer.save()
return True
+
@task()
-@single_instance_task(60*10)
+@single_instance_task(60 * 10)
def exporting(importer_pk, extra_args=[]):
try:
importer = Importer.objects.get(pk=importer_pk)
@@ -116,10 +118,11 @@ def exporting(importer_pk, extra_args=[]):
pass
if error:
importer.state = unicode(IMPORT_MESSAGES['export_failed'][0]) \
- + u" - " + unicode(IMPORT_MESSAGES['export_failed'][1]) % error
+ + u" - " + unicode(IMPORT_MESSAGES['export_failed'][1]) % error
importer.save()
return
importer.state = unicode(IMPORT_MESSAGES['export_done'][0]) + u" - " \
- + unicode(IMPORT_MESSAGES['export_done'][1]) % {'updated':updated_item}
+ + unicode(IMPORT_MESSAGES['export_done'][1]) % {
+ 'updated': updated_item}
importer.save()
return True
diff --git a/chimere/templates/chimere/blocks/map_menu.html b/chimere/templates/chimere/blocks/map_menu.html
index 38fb4a8..02f415a 100644
--- a/chimere/templates/chimere/blocks/map_menu.html
+++ b/chimere/templates/chimere/blocks/map_menu.html
@@ -1,7 +1,7 @@
{% load i18n %}
<div id='chimere_map_menu'>
<ul>
- {% if routing %}
+ {% if routing and not simple %}
<li id='map_menu_from' class='routing_item'>{% trans "From" context "routing" %}</li>
<li id='map_menu_step' class='routing_item'>{% trans "Add a step" context "routing" %}</li>
<li id='map_menu_to' class='routing_item'>{% trans "To" context "routing" %}</li>
diff --git a/chimere/templates/chimere/blocks/news.html b/chimere/templates/chimere/blocks/news.html
index 07c2bbb..0514081 100644
--- a/chimere/templates/chimere/blocks/news.html
+++ b/chimere/templates/chimere/blocks/news.html
@@ -22,7 +22,7 @@ $(function(){
<h3>{{news.title}} &ndash; {{ news.date }}</h3>
<p>{{news.content|safe}}</p>
{% else %}
- <h3>{{news.name}} &ndash; {{ news.start_date }}{% if news.end_date %} - {{ news.end_date }}{% endif %}</h3>
+ <h3>{{news.name}} &ndash; {{ news.start_date }}{% if news.end_date and news.end_date != news.start_date %} &ndash; {{ news.end_date }}{% endif %}</h3>
{% if news.default_pictures or news.default_pictures or news.default_multimedia_items%}
<div class='small-gallery'>
{% for picture in news.default_pictures %}
diff --git a/chimere/templates/chimere/category_directory.html b/chimere/templates/chimere/category_directory.html
new file mode 100644
index 0000000..7031c83
--- /dev/null
+++ b/chimere/templates/chimere/category_directory.html
@@ -0,0 +1,35 @@
+{% extends "chimere/base.html" %}
+{% load i18n chimere_tags %}
+{% load url from future %}
+{% block extra_head %}
+ {{ block.super }}
+ {{ form.media }}
+ {% head_jquery %}
+{% endblock %}
+{% block message_map %}{% endblock %}
+{% block message_edit%}{% endblock %}
+{% block content %}
+ {{ block.super }}
+ <div id="category-directory-content">
+ {% if not object_list.count %}
+ <p>{% trans "No category defined!" %}</p>
+ {% else %}
+ <ul id="category-directory" class="list-group">{% for object in object_list %}
+ {% ifchanged object.category %}
+ {% if forloop.counter0 %}
+ </ul>
+ </li>
+ {% endif %}
+ <li class='list-group-item' id='{{object.category|slugify}}'><p class='category-directory-category'>{{object.category}}</p>
+ <ul>
+ {% endifchanged %}
+ <li class='list-group-item'><span class='icon'><img src='{{MEDIA_URL}}{{object.icon.image}}'/></span><a href="{% url 'chimere:category-directory-detail' area_name object.slug %}">{{object.name}}</a></li>
+ {% endfor %}
+ </ul>
+ </li>
+ </ul>
+ {% endif %}
+ </div>
+{% endblock %}
+
+
diff --git a/chimere/templates/chimere/category_directory_detail.html b/chimere/templates/chimere/category_directory_detail.html
new file mode 100644
index 0000000..1b23b7e
--- /dev/null
+++ b/chimere/templates/chimere/category_directory_detail.html
@@ -0,0 +1,25 @@
+{% extends "chimere/base.html" %}
+{% load i18n chimere_tags %}
+{% load url from future %}
+{% block extra_head %}
+ {{ block.super }}
+ {{ form.media }}
+ {% head_jquery %}
+{% endblock %}
+{% block message_map %}{% endblock %}
+{% block message_edit%}{% endblock %}
+{% block content %}
+ {{ block.super }}
+ <ol class="breadcrumb">
+ <li><a href="{% url 'chimere:category-directory' area_name %}#{{category.category.name|slugify}}">{{category.category.name}}</a></li>
+ <li class="active">{{category.name}}</li>
+ </ol>
+ <ul id="category-directory" class="list-group">{% for marker in items %}
+ <li class='list-group-item' id='{{item.name|slugify}}'>
+ {% include "chimere/category_item_detail.html" %}
+ </li>
+ {% endfor %}
+ </ul>
+{% endblock %}
+
+
diff --git a/chimere/templates/chimere/category_item_detail.html b/chimere/templates/chimere/category_item_detail.html
new file mode 100644
index 0000000..3f90c6c
--- /dev/null
+++ b/chimere/templates/chimere/category_item_detail.html
@@ -0,0 +1,38 @@
+{% load i18n sanitize chimere_tags %}
+
+<h2>{{ marker.name }}</h2>
+<div class='detail_content'>
+ {% if marker.default_pictures or marker.default_pictures or marker.default_multimedia_items%}
+ <div class='small-gallery'>
+ {% for picture in marker.default_pictures %}
+ {% multimedia_render picture %}
+ {%endfor%}
+ {% for multimedia_item in marker.default_multimedia_items %}
+ {% multimedia_render multimedia_item %}
+ {%endfor%}
+ </div>
+ {%endif%}
+ <div>
+ {% if dated %}
+ <p class='detail_start_date'><label>{% trans "Date:" %}</label> <span>{{marker.start_date|date:"D d M Y"}}
+ {% if marker.end_date %} - {{marker.end_date|date:"D d M Y"}}</p>{% endif %}</span>
+ {% endif %}
+ {% if marker.description %}
+ <p class='description'>{{ marker.description|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>
+ {% endif %}
+ {% for property in marker.getProperties %}
+ <p class='{{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 %}
+ {% share_bar marker.name %}
+ <a href="{% get_tinyfied_url marker area_name %}">{% trans "See on the map" %}</a>
+ <p class='detail_amendment'><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 an amendment" %}
+ </a>
+ {% 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%}
+ </div>
+</div>
diff --git a/chimere/templates/search/indexes/chimere/marker_text.txt b/chimere/templates/search/indexes/chimere/marker_text.txt
index 7c7929d..d089654 100644
--- a/chimere/templates/search/indexes/chimere/marker_text.txt
+++ b/chimere/templates/search/indexes/chimere/marker_text.txt
@@ -2,3 +2,5 @@
{{object.name}}
{{object.description|safe|striptags|unescape}}
{{object.keywords}}
+{% for category in object.categories.all %}{{category.keywords}}
+{% endfor %}
diff --git a/chimere/templates/search/indexes/chimere/route_text.txt b/chimere/templates/search/indexes/chimere/route_text.txt
index 5e612cd..d67c88b 100644
--- a/chimere/templates/search/indexes/chimere/route_text.txt
+++ b/chimere/templates/search/indexes/chimere/route_text.txt
@@ -1,2 +1,4 @@
{{object.name}}
{{object.keywords}}
+{% for category in object.categories.all %}{{category.keywords}}
+{% endfor %}
diff --git a/chimere/templates/search/search.html b/chimere/templates/search/search.html
index 95d3937..ab3e61e 100644
--- a/chimere/templates/search/search.html
+++ b/chimere/templates/search/search.html
@@ -30,7 +30,7 @@ var end_do_you_mean = "{% trans '?' %}";
{% else %}
<form id='search-form' class='autocomplete-me'>
<input type="text" id="id_q" name="q" autocomplete="off"/>
- <button name='haystack-search' id='haystack-search' type='button' disabled='disabled' class="btn btn-default"><span class='action-label'>{% trans "Search" %} </span><span class="glyphicon glyphicon-search"></span></button>
+ <button name='haystack-search' id='haystack-search' type='button' class="btn btn-default"><span class='action-label'>{% trans "Search" %} </span><span class="glyphicon glyphicon-search"></span></button>
</form>
<div id='spelling'></div>
<div id='search-result'></div>
@@ -42,10 +42,11 @@ $(function(){
$("#main-map").chimere("razMap");
haystack_search(evt);
});
+ {% if autocomplete %}
window.autocomplete = new Autocomplete({
form_selector: '.autocomplete-me'
});
- window.autocomplete.setup();
+ window.autocomplete.setup();{% endif %}
});
</script>
{% endif %}
diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py
index e3b439f..34cb4b2 100644
--- a/chimere/templatetags/chimere_tags.py
+++ b/chimere/templatetags/chimere_tags.py
@@ -57,13 +57,13 @@ def get_news(map=None):
Q(end_date__gte=today)|
(Q(end_date__isnull=True) & Q(start_date__gte=today)))
- if not'CHIMERE_ALL_DATED_ARE_FRONT' in dir(settings)\
+ if not 'CHIMERE_ALL_DATED_ARE_FRONT' in dir(settings)\
or not settings.CHIMERE_ALL_DATED_ARE_FRONT:
q = q.filter(is_front_page=True)
if map:
q = q.filter(map.getIncludeMarker())
news += list(q)
- news.sort(key=lambda x:x.date, reverse=True)
+ news.sort(key=lambda x:x.date)
return news
@register.inclusion_tag('chimere/blocks/welcome.html', takes_context=True)
@@ -182,7 +182,8 @@ def head_form():
@register.inclusion_tag('chimere/blocks/map_menu.html', takes_context=True)
def map_menu(context):
context_data = {'routing': settings.CHIMERE_ENABLE_ROUTING \
- if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') else False}
+ if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') else False,
+ 'simple':context.get('simple')}
return context_data
@register.inclusion_tag('chimere/blocks/routing.html', takes_context=True)
@@ -330,9 +331,10 @@ def get_tinyfied_url(marker, map_name=''):
@register.inclusion_tag('chimere/blocks/share_bar.html',
takes_context=True)
-def share_bar(context, name='', email_only=False):
+def share_bar(context, name='', email_only=False, rss=True):
context['STATIC_URL'] = settings.STATIC_URL
context['name'] = name
+ context['rss'] = rss
context['email_only'] = email_only
context['share_networks'] = [(defaultfilters.slugify(name), url, icon)
for name, url, icon in settings.CHIMERE_SHARE_NETWORKS]
diff --git a/chimere/tests.py b/chimere/tests.py
index e06b073..0e500f1 100644
--- a/chimere/tests.py
+++ b/chimere/tests.py
@@ -365,6 +365,22 @@ class XmlXsltImporterTest(TestCase, ImporterTest):
importer1.categories.add(subcategories[0])
self.marker_importers = [(importer1, 10),]
+
+class JsonImporterTest(TestCase, ImporterTest):
+ def setUp(self):
+ subcategories = subcategory_setup()
+ jsonfile = File(open(test_dir_path + 'tests/test.json'))
+ importer1 = Importer.objects.create(
+ importer_type='JSON',
+ source_file=jsonfile,
+ filtr='{"title":"name", "id_agenda":"id", '
+ '"content":"description", "date_start_evt":"start_date", '
+ '"date_end_evt":"end_date"}',
+ default_localisation='SRID=4326;POINT(-4.5 48.4)',)
+ importer1.categories.add(subcategories[0])
+ self.marker_importers = [(importer1, 5), ]
+
+
class FeedsTest(TestCase):
def setUp(self):
self.areas = areas_setup()
diff --git a/chimere/tests/test.json b/chimere/tests/test.json
new file mode 100644
index 0000000..6c9fa0c
--- /dev/null
+++ b/chimere/tests/test.json
@@ -0,0 +1,57 @@
+
+[
+{"id_agenda":"1759",
+"title":"Exposition municipale d'Orsay : inscription en ligne",
+"content":"TEST
+TESTST",
+"date_start_evt":"2015-08-20",
+"date_end_evt":"2015-12-14",
+"date_start_display":"2015-10-20",
+"date_end_display":"2015-12-14",
+"date_add":"2015-10-20 10:37:52",
+"date_update":"2015-10-27 14:56:18"
+},
+{"id_agenda":"179",
+"title":"Exposition municipale d'Orsay : inscription en ligne",
+"content":"TEST
+TESTST",
+"date_start_evt":"2015-08-20",
+"date_end_evt":"2015-12-14",
+"date_start_display":"2015-10-20",
+"date_end_display":"2015-12-14",
+"date_add":"2015-10-20 10:37:52",
+"date_update":"2015-10-27 14:56:18"
+},
+{"id_agenda":"19",
+"title":"Exposition municipale d'Orsay : inscription en ligne",
+"content":"TEST
+TESTST",
+"date_start_evt":"2015-08-20",
+"date_end_evt":"2015-12-14",
+"date_start_display":"2015-10-20",
+"date_end_display":"2015-12-14",
+"date_add":"2015-10-20 10:37:52",
+"date_update":"2015-10-27 14:56:18"
+},
+{"id_agenda":"17",
+"title":"Exposition municipale d'Orsay : inscription en ligne",
+"content":"TEST
+TESTST",
+"date_start_evt":"2015-08-20",
+"date_end_evt":"2015-12-14",
+"date_start_display":"2015-10-20",
+"date_end_display":"2015-12-14",
+"date_add":"2015-10-20 10:37:52",
+"date_update":"2015-10-27 14:56:18"
+},
+{"id_agenda":"59",
+"title":"Exposition municipale d'Orsay : inscription en ligne",
+"content":"TEST
+TESTST",
+"date_start_evt":"2015-08-20",
+"date_end_evt":"2015-12-14",
+"date_start_display":"2015-10-20",
+"date_end_display":"2015-12-14",
+"date_add":"2015-10-20 10:37:52",
+"date_update":"2015-10-27 14:56:18"
+}]
diff --git a/chimere/urls.py b/chimere/urls.py
index 256c08f..b9ec380 100644
--- a/chimere/urls.py
+++ b/chimere/urls.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2008-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2008-2014 É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
@@ -23,33 +23,34 @@ from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured
admin.autodiscover()
-from chimere.models import Map
+from chimere.views import CategoryDirectoryView, CategoryView
from chimere.feeds import LatestPOIsByCategory, LatestPOIsBySubCategory, \
LatestPOIs, LatestPOIsByZone, LatestPOIsByZoneID
+
def i18n_javascript(request):
return admin.site.i18n_javascript(request)
urlpatterns = patterns('chimere.views',
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?simple$', 'index', {'simple':True},
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?simple$', 'index', {'simple':True},
name="simple_index")
)
if settings.CHIMERE_FEEDS:
urlpatterns += patterns('',
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds$', 'chimere.views.rss',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds$', 'chimere.views.rss',
name='feeds-form'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds/category/(?P<category_id>\d+)$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/category/(?P<category_id>\d+)$',
LatestPOIsByCategory(), name='feeds-cat'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds/subcategory/(?P<category_id>\d+)$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/subcategory/(?P<category_id>\d+)$',
LatestPOIsBySubCategory(), name='feeds-subcat'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds/global/$', LatestPOIs(),
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/global/$', LatestPOIs(),
name='feeds-global'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds/area/(?P<area>[0-9-_.]+)$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/area/(?P<area>[0-9-_.]+)$',
LatestPOIsByZone(), name='feeds-area'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?feeds/mapid/(?P<map_id>\d+)$',
- LatestPOIsByZoneID(), name='feeds-mapid'),
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/areaid/(?P<area_id>\d+)$',
+ LatestPOIsByZoneID(), name='feeds-areaid'),
)
if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') \
@@ -59,7 +60,7 @@ if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') \
raise ImproperlyConfigured(u"CHIMERE_ROUTING_TRANSPORT must be set in"\
u" settings if you enable routing")
urlpatterns += patterns('chimere.views',
- url(r'^(?P<map_name>[a-zA-Z0-9_-]*/)?route/'\
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?route/'\
r'(?P<transport>(%s))/((?P<speed>[0-9][0-9]*)/)?'
r'(?P<lon1>[-]?[0-9]+[.]?[0-9]*)_(?P<lat1>[-]?[0-9]+[.]?[0-9]*)_'\
r'(?P<lonlat_steps>([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\
@@ -85,45 +86,46 @@ if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \
#urlpatterns += [url(r'^search/', include('haystack.urls')),]
urlpatterns += patterns('chimere.views',
- url(r'^logout/?$', 'logout_view', name="logout"),
url(r'^charte/?$', 'charte', name="charte"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?contact/?$', 'contactus',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?contact/?$', 'contactus',
name="contact"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?edit/$', 'edit',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/$', 'edit',
name="edit"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?edit/(?P<item_id>\w+)/(?P<submited>\w+)?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/(?P<item_id>\w+)/(?P<submited>\w+)?$',
'edit', name="edit-item"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?edit-route/$', 'editRoute',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit-route/$', 'editRoute',
name="editroute"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?edit-route/(?P<item_id>\w+)/(?P<submited>\w+)?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit-route/(?P<item_id>\w+)/(?P<submited>\w+)?$',
'editRoute', name="editroute-item"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getDetail/(?P<marker_id>\d+)/?$', 'getDetail',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDetail/(?P<marker_id>\d+)/?$', 'getDetail',
name="get_detail"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getDescriptionDetail/?(?P<category_id>\d+)/?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDescriptionDetail/?(?P<category_id>\d+)/?$',
'getDescriptionDetail', name="get_description_detail"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getGeoObjects/'\
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getGeoObjects/'\
r'(?P<category_ids>[a-zA-Z0-9_-]+)(/(?P<status>\w+))?$', 'getGeoObjects',
name="getgeoobjects"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getAvailableCategories/$',
- 'get_available_categories', name="get_categories"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?get-marker/'\
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?get-marker/'\
r'(?P<pk>[0-9]+)$', 'getMarker', name="get-marker"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getAllCategories/$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAvailableCategories/$',
+ 'get_available_categories', name="get_categories"),
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAllCategories/$',
'get_all_categories', name="get_all_categories"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?getCategory/(?P<category_id>\d+)/?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getCategory/(?P<category_id>\d+)/?$',
'getCategory', name="get_category"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]*/)?get-share-url/(?P<network>\w+)?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?get-share-url/(?P<network>\w+)?$',
'getShareUrl', name="get-share-url"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]*/)?ty/(?P<tiny_urn>\w+)$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?ty/(?P<tiny_urn>\w+)$',
'redirectFromTinyURN', name="tiny"),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?upload_file/((?P<category_id>\w+)/)?$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?upload_file/((?P<category_id>\w+)/)?$',
'uploadFile', name='upload_file'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?process_route_file/(?P<file_id>\d+)/$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?process_route_file/(?P<file_id>\d+)/$',
'processRouteFile', name='process_route_file'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?dyn/(?P<page_id>\w+)/$',
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?dyn/(?P<page_id>\w+)/$',
'extraPage', name='extra_page'),
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+/)?json/(?P<app_name>[a-zA-Z0-9_-]+)/(?P<filename>[a-zA-Z0-9_-]+).json$', 'get_json',
- name='get-json'),
+ url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/$',
+ CategoryDirectoryView.as_view(), name='category-directory'),
+ url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/(?P<category_slug>[a-zA-Z0-9_-]+)$',
+ CategoryView.as_view(), name='category-directory-detail'),
# At the end, because it catches large
- url(r'^(?P<map_name>[a-zA-Z0-9_-]+)?', 'index', name="index"),
+ url(r'^(?P<area_name>[a-zA-Z0-9_-]+)?', 'index', name="index"),
)
diff --git a/chimere/utils.py b/chimere/utils.py
index 790fd56..8066255 100644
--- a/chimere/utils.py
+++ b/chimere/utils.py
@@ -22,14 +22,14 @@ Utilitaries
"""
import csv
+import collections
import datetime
import feedparser
-import simplejson as json
+import json
import os
import re
import StringIO
import tempfile
-from urllib import urlencode
import urllib2
import unicodedata
import zipfile
@@ -47,26 +47,30 @@ from django.utils.translation import ugettext_lazy as _
from chimere import get_version
from external_utils import OsmApi
+
def unicode_normalize(string):
if type(string) == str:
string = unicode(string.decode('utf-8'))
return ''.join(
(c for c in unicodedata.normalize('NFD', string)
- if unicodedata.category(c) != 'Mn'))
+ if unicodedata.category(c) != 'Mn'))
+
class ImportManager(object):
u"""
Generic class for specific importers
"""
default_source = None
+
def __init__(self, importer_instance):
self.importer_instance = importer_instance
if self.importer_instance.default_name:
self.default_name = self.importer_instance.default_name
else:
- self.default_name = " - ".join([cat.name
+ self.default_name = " - ".join([
+ cat.name
for cat in self.importer_instance.categories.order_by(
- 'name').all()])
+ 'name').all()])
def get(self):
raise NotImplementedError
@@ -85,8 +89,8 @@ class ImportManager(object):
item = None
if import_key or pk:
dct_import = {
- 'import_key__icontains':'%s:%s;' % (key, import_key),
- 'import_source':self.importer_instance.source}
+ 'import_key__icontains': '%s:%s;' % (key, import_key),
+ 'import_source': self.importer_instance.source}
ref_item = cls.objects.filter(**dct_import)
try:
item = None
@@ -102,7 +106,7 @@ class ImportManager(object):
return ref_item, None, None
if not self.importer_instance.overwrite \
and ref_item.modified_since_import:
- dct_import['ref_item'] = ref_item
+ return ref_item, None, None
else:
item = ref_item
for k in values:
@@ -123,16 +127,17 @@ class ImportManager(object):
if not self.importer_instance.get_description and \
self.importer_instance.default_description:
values['description'] = \
- self.importer_instance.default_description
+ self.importer_instance.default_description
values.update({
- 'import_source':self.importer_instance.source})
- values['status'] = 'I' \
- if not self.importer_instance.automatic_update else 'A'
+ 'import_source': self.importer_instance.source})
+ values['status'] = self.importer_instance.default_status
if not self.importer_instance.associate_marker_to_way\
- and cls.__name__ == 'Route':
+ and cls.__name__ == 'Route':
values['has_associated_marker'] = False
try:
item = cls.objects.create(**values)
+ item.modified_since_import = False
+ item.save()
except TypeError:
# error on data source
return None, False, False
@@ -159,8 +164,8 @@ class ImportManager(object):
current_file_name = None
for name in namelist:
if name.endswith(suffix) \
- or name.endswith(suffix.lower()) \
- or name.endswith(suffix.upper()):
+ or name.endswith(suffix.lower()) \
+ or name.endswith(suffix.upper()):
current_file_name = name
filenames.append(current_file_name)
files = []
@@ -181,7 +186,7 @@ class ImportManager(object):
if not hasattr(source, 'read'):
if not source:
source = self.importer_instance.source \
- if self.importer_instance.source else self.default_source
+ if self.importer_instance.source else self.default_source
try:
url = source
if extra_url:
@@ -208,6 +213,7 @@ class ImportManager(object):
source = files[0] if len(suffixes) == 1 else files
return (source, None)
+
class KMLManager(ImportManager):
u"""
KML importer
@@ -216,6 +222,7 @@ class KMLManager(ImportManager):
"""
XPATH = '//kml:Folder/kml:name[text()="%s"]/../kml:Placemark'
DEFAULT_XPATH = '//kml:Placemark'
+
def __init__(self, importer_instance, ns=''):
super(KMLManager, self).__init__(importer_instance)
self.ns = ns
@@ -250,9 +257,9 @@ class KMLManager(ImportManager):
if not self.ns:
self.ns = tree.getroot().nsmap[None]
xpath = self.XPATH % self.importer_instance.filtr \
- if self.importer_instance.filtr else self.DEFAULT_XPATH
+ if self.importer_instance.filtr else self.DEFAULT_XPATH
for placemark in tree.xpath(xpath,
- namespaces={'kml':self.ns}):
+ namespaces={'kml': self.ns}):
name, point, line = None, None, None
pl_id = placemark.attrib.get('id')
pl_key = 'kml-%d' % self.importer_instance.pk
@@ -280,10 +287,10 @@ class KMLManager(ImportManager):
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}
+ dct = {'description': description,
+ 'name': name,
+ 'origin': self.importer_instance.origin,
+ 'license': self.importer_instance.license}
if point:
dct['point'] = point
cls = Marker
@@ -293,7 +300,7 @@ class KMLManager(ImportManager):
cls = Route
if cls:
item, updated, created = self.create_or_update_item(
- cls, dct, pl_id, key=pl_key)
+ cls, dct, pl_id, key=pl_key)
if updated:
updated_item += 1
if created:
@@ -302,15 +309,17 @@ class KMLManager(ImportManager):
@classmethod
def export(cls, queryset):
- dct = {'name':settings.PROJECT_NAME,
- 'description':unicode(datetime.date.today()),
- 'locations':queryset.all()
+ dct = {
+ 'name': settings.PROJECT_NAME,
+ 'description': unicode(datetime.date.today()),
+ 'locations': queryset.all()
}
- filename = unicode_normalize(settings.PROJECT_NAME + dct['description']\
+ filename = unicode_normalize(settings.PROJECT_NAME + dct['description']
+ '.kml')
result = render_to_response('chimere/export.kml', dct)
return filename, result
+
class ShapefileManager(ImportManager):
u"""
Shapefile importer
@@ -352,7 +361,7 @@ class ShapefileManager(ImportManager):
srid = settings.CHIMERE_EPSG_DISPLAY_PROJECTION
msg = _(u"SRID cannot be guessed. The default SRID (%s) has "
u"been used.") % srid
- #If imported items are not well located "
+ # If imported items are not well located "
# u"ask your data provider for the SRID to use.") % srid
shapefilename = tmpdir + os.sep + sources[0]
ds = DataSource(shapefilename)
@@ -375,7 +384,7 @@ class ShapefileManager(ImportManager):
u"is not managed by Chimère.") % lyr.geom_type)
geom_key = 'point' if lyr.geom_type == 'Point' else 'route'
geom_cls = Marker if lyr.geom_type == 'Point' else Route
- indexes = []
+ # indexes = []
for idx, feat in enumerate(lyr):
name = unicode(idx)
if lbl_name:
@@ -385,7 +394,7 @@ class ShapefileManager(ImportManager):
except UnicodeDecodeError:
try:
name = unicode(
- name.decode(settings.CHIMERE_SHAPEFILE_ENCODING))
+ name.decode(settings.CHIMERE_SHAPEFILE_ENCODING))
except:
continue
try:
@@ -394,15 +403,17 @@ class ShapefileManager(ImportManager):
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 ''
+ 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,
- 'origin':self.importer_instance.origin,
- 'license':self.importer_instance.license
- }
+ dct = {
+ geom_key: 'SRID=%s;%s' % (srid, geom),
+ '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)
+ geom_cls, dct, import_key)
if updated:
updated_item += 1
if created:
@@ -427,8 +438,9 @@ class ShapefileManager(ImportManager):
tmp_name = tmp.name
field_names = [field.name for field in queryset.model._meta.fields]
- geo_field = getattr(queryset.model,
- 'point' if 'point' in field_names else 'route')._field
+ geo_field = getattr(
+ queryset.model,
+ 'point' if 'point' in field_names else 'route')._field
dr = ogr.GetDriverByName('ESRI Shapefile')
ds = dr.CreateDataSource(tmp_name)
@@ -454,7 +466,7 @@ class ShapefileManager(ImportManager):
feat = ogr.Feature(feature_def)
feat.SetField('name', str(unicode_normalize(item.name)[:80]))
feat.SetField('category',
- str(unicode_normalize(category.name)[:80]))
+ str(unicode_normalize(category.name)[:80]))
geom = getattr(item, geo_field.name)
if not geom:
@@ -480,6 +492,7 @@ class ShapefileManager(ImportManager):
buff.close()
return filename, zip_stream
+
class CSVManager(ImportManager):
u"""
CSV importer
@@ -490,9 +503,8 @@ class CSVManager(ImportManager):
# (label, getter, setter)
COLS = [("Id", 'pk', 'pk'), (_(u"Name"), 'name', 'name'),
- (_(u"Categories"), lambda obj:", ".join(
- [c.name for c in obj.categories.all()]),
- set_categories),
+ (_(u"Categories"), lambda obj: ", ".join(
+ [c.name for c in obj.categories.all()]), set_categories),
(_(u"State"), 'status', lambda x: x),
(_(u"Description"), 'description', 'description'),
(_(u"Localisation"), 'geometry', 'geometry')]
@@ -512,40 +524,32 @@ class CSVManager(ImportManager):
if msg:
return (0, 0, msg)
reader = csv.reader(source, delimiter=';', quotechar='"')
- prop_cols, nominatim_fields = [], {}
- reverse_nominatim_dct = dict((v, k)
- for k, v in settings.CHIMERE_NOMINATIM_FIELDS.iteritems())
- nominatim_default_query = settings.CHIMERE_NOMINATIM_FIELDS
- for idx, pm in enumerate(Marker.all_properties()):
+ prop_cols = []
+ for pm in Marker.all_properties():
prop_cols.append((pm.name, pm.getAttrName(),
- pm.getAttrName()+'_set'))
- if settings.CHIMERE_NOMINATIM_FIELDS and \
- pm.slug in reverse_nominatim_dct:
- nominatim_fields[idx+len(self.COLS)] = \
- reverse_nominatim_dct[pm.slug]
- nominatim_default_query.pop(reverse_nominatim_dct[pm.slug])
+ pm.getAttrName() + '_set'))
cols = list(self.COLS) + prop_cols
- datas = []
+ # datas = []
for idx, row in enumerate(reader):
- if not idx: # first row
+ if not idx: # first row
try:
assert(len(row) >= len(cols))
except AssertionError:
- return (0, 0, _(u"Invalid CSV format - not enough columns "
- u"check a reference CSV file"))
+ 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]
+ # pk, name, cats, state = row[0], row[1], row[2], row[3]
+ pk, name = row[0], row[1]
geom = row[5]
description = ''
if self.importer_instance.get_description:
description = row[4]
COL_INDEX = 6
- dct = {'description':description,
- 'name':name,
- 'origin':self.importer_instance.origin,
- 'license':self.importer_instance.license}
+ dct = {'description': description,
+ 'name': name,
+ 'origin': self.importer_instance.origin,
+ 'license': self.importer_instance.license}
cls = None
if 'POINT' in geom:
cls = Marker
@@ -553,27 +557,11 @@ class CSVManager(ImportManager):
elif 'LINE' in geom:
cls = Route
dct['route'] = geom
- elif settings.CHIMERE_NOMINATIM_FIELDS:
- nominatim_query = settings.NOMINATIM_URL + "?"
- nominatim_keys = nominatim_default_query.copy()
- nominatim_keys['format'] = 'json'
- for idx in nominatim_fields:
- nominatim_keys[nominatim_fields[idx]] = row[idx]
- nominatim_query += urlencode(nominatim_keys)
- remotehandle = urllib2.urlopen(nominatim_query)
- result = StringIO.StringIO(remotehandle.read())
- remotehandle.close()
- result = json.load(result)
- if not result:
- continue
- result = result[0]
- cls = Marker
- dct['point'] = "POINT(%s %s)" % (result['lon'], result['lat'])
else:
continue
import_key = pk if pk else name.decode('utf-8')
- item, updated, created = self.create_or_update_item(cls, dct,
- import_key, pk=pk)
+ item, updated, created = self.create_or_update_item(
+ cls, dct, import_key, pk=pk)
if updated:
updated_item += 1
if created:
@@ -581,19 +569,17 @@ class CSVManager(ImportManager):
for idx, col in enumerate(cols[COL_INDEX:]):
name, getter, setter_val = col
setter = getattr(item, setter_val)
- val = row[idx+COL_INDEX]
+ val = row[idx + COL_INDEX]
setter(item, val)
return (new_item, updated_item, msg)
@classmethod
- def export(cls, queryset, cols=[]):
- dct = {'description':unicode(datetime.date.today()), 'data':[]}
- cls_name = queryset.model.__name__.lower()
- if not cols:
- cols = list(cls.COLS)
- if hasattr(queryset.model, 'all_properties'):
- for pm in queryset.model.all_properties():
- cols.append((pm.name, pm.getAttrName(), pm.getAttrName()+'_set'))
+ def export(cls, queryset):
+ dct = {'description': unicode(datetime.date.today()), 'data': []}
+ # cls_name = queryset.model.__name__.lower()
+ cols = list(cls.COLS)
+ for pm in queryset.model.all_properties():
+ 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():
@@ -602,16 +588,14 @@ class CSVManager(ImportManager):
if callable(attr):
data.append(attr(item))
else:
- v = getattr(item, attr)
- if v == None:
- v = ''
- data.append(v)
+ data.append(getattr(item, attr))
dct['data'].append(data)
- filename = unicode_normalize(settings.PROJECT_NAME + dct['description']\
+ filename = unicode_normalize(settings.PROJECT_NAME + dct['description']
+ '.csv')
result = render_to_response('chimere/export.csv', dct)
return filename, result
+
class GeoRSSManager(ImportManager):
u"""
RSS importer.
@@ -627,19 +611,19 @@ class GeoRSSManager(ImportManager):
- number of item updated ;
- error detail on error
"""
- from models import Marker
+ from models import Marker, Route
new_item, updated_item, msg = 0, 0, ''
feed = feedparser.parse(self.importer_instance.source)
- if feed['bozo'] and not isinstance(feed['bozo_exception'],
- feedparser.CharacterEncodingOverride):
+ if feed['bozo'] and not isinstance(
+ feed['bozo_exception'], feedparser.CharacterEncodingOverride):
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 \
and not ("geo_lat" in item and "geo_long" in item):
continue
cls = None
- dct = {'origin':self.importer_instance.origin,
- 'license':self.importer_instance.license}
+ dct = {'origin': self.importer_instance.origin,
+ 'license': self.importer_instance.license}
if 'georss_point' in item or "geo_lat" in item:
cls = Marker
if 'georss_point' in item:
@@ -661,11 +645,11 @@ class GeoRSSManager(ImportManager):
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]))
+ 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)
+ ",".join(reordered_points)
dct['name'] = item['title']
pl_id = item['id'] if 'id' in item else item['title']
@@ -676,10 +660,101 @@ class GeoRSSManager(ImportManager):
new_item += 1
return (new_item, updated_item, msg)
+
+class JsonManager(ImportManager):
+ u"""
+ Json importer.
+ This manager only gets and do not produce Json feed
+ """
+
+ def get(self):
+ u"""
+ Get data from a json 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, ''
+ source, msg = self.get_source_file(['.json'])
+ if msg:
+ return (0, 0, msg)
+
+ vals = source.read().replace('\n', ' ')
+ try:
+ values = json.JSONDecoder(
+ object_pairs_hook=collections.OrderedDict).decode(vals)
+ except ValueError as e:
+ return (new_item, updated_item,
+ _(u"JSON file is not well formed: " + e.message))
+ # configuration in filtr
+ try:
+ filtr = json.JSONDecoder().decode(self.importer_instance.filtr)
+ except ValueError:
+ return (
+ new_item, updated_item,
+ _(u"Bad configuration: filter field must be a valid "
+ u"JSON string"))
+
+ vls = filtr.values()
+ for k in ('name', 'id', 'description'):
+ if k not in vls:
+ return (
+ new_item, updated_item,
+ _(u"A key must be associated to \"%s\" in the "
+ u"filter.") % k)
+
+ default_dct = {'origin': self.importer_instance.origin,
+ 'license': self.importer_instance.license}
+ if 'prefix_name' in filtr:
+ default_dct['name'] = filtr.pop('prefix_name')
+ if 'prefix_description' in filtr:
+ default_dct['description'] = filtr.pop('prefix_description')
+ if self.importer_instance.default_localisation:
+ default_dct['point'] = self.importer_instance.default_localisation
+
+ for item in values:
+ dct = default_dct.copy()
+ for k in filtr:
+ if k in item and item[k]:
+ if filtr[k] not in dct:
+ dct[filtr[k]] = ""
+ else:
+ if filtr[k] == 'description':
+ dct[filtr[k]] += "<br/>"
+ else:
+ dct[filtr[k]] += " "
+ dct[filtr[k]] += item[k]
+ if 'point' in item:
+ x, y = item['point'].split(",")
+ dct['point'] = 'SRID=4326;POINT(%s %s)' % (x, y)
+ elif 'lat' in item and item['lat'] \
+ and 'lon' in item and item['lon']:
+ dct['point'] = 'SRID=4326;POINT(%s %s)' % (item['lon'],
+ item['lat'])
+ elif 'x' in item and item['x'] \
+ and 'y' in item and item['y']:
+ dct['point'] = 'SRID=4326;POINT(%s %s)' % (item['x'],
+ item['y'])
+ if not dct['point']:
+ continue
+ cls = Marker
+ pl_id = (dct.pop('id') if 'id' in dct else dct['name']) \
+ + "-" + unicode(self.importer_instance.pk)
+ 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
+
class OSMManager(ImportManager):
u"""
OSM importer/exporter
@@ -697,8 +772,8 @@ class OSMManager(ImportManager):
- updated items;
- error detail on error.
"""
- source, msg = self.get_source_file(['.osm'],
- extra_url=self.importer_instance.filtr)
+ source, msg = self.get_source_file(
+ ['.osm'], extra_url=self.importer_instance.filtr)
if not source:
return (0, 0, msg)
@@ -711,8 +786,8 @@ class OSMManager(ImportManager):
return 0, 0, _(u"Nothing to import")
def import_ways(self, tree):
- from chimere.models import Marker, Route
- msg, items, new_item, updated_item = "", [], 0 , 0
+ from chimere.models import Route
+ msg, items, new_item, updated_item = "", [], 0, 0
nodes = {}
for node in tree.xpath('//node'):
node_id = node.attrib.get('id')
@@ -734,17 +809,17 @@ class OSMManager(ImportManager):
points.append(item.get('ref'))
if not points:
continue
- wkt = 'SRID=4326;LINESTRING(%s)' % ",".join([nodes[point_id]
- 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}
+ wkt = 'SRID=4326;LINESTRING(%s)' % ",".join(
+ [nodes[point_id] 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)
+ Route, dct, node_id, version)
if updated:
updated_item += 1
if created:
@@ -754,7 +829,7 @@ class OSMManager(ImportManager):
def import_nodes(self, tree):
from chimere.models import Marker
- msg, items, new_item, updated_item = "", [], 0 , 0
+ msg, items, new_item, updated_item = "", [], 0, 0
for node in tree.xpath('//node'):
name = None
node_id = node.attrib.get('id')
@@ -767,15 +842,15 @@ class OSMManager(ImportManager):
name = item.attrib.get('v')
point = 'SRID=4326;POINT(%s %s)' % (node.get('lon'),
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}
+ 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)
+ Marker, dct, node_id, version)
if updated:
updated_item += 1
if created:
@@ -810,8 +885,8 @@ class OSMManager(ImportManager):
username = username.encode('latin1')
password = password.encode('latin1')
api = OsmApi.OsmApi(api=api, username=username, password=password)
- api.ChangesetCreate({u"comment": u"Import from Chimère %s" % \
- get_version()})
+ api.ChangesetCreate({u"comment": u"Import from Chimère %s" %
+ get_version()})
hooks = RE_HOOK.findall(self.importer_instance.filtr)
if not hooks:
hooks = RE_HOOK.findall(self.importer_instance.source)
@@ -825,28 +900,31 @@ class OSMManager(ImportManager):
continue
if key == 'bbox':
x1, y1, x2, y2 = [float(val) for val in value.split(',')]
- bbox = GEOSGeometry(
+ bbox = GEOSGeometry(
'POLYGON((%f %f,%f %f,%f %f,%f %f,%f %f))' % (
- x1, y1, x2, y1, x2, y2, x1, y2, x1, y1), srid=4326)
+ x1, y1, x2, y1, x2, y2, x1, y2, x1, y1), srid=4326)
continue
tags[key] = value
if not tags:
return 0, _(u"No non ambigious tag is defined in the XAPI request")
if not bbox:
- return 0, _(u"No bounding box is defined in the XAPI request."\
- u"If you are sure to manage the entire planet set the bounding box"\
- u" to -180,-90,180,90")
- default_dct = {'tag':tags,
- 'import_source':self.importer_instance.source}
+ return 0, _(
+ u"No bounding box is defined in the XAPI request."
+ u"If you are sure to manage the entire planet set the "
+ u"bounding box to -180,-90,180,90")
+ default_dct = {'tag': tags,
+ 'import_source': self.importer_instance.source}
idx = -1
- for idx, item in enumerate(Marker.objects.filter(status='A',
- point__contained=bbox,
- categories=self.importer_instance.categories.all(),
- not_for_osm=False, modified_since_import=True,
- route=None).all()):
+ for idx, item in enumerate(
+ Marker.objects.filter(
+ status='A',
+ point__contained=bbox,
+ categories=self.importer_instance.categories.all(),
+ not_for_osm=False, modified_since_import=True,
+ route=None).all()):
dct = default_dct.copy()
- dct.update({'lon':item.point.x,
- 'lat':item.point.y})
+ dct.update({'lon': item.point.x,
+ 'lat': item.point.y})
dct['tag']['name'] = item.name
node = None
import_key = item.get_key('OSM')
@@ -861,7 +939,7 @@ class OSMManager(ImportManager):
if error.status == 404:
dct.pop('id')
dct.pop('version')
- pass # if the node doesn't exist it is created
+ pass # if the node doesn't exist it is created
else:
raise
if not updated:
@@ -870,20 +948,23 @@ class OSMManager(ImportManager):
item.import_version = node['version']
item.save()
api.ChangesetClose()
- return idx+1, None
+ return idx + 1, None
+
-import urllib2, chardet, HTMLParser
+import chardet
+import HTMLParser
from BeautifulSoup import BeautifulSoup
-from lxml import etree
+
RE_CLEANS = ((re.compile('(\n)*|^( )*(\n)*( )*|( )*(\n)*( )*$'), ''),
(re.compile(' ( )*'), ' '),
(re.compile(r"""<a href=["'](?!https?)(.*)["']"""),
- '<a href="%(base_url)s\\1"'),
+ '<a href="%(base_url)s\\1"'),
)
from calendar import TimeEncoding, month_name
+
def get_month_name(month_no, locale):
with TimeEncoding(locale) as encoding:
s = month_name[month_no]
@@ -891,62 +972,62 @@ def get_month_name(month_no, locale):
s = s.decode(encoding)
return s
-MONTH_NAMES = {locale:[get_month_name(no_month, locale+'.UTF-8')
- for no_month in xrange(1, 13)] for locale in ['fr_FR']}
+MONTH_NAMES = {locale: [get_month_name(no_month, locale + '.UTF-8')
+ for no_month in xrange(1, 13)] for locale in ['fr_FR']}
try:
- UNI_MONTH_NAMES = {locale:[m.decode('utf-8') for m in MONTH_NAMES[locale]]
- for locale in MONTH_NAMES}
+ UNI_MONTH_NAMES = {locale: [m.decode('utf-8') for m in MONTH_NAMES[locale]]
+ for locale in MONTH_NAMES}
except UnicodeEncodeError:
- UNI_MONTH_NAMES = {locale:[m for m in MONTH_NAMES[locale]]
- for locale in MONTH_NAMES}
-
-DATE_PARSINGS = {'fr_FR':[
- re.compile(r'(?P<day1>\d{1,2}) '\
- r'(?P<month1>'+ '|'.join(UNI_MONTH_NAMES['fr_FR']) +') '\
- r'(?P<year1>\d{4})?[^\d]*'\
- r'(?P<day2>\d{1,2}) '\
- r'(?P<month2>'+ '|'.join(UNI_MONTH_NAMES['fr_FR']) +') *'\
- r'(?P<year2>\d{4})?.*'),
- re.compile(r'(?P<day1>\d{1,2}) '\
- r'(?P<month1>'+ '|'.join(UNI_MONTH_NAMES['fr_FR']) +') *'\
- r'(?P<year1>\d{4})?')
- ],
- 'en':[
- re.compile(r'(?P<year1>\d{4})-'\
- r'(?P<month1>\d{2})-'\
- r'(?P<day1>\d{2})'\
- r'(?:T'\
- r'(?P<hour1>\d{2})?:'\
- r'(?P<minut1>\d{2})?:'\
- r'(?P<second1>\d{2})'\
- r')?.*'\
- r'(?P<year2>\d{4})-'\
- r'(?P<month2>\d{2})-'\
- r'(?P<day2>\d{2})'\
- r'(?:T'\
- r'(?P<hour2>\d{2})?:'\
- r'(?P<minut2>\d{2})?:'\
- r'(?P<second2>\d{2})'\
- r')?.*'
- ),
- re.compile(r'(?P<year1>\d{4})-'\
- r'(?P<month1>\d{2})-'\
- r'(?P<day1>\d{2})'\
- r'(?:T'\
- r'(?P<hour1>\d{2})?:'\
- r'(?P<minut1>\d{2})?:'\
- r'(?P<second1>\d{2})'\
- r')?'
- )
- ],
- }
+ UNI_MONTH_NAMES = {locale: [m for m in MONTH_NAMES[locale]]
+ for locale in MONTH_NAMES}
+
+DATE_PARSINGS = {
+ 'fr_FR': [
+ re.compile(r'(?P<day1>\d{1,2}) '
+ r'(?P<month1>' + '|'.join(UNI_MONTH_NAMES['fr_FR']) + ') '
+ r'(?P<year1>\d{4})?[^\d]*'
+ r'(?P<day2>\d{1,2}) '
+ r'(?P<month2>' + '|'.join(UNI_MONTH_NAMES['fr_FR']) + ') *'
+ r'(?P<year2>\d{4})?.*'),
+ re.compile(r'(?P<day1>\d{1,2}) '
+ r'(?P<month1>' + '|'.join(UNI_MONTH_NAMES['fr_FR']) + ') * '
+ r'(?P<year1>\d{4})?')],
+ 'en': [
+ re.compile(r'(?P<year1>\d{4})-'
+ r'(?P<month1>\d{2})-'
+ r'(?P<day1>\d{2})'
+ r'(?:T'
+ r'(?P<hour1>\d{2})?:'
+ r'(?P<minut1>\d{2})?:'
+ r'(?P<second1>\d{2})'
+ r')?.*'
+ r'(?P<year2>\d{4})-'
+ r'(?P<month2>\d{2})-'
+ r'(?P<day2>\d{2})'
+ r'(?:T'
+ r'(?P<hour2>\d{2})?:'
+ r'(?P<minut2>\d{2})?:'
+ r'(?P<second2>\d{2})'
+ r')?.*'),
+ re.compile(r'(?P<year1>\d{4})-'
+ r'(?P<month1>\d{2})-'
+ r'(?P<day1>\d{2})'
+ r'(?:T'
+ r'(?P<hour1>\d{2})?:'
+ r'(?P<minut1>\d{2})?:'
+ r'(?P<second1>\d{2})'
+ r')?')],
+}
+
def clean_field(value):
return value.strip()
+
class HtmlXsltManager(ImportManager):
PARSER = 'HTMLParser'
+
def get(self):
u"""
Get data from the source
@@ -970,7 +1051,7 @@ class HtmlXsltManager(ImportManager):
soup = BeautifulSoup(data)
main_page = soup.prettify()
# convert it to valid XHTML
- #doc, errors = tidy_document(main_page)
+ # doc, errors = tidy_document(main_page)
doc = main_page
dom = etree.HTML(doc, getattr(etree, self.PARSER)())
try:
@@ -994,8 +1075,8 @@ class HtmlXsltManager(ImportManager):
base_url = u"/".join(self.importer_instance.source.split(u'/')[:-1])
base_url += u"/"
for item in newdom.getroot():
- c_item = {child.tag:clean_field(child.text)
- for child in item.getchildren() if child.text}
+ c_item = {child.tag: clean_field(child.text)
+ for child in item.getchildren() if child.text}
# try to have more information on the linked page
if transform_child and 'link' in c_item:
# not an absolute address
@@ -1016,8 +1097,8 @@ class HtmlXsltManager(ImportManager):
child_dom = etree.HTML(child_page, etree.HTMLParser())
extra_keys = transform_child(child_dom).getroot()
if len(extra_keys):
- c_item.update({extra.tag:etree.tostring(extra)
- for extra in extra_keys[0].getchildren()})
+ c_item.update({extra.tag: etree.tostring(extra)
+ for extra in extra_keys[0].getchildren()})
items.append(c_item)
# change relative link to full link, simplify, unescape HTML entities
html_unescape = HTMLParser.HTMLParser().unescape
@@ -1025,7 +1106,7 @@ class HtmlXsltManager(ImportManager):
for k in item:
val = item[k]
for r, replaced in RE_CLEANS:
- val = re.sub(r, replaced % {'base_url':base_url}, val)
+ val = re.sub(r, replaced % {'base_url': base_url}, val)
item[k] = html_unescape(val)
self.key_categories = self.importer_instance.get_key_category_dict()
self.missing_cats = set()
@@ -1034,9 +1115,10 @@ class HtmlXsltManager(ImportManager):
self.add_dct_item(item)
msg = ''
if self.missing_cats:
- msg = _(u"Names \"%s\" doesn't match existing categories. "
- u"Modify the import to match theses names with categories.") % (
- u'", "'.join(self.missing_cats))
+ msg = _(
+ u"Names \"%s\" doesn't match existing categories. "
+ u"Modify the import to match theses names with categories.") %\
+ (u'", "'.join(self.missing_cats))
return (self.new_item, self.updated_item, msg)
@classmethod
@@ -1073,18 +1155,18 @@ class HtmlXsltManager(ImportManager):
if not m:
continue
values = m.groupdict()
- date = self._internal_parse_date(locale,
- 'year1' in values and values['year1'],
- values['month1'], values['day1'])
+ date = self._internal_parse_date(
+ locale, 'year1' in values and values['year1'],
+ values['month1'], values['day1'])
if not date:
continue
dct['start_date'] = date
has_dates = True
if 'day2' not in values:
break
- date = self._internal_parse_date(locale,
- 'year2' in values and values['year2'],
- values['month2'], values['day2'])
+ date = self._internal_parse_date(
+ locale, 'year2' in values and values['year2'],
+ values['month2'], values['day2'])
if date:
dct['end_date'] = date
break
@@ -1092,13 +1174,14 @@ class HtmlXsltManager(ImportManager):
def add_dct_item(self, item):
if not self.importer_instance.default_localisation and \
- not "point" in item and not ("lat" in item and item['lat']):
+ "point" not in item and not ("lat" in item and item['lat']):
return
cls = None
- dct = {'origin':"<a href='%s'>%s</a>" % (item['link'],
- self.importer_instance.origin),
- 'license':self.importer_instance.license,
- 'name':item['name']}
+ dct = {
+ 'origin': "<a href='%s' target='_blank'>%s</a>" % (
+ item.get('link') or '#', self.importer_instance.origin),
+ 'license': self.importer_instance.license,
+ 'name': item['name']}
category = None
if 'category' in item and item['category']:
if item['category'] in self.key_categories:
@@ -1114,7 +1197,7 @@ class HtmlXsltManager(ImportManager):
item['lat'])
else:
dct['point'] = self.importer_instance.default_localisation
- dct['description'] = item['description']
+ dct['description'] = item.get('description', '')
if 'date' in item:
dct.update(self.parse_date(item['date']))
key = item['key']
@@ -1125,5 +1208,6 @@ class HtmlXsltManager(ImportManager):
if created:
self.new_item += 1
+
class XMLXsltManager(HtmlXsltManager):
PARSER = 'XMLParser'
diff --git a/chimere/views.py b/chimere/views.py
index be9d816..88619ce 100644
--- a/chimere/views.py
+++ b/chimere/views.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2008-2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2008-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
#
# RSS : Copyright (C) 2010 Pierre Clarenc <pierre.crc_AT_gmailDOTcom>,
# Samuel Renard <renard.samuel_AT_gmailDOTcom>,
@@ -24,15 +24,12 @@
Views of the project
"""
-import copy
import datetime
from itertools import groupby
import re
import simplejson as json
from django.conf import settings
-from django.contrib.auth import authenticate, login, logout
-from django.contrib.auth.forms import AuthenticationForm
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.gdal.error import OGRException
from django.contrib.gis.measure import D
@@ -41,23 +38,24 @@ from django.core import serializers
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.db.models import Q
-from django.http import HttpResponseRedirect, HttpResponse
-from django.shortcuts import redirect, render_to_response
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from django.shortcuts import get_object_or_404, redirect, render_to_response
from django.template import loader, RequestContext, defaultfilters
from django.utils import simplejson as json
from django.utils.http import urlquote
from django.utils.translation import ugettext as _
+from django.views.generic import TemplateView, ListView
-from chimere.actions import actions as default_actions
+from chimere.actions import actions
from chimere.models import Category, SubCategory, PropertyModel, Page,\
- Marker, Route, News, SimpleArea, Map, Color, TinyUrl, RouteFile,\
+ Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile,\
AggregatedRoute
-from chimere.widgets import getMapJS, PointChooserWidget, NominatimWidget,\
+from chimere.widgets import getMapJS, PointChooserWidget, \
RouteChooserWidget, AreaWidget
from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \
FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\
- notifyStaff, MapForm, RoutingForm, getStaffEmails
+ notifyStaff, AreaForm, RoutingForm, getStaffEmails
from chimere.route import router
@@ -74,41 +72,43 @@ def get_base_uri(request):
return base_uri
#TODO: convert to requestcontext
-def get_base_response(request, map_name="", propose=False):
+def get_base_response(request, area_name=""):
"""
Get the base url
"""
- base_response_dct = {'media_path':settings.MEDIA_URL,
- 'is_authenticated':request.user.is_authenticated()}
+ base_response_dct = {'media_path':settings.MEDIA_URL,}
base_response_dct['MOBILE'] = settings.MOBILE_TEST or \
get_current_site(request).domain in settings.MOBILE_DOMAINS
base_url = reverse("chimere:index")
if not base_url.startswith('/'):
base_url = '/' + base_url
- if map_name and map_name.endswith('/'):
- map_name = map_name[:-1]
- if map_name:
- base_response_dct['map_name_slash'] = map_name + "/"
+ if area_name and area_name.endswith('/'):
+ area_name = area_name[:-1]
+ if area_name:
+ base_response_dct['area_name_slash'] = area_name + "/"
if base_url[-1] != '/':
base_url += '/'
- base_url += map_name + '/'
+ base_url += area_name + '/'
base_response_dct['extra_url'] = base_url
- map = Map.getAvailable(user=request.user, urn=map_name, propose=propose,
- single=True)
- if map:
- map_name = map.urn
- elif map_name:
- return None, redirect(reverse('chimere:index'))
- if map:
- base_response_dct['can_write'] = map.can_write(user=request.user)
- base_response_dct['can_propose'] = map.can_propose(user=request.user)
-
- base_response_dct['map'] = map
- base_response_dct['map_name'] = map_name
- if map and map.external_css:
- base_response_dct['css_map'] = map.external_css
+ area = None
+ if area_name:
+ try:
+ area = Area.objects.get(urn=area_name, available=True)
+ except ObjectDoesNotExist:
+ return None, redirect(reverse('chimere:index'))
+ else:
+ try:
+ area = Area.objects.get(default=True)
+ area_name = area.urn
+ except ObjectDoesNotExist:
+ pass
+
+ base_response_dct['area'] = area
+ base_response_dct['area_name'] = area_name
+ if area and area.external_css:
+ base_response_dct['css_area'] = area.external_css
base_response_dct['dynamic_categories'] = True \
- if map and map.dynamic_categories else False
+ if area and area.dynamic_categories else False
base_response_dct['JQUERY_JS_URLS'] = settings.JQUERY_JS_URLS
base_response_dct['JQUERY_CSS_URLS'] = settings.JQUERY_CSS_URLS
base_response_dct['PROJECT_NAME'] = settings.PROJECT_NAME
@@ -116,17 +116,17 @@ def get_base_response(request, map_name="", propose=False):
base_response_dct['EXTRA_CSS'] = settings.EXTRA_CSS
return base_response_dct, None
-def getShareUrl(request, map_name='', network=''):
+def getShareUrl(request, area_name='', network=''):
"""
Get a share url
"""
- data = getTinyfiedUrl(request, request.GET.urlencode(), map_name)
+ data = getTinyfiedUrl(request, request.GET.urlencode(), area_name)
for name, url, img in settings.CHIMERE_SHARE_NETWORKS:
if defaultfilters.slugify(name) == network:
return HttpResponse(url % {'text':data['text'], 'url':data['url']})
return HttpResponse('')
-def getShareNetwork(request, map_name='', marker=None):
+def getShareNetwork(request, area_name='', marker=None):
"""
Get URLs to share items
"""
@@ -135,19 +135,14 @@ def getShareNetwork(request, map_name='', marker=None):
parameters = u'current_feature=%d' % marker.pk
parameters += u"&checked_categories=%s" % "_".join([str(m.id) \
for m in marker.categories.all()])
- net_dct = getTinyfiedUrl(request, parameters, map_name)
+ net_dct = getTinyfiedUrl(request, parameters, area_name)
share_networks = []
for network in settings.CHIMERE_SHARE_NETWORKS:
share_networks.append((network[0], network[1] % net_dct, network[2]))
return share_networks, net_dct
-
-def logout_view(request):
- logout(request)
- return redirect(reverse('chimere:index'))
-
-def index(request, map_name=None, default_map=None, simple=False,
- get_response=False, actions=default_actions):
+def index(request, area_name=None, default_area=None, simple=False,
+ get_response=False):
"""
Main page
"""
@@ -159,28 +154,9 @@ def index(request, map_name=None, default_map=None, simple=False,
request.session['last_visit'] != today:
request.session['last_visit'] = today
news_visible = True
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
-
- if request.POST:
- auth_form = AuthenticationForm(None, request.POST)
- invalid_msg = _(u"Invalid user or password.")
- if auth_form.is_valid():
- user = authenticate(
- username=auth_form.cleaned_data['username'],
- password=auth_form.cleaned_data['password'])
- if user is not None and user.is_active:
- login(request, user)
- return redirect(reverse('chimere:index'))
- else:
- response_dct['auth_form'] = auth_form
- else:
- response_dct['auth_form'] = AuthenticationForm()
-
- if not response_dct['map']:
- return render_to_response('chimere/no_map.html', response_dct,
- context_instance=RequestContext(request))
# don't mess with permalink
zoomout = True
if request.GET and 'lat' in request.GET \
@@ -198,24 +174,24 @@ def index(request, map_name=None, default_map=None, simple=False,
except:
pass
response_dct.update({
- 'actions':actions(request.user, response_dct['map_name']),
+ 'actions':actions(response_dct['area_name']),
'action_selected':('view',),
'error_message':'',
'is_map':True,
'news_visible': news_visible,
- 'maps_visible': settings.CHIMERE_DISPLAY_MAPS,
+ 'areas_visible': settings.CHIMERE_DISPLAY_AREAS,
'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,
'dynamic_categories':response_dct['dynamic_categories'],
'zoomout':zoomout,
- 'has_default_map':Map.objects.filter(default=True).count(),
- 'zoomout':zoomout,
- 'has_search':settings.CHIMERE_SEARCH_ENGINE,
+ 'has_default_area':Area.objects.filter(default=True).count(),
'zoomout':zoomout,
+ 'has_search':hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and \
+ settings.CHIMERE_SEARCH_ENGINE
})
if hasattr(settings, 'CONTACT_EMAIL') and settings.CONTACT_EMAIL:
response_dct['contact_email'] = settings.CONTACT_EMAIL
response_dct['share_networks'], net_dct = \
- getShareNetwork(request, response_dct['map_name'])
+ getShareNetwork(request, response_dct['area_name'])
tpl = 'chimere/main_map.html'
response_dct['simple'] = simple
if simple:
@@ -231,13 +207,13 @@ def get_edit_page(redirect_url, item_cls, item_form,
"""
Edition page
"""
- def func(request, map_name="", item_id=None, cat_type=['M']):
- response_dct, redir = get_base_response(request, map_name, propose=True)
+ def func(request, area_name="", item_id=None, cat_type=['M']):
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir, None, None
- if 'map_name' in response_dct:
- map_name = response_dct['map_name']
- subcategories = SubCategory.getAvailable(cat_type, map_name,
+ if 'area_name' in response_dct:
+ area_name = response_dct['area_name']
+ subcategories = SubCategory.getAvailable(cat_type, area_name,
public=True)
listed_subcats = []
if subcategories:
@@ -250,7 +226,7 @@ def get_edit_page(redirect_url, item_cls, item_form,
try:
init_item = item_cls.objects.get(pk=item_id)
except:
- return redirect(redirect_url, map_name + '/' if map_name \
+ return redirect(redirect_url, area_name + '/' if area_name \
else ''), None, None
ref_item = init_item
modified_item = item_cls.objects.filter(ref_item=init_item,
@@ -261,17 +237,18 @@ def get_edit_page(redirect_url, item_cls, item_form,
init_multi = init_item.get_init_multi() if init_item else None
init_picture = init_item.get_init_picture() if init_item else None
- if init_item and not response_dct['can_write'] and \
+ if init_item and not request.user.is_superuser and \
not init_item.submiter_session_key == \
request.session.session_key:
# hide personal information
for k in ('submiter_name', 'submiter_email', 'submiter_comment'):
setattr(init_item, k, '')
+ response_dct['is_superuser'] = request.user.is_superuser
# If the form has been submited
if request.method == 'POST':
inst = None
- # allow to directly modify only if owner or has can_write permission
- if init_item and (response_dct['can_write'] or \
+ # allow to directly modify only if owner or superuser
+ if init_item and (request.user.is_superuser or \
init_item.submiter_session_key == \
request.session.session_key):
inst = init_item
@@ -284,7 +261,7 @@ def get_edit_page(redirect_url, item_cls, item_form,
# All validation rules pass
if form.is_valid() and formset_multi.is_valid() and \
formset_picture.is_valid():
- item = form.save(can_write=response_dct.get('can_write'))
+ item = form.save()
# set the session key (to permit modifications)
item.submiter_session_key = request.session.session_key
@@ -302,7 +279,7 @@ def get_edit_page(redirect_url, item_cls, item_form,
# just submited
if not item.status:
- item.status = 'A' if response_dct.get('can_write') else 'S'
+ item.status = 'S'
item.save()
marker = item
@@ -318,9 +295,9 @@ def get_edit_page(redirect_url, item_cls, item_form,
f.save(marker)
base_uri = get_base_uri(request)
notifySubmission(base_uri, item)
- response_dct = get_base_response(request, map_name)
+ response_dct = get_base_response(request, area_name)
return redirect(redirect_url + '-item',
- map_name + '/' if map_name else '',
+ area_name + '/' if area_name else '',
item.ref_item.pk, 'submited'), None, subcategories
else:
response_dct['error_message'] = _(u"There are missing field(s)"
@@ -337,12 +314,11 @@ def get_edit_page(redirect_url, item_cls, item_form,
get_edit_marker = get_edit_page('chimere:edit', Marker, MarkerForm)
-def edit(request, map_name="", item_id=None, submited=False,
- actions=default_actions):
+def edit(request, area_name="", item_id=None, submited=False):
"""
Edition page
"""
- response, values, sub_categories = get_edit_marker(request, map_name,
+ response, values, sub_categories = get_edit_marker(request, area_name,
item_id, ['M', 'B'])
if response:
return response
@@ -356,24 +332,20 @@ def edit(request, map_name="", item_id=None, submited=False,
point_value = init_item.point if init_item else None
if request.POST and request.POST.get('point'):
point_value = request.POST.get('point')
- has_dated_items = settings.CHIMERE_DAYS_BEFORE_EVENT and [
- True for cat, subcats in sub_categories
- if [True for subcat in subcats if subcat.dated]]
response_dct.update({
- 'actions':actions(request.user, response_dct['map_name']),
+ 'actions':actions(response_dct['area_name']),
'action_selected':('contribute', 'edit'),
'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,
'form':form,
'formset_multi':formset_multi,
'formset_picture':formset_picture,
- 'dated':has_dated_items,
- 'extra_head':form.media + NominatimWidget().media,
+ 'dated':settings.CHIMERE_DAYS_BEFORE_EVENT,
+ 'extra_head':form.media,
'marker_id':item_id,
'sub_categories':sub_categories,
'point_widget':PointChooserWidget().render('point',
point_value,
- map_name=response_dct['map_name']),
- 'nominatim_widget':NominatimWidget().render('point'),
+ area_name=response_dct['area_name']),
'properties':declared_fields,
'filtered_properties':filtered_properties,
'submited':submited
@@ -384,8 +356,8 @@ def edit(request, map_name="", item_id=None, submited=False,
return render_to_response('chimere/edit.html', response_dct,
context_instance=RequestContext(request))
-def uploadFile(request, category_id='', map_name=''):
- response_dct, redir = get_base_response(request, map_name)
+def uploadFile(request, category_id='', area_name=''):
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
Form = FileForm if not category_id else FullFileForm
@@ -432,7 +404,7 @@ def uploadFile(request, category_id='', map_name=''):
return render_to_response('chimere/upload_file.html', response_dct,
context_instance=RequestContext(request))
-def processRouteFile(request, map_name='', file_id=None):
+def processRouteFile(request, area_name='', file_id=None):
if file_id:
try:
route_file = RouteFile.objects.get(pk=file_id)
@@ -450,12 +422,11 @@ def processRouteFile(request, map_name='', file_id=None):
get_edit_route = get_edit_page('chimere:editroute', Route, RouteForm)
-def editRoute(request, map_name="", item_id=None, submited=False,
- actions=default_actions):
+def editRoute(request, area_name="", item_id=None, submited=False):
"""
Route edition page
"""
- response, values, sub_categories = get_edit_route(request, map_name,
+ response, values, sub_categories = get_edit_route(request, area_name,
item_id, ['R', 'B'])
if response:
return response
@@ -469,22 +440,19 @@ def editRoute(request, map_name="", item_id=None, submited=False,
route_value = init_item.route if init_item else None
if request.POST and request.POST.get('route'):
route_value = request.POST.get('route')
- has_dated_items = settings.CHIMERE_DAYS_BEFORE_EVENT and [
- True for cat, subcats in sub_categories
- if [True for subcat in subcats if subcat.dated]]
response_dct.update({
- 'actions':actions(request.user, response_dct['map_name']),
+ 'actions':actions(response_dct['area_name']),
'action_selected':('contribute', 'edit-route'),
'error_message':'',
'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,
'form':form,
'formset_multi':formset_multi,
'formset_picture':formset_picture,
- 'dated':has_dated_items,
+ 'dated':settings.CHIMERE_DAYS_BEFORE_EVENT,
'extra_head':form.media,
'sub_categories':sub_categories,
'route_widget':RouteChooserWidget().render('route', route_value,
- map_name=response_dct['map_name'], routefile_id='',),
+ area_name=response_dct['area_name'], routefile_id='',),
'properties':declared_fields,
'submited':submited
})
@@ -494,33 +462,34 @@ def editRoute(request, map_name="", item_id=None, submited=False,
return render_to_response('chimere/edit_route.html', response_dct,
context_instance=RequestContext(request))
-def submited(request, map_name="", action="", actions=default_actions):
+def submited(request, area_name="", action=""):
"""
Successful submission page
"""
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- response_dct.update({'actions':actions(request.user, response_dct['map_name']),
- 'action_selected':action,})
+ dct = {'actions':actions(response_dct['area_name']),
+ 'action_selected':action,}
if hasattr(settings, 'CONTACT_EMAIL') and settings.CONTACT_EMAIL:
response_dct['contact_email'] = settings.CONTACT_EMAIL
+ response_dct.update(dct)
return render_to_response('chimere/submited.html', response_dct,
context_instance=RequestContext(request))
-def charte(request, map_name="", actions=default_actions):
+def charte(request, area_name=""):
"""
Affichage de la charte
"""
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- response_dct.update({'actions':actions(request.user, response_dct['map_name']),
+ response_dct.update({'actions':actions(response_dct['area_name']),
'action_selected':('charte',)})
return render_to_response('chimere/charte.html', response_dct,
context_instance=RequestContext(request))
-def contactus(request, map_name="", actions=default_actions):
+def contactus(request, area_name=""):
"""
Contact page
"""
@@ -541,16 +510,16 @@ def contactus(request, map_name="", actions=default_actions):
msg = _(u"Temporary error. Renew your message later.")
else:
form = ContactForm()
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- response_dct.update({'actions':actions(request.user, response_dct['map_name']),
+ response_dct.update({'actions':actions(response_dct['area_name']),
'action_selected':('contact',),
'contact_form':form, 'message':msg})
return render_to_response('chimere/contactus.html', response_dct,
context_instance=RequestContext(request))
-def extraPage(request, map_name="", page_id="", actions=default_actions):
+def extraPage(request, area_name="", page_id=""):
"""
Extra dynamic pages
"""
@@ -558,10 +527,10 @@ def extraPage(request, map_name="", page_id="", actions=default_actions):
page = Page.objects.get(available=True, mnemonic=page_id)
except ObjectDoesNotExist:
return redirect(reverse('chimere:index'))
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- response_dct.update({'actions':actions(request.user, response_dct['map_name']),
+ response_dct.update({'actions':actions(response_dct['area_name']),
'action_selected':(page_id,),
'content':page.content,
'title':page.title})
@@ -570,7 +539,7 @@ def extraPage(request, map_name="", page_id="", actions=default_actions):
return render_to_response(tpl, response_dct,
context_instance=RequestContext(request))
-def getDetail(request, map_name, marker_id):
+def getDetail(request, area_name, marker_id):
'''
Get the detail for a marker
'''
@@ -579,7 +548,7 @@ def getDetail(request, map_name, marker_id):
status__in=['A', 'S'])[0]
except (ValueError, IndexError):
return HttpResponse('no results')
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
response_dct['marker'] = marker
@@ -587,7 +556,7 @@ def getDetail(request, map_name, marker_id):
if 'simple' in request.GET and request.GET['simple']:
response_dct['simple'] = True
response_dct['share_networks'], net_dct = \
- getShareNetwork(request, response_dct['map_name'], marker)
+ getShareNetwork(request, response_dct['area_name'], marker)
response_dct['share_url'] = net_dct['url']
net_dct['to'] = settings.CONTACT_EMAIL
if net_dct['to']:
@@ -602,7 +571,7 @@ def getDetail(request, map_name, marker_id):
return render_to_response('chimere/detail.html', response_dct,
context_instance=RequestContext(request))
-def getDescriptionDetail(request, map_name, category_id):
+def getDescriptionDetail(request, area_name, category_id):
'''
Get the description for a category
'''
@@ -610,7 +579,7 @@ def getDescriptionDetail(request, map_name, category_id):
category = Category.objects.filter(id=int(category_id))[0]
except (ValueError, IndexError):
return HttpResponse('no results')
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
response_dct['category'] = category
@@ -632,82 +601,87 @@ def checkDate(q):
)
return q
-def getGeoObjects(request, map_name, category_ids, status):
+def _getGeoObjects(area_name, category_ids, status='A', getjson=True,
+ item_types=('Marker', 'Route')):
+ '''
+ Get markers and routes
+ '''
+ items = []
+ current_cat, colors, idx = None, None, 0
+ empty = [] if not getjson else {}
+
+ # marker
+ if 'Marker' in item_types:
+ try:
+ q = checkDate(Q(status__in=status, categories__in=category_ids))
+ query = Marker.objects.filter(q).distinct('pk').order_by('-pk')
+ except:
+ return empty
+
+ category_ids = [int(cat_id) for cat_id in category_ids]
+ if getjson:
+ for geo_object in list(query):
+ items += json.loads(geo_object.getGeoJSON(category_ids))
+ else:
+ items += list(query)
+
+ # routes
+ if 'Route' in item_types:
+ query = AggregatedRoute.objects.filter(status__in=status,
+ subcategory__in=category_ids).order_by('subcategory', '-pk')
+ if getjson:
+ for route in query.all():
+ c_cat = route.subcategory
+ if not current_cat or current_cat != c_cat:
+ idx = 0
+ current_cat = c_cat
+ colors = list(Color.objects.filter(
+ color_theme=c_cat.color_theme))
+ if colors:
+ items.append(json.loads(
+ route.getGeoJSON(color=colors[idx % len(colors)].code)))
+ else:
+ items.append(json.loads(route.getGeoJSON(color='000')))
+ idx += 1
+ else:
+ items += list(query)
+
+ if not items:
+ return empty
+ return items
+
+def getGeoObjects(request, area_name, category_ids, status):
'''
Get the JSON for markers and routes
'''
if not status:
status = 'A'
status = status.split('_')
- category_ids = category_ids.split('_')
- query = AggregatedRoute.objects.filter(status__in=status,
- subcategory__in=category_ids).order_by('subcategory')
- jsons = []
- current_cat, colors, idx = None, None, 0
- for route in query.all():
- c_cat = route.subcategory
- if not current_cat or current_cat != c_cat:
- idx = 0
- current_cat = c_cat
- colors = list(Color.objects.filter(color_theme = c_cat.color_theme))
- color = '000'
- if colors:
- color = colors[idx % len(colors)].code
- if '#' not in color:
- color = '#' + color
- base_dct = {"type":"Feature",
- "properties":{
- "color":color
- }
- }
- jsons.append(route._getItems(base_dct))
- idx += 1
- try:
- q = checkDate(Q(status__in=status, categories__in=category_ids))
- query = Marker.objects.filter(q).distinct('pk').order_by('pk')
- except:
- return HttpResponse('no results')
- category_ids = [int(cat_id) for cat_id in category_ids]
- for category_id in category_ids:
- if not category_id:
- continue
- cat = SubCategory.objects.get(pk=category_id)
- base_dct = {"type":"Feature",
- "properties":{
- "icon_path":unicode(cat.icon.image),
- "icon_hover_path":cat.hover_icon.image \
- if cat.hover_icon else '',
- "icon_width":cat.icon.image.width,
- 'icon_height':cat.icon.image.height,
- 'category_name':cat.name}
- }
- for values in query.filter(categories__pk=category_id).values(
- 'point', 'pk', 'name', 'weight'):
- jsons.append(Marker._getJson(values, copy.deepcopy(base_dct)))
+ category_ids = unicode(category_ids).split('_')
+
+ jsons = _getGeoObjects(area_name, category_ids, status)
if not jsons:
return HttpResponse('no results')
- data = {"type": "FeatureCollection", "features":jsons}
- data = json.dumps(data)
-
+ data = json.dumps({"type": "FeatureCollection", "features":jsons})
return HttpResponse(data, content_type="application/json")
-def getMarker(request, map_name, pk):
+def getMarker(request, area_name, pk):
q = Marker.objects.filter(pk=pk, status='A')
if not q.count():
return HttpResponse('{}')
data = q.all()[0].getGeoJSON()
return HttpResponse(data, content_type="application/json")
-def get_all_categories(request, map_name=None):
+def get_all_categories(request, area_name=None):
'''
Get all available categories in JSON
'''
- context_data, redir = get_base_response(request, map_name)
- map = context_data["map"]
+ context_data, redir = get_base_response(request, area_name)
+ area = context_data["area"]
subcategories = []
- if map:
- subcategories = list(map.getCategories('A',
- map_name=context_data['map_name']))
+ if area:
+ subcategories = list(area.getCategories('A',
+ area_name=context_data['area_name']))
else:
categories = SubCategory.getAvailable()
for cat, subcats in categories:
@@ -716,25 +690,25 @@ def get_all_categories(request, map_name=None):
jsons = json.dumps({'categories':subcats})
return HttpResponse(jsons)
-def get_available_categories(request, map_name=None, map=None, status='A',
+def get_available_categories(request, area_name=None, area=None, status='A',
force=None):
'''
- Get category menu for a designed map
+ Get category menu for a designed area
'''
- context_data, redir = get_base_response(request, map_name)
- map = context_data["map"]
+ context_data, redir = get_base_response(request, area_name)
+ area = context_data["area"]
if redir:
return redir
- if map and map.dynamic_categories and \
+ if area and area.dynamic_categories and \
not "current_extent" in request.GET:
context_data['sub_categories'] = []
return render_to_response('chimere/blocks/categories.html', context_data,
context_instance=RequestContext(request))
- if not map or not map.dynamic_categories:
+ if not area or not area.dynamic_categories:
# Categories are not updated dynamicaly when the user move the map
# so we return ALL the categories
subcategories = SubCategory.getAvailable(
- map_name=context_data['map_name'])
+ area_name=context_data['area_name'])
context_data['sub_categories'] = subcategories
return render_to_response('chimere/blocks/categories.html', context_data,
context_instance=RequestContext(request))
@@ -746,12 +720,12 @@ def get_available_categories(request, map_name=None, map=None, status='A',
status = status.split('_')
current_extent = request.GET["current_extent"].replace('M', '-')\
.replace('D', '.')
- map = SimpleArea([float(pt) for pt in current_extent.split('_')])
+ area = SimpleArea([float(pt) for pt in current_extent.split('_')])
except:
# bad extent format
return HttpResponse(default_message)
- # if not force and map.isIn(SimpleArea(cookie.AREA):return
- categories = map.getCategories(status, map_name=context_data['map_name'])
+ # if not force and area.isIn(SimpleArea(cookie.AREA):return
+ categories = area.getCategories(status, area_name=context_data['area_name'])
if not categories:
return HttpResponse(default_message)
get_cat = lambda subcat: subcat.category
@@ -764,7 +738,7 @@ def get_available_categories(request, map_name=None, map=None, status='A',
return render_to_response('chimere/blocks/categories.html', context_data,
context_instance=RequestContext(request))
-def getCategory(request, map_name='', category_id=0):
+def getCategory(request, area_name='', category_id=0):
'''
Get the JSON for a category (mainly in order to get the description)
'''
@@ -774,7 +748,7 @@ def getCategory(request, map_name='', category_id=0):
return HttpResponse('no results')
return HttpResponse(category.getJSON())
-def getTinyfiedUrl(request, parameters, map_name=''):
+def getTinyfiedUrl(request, parameters, area_name=''):
'''
Get the tinyfied version of parameters
'''
@@ -783,11 +757,11 @@ def getTinyfiedUrl(request, parameters, map_name=''):
urn = TinyUrl.getUrnByParameters(parameters)
except:
return {}
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- url = reverse('chimere:tiny', args=[(response_dct['map_name'] \
- if response_dct['map_name'] else '') + '/', urn])
+ url = reverse('chimere:tiny', args=[(response_dct['area_name'] \
+ if response_dct['area_name'] else '') + '/', urn])
if not url.startswith('http'):
url = get_base_uri(request) + url
url = re.sub("([^:])\/\/", "\g<1>/", url)
@@ -804,17 +778,89 @@ def getTinyfiedUrl(request, parameters, map_name=''):
data["text"] = urlquote(text)
return data
-def redirectFromTinyURN(request, map_name='', tiny_urn=''):
+def redirectFromTinyURN(request, area_name='', tiny_urn=''):
"""
Redirect from a tiny Urn
"""
parameters = '?' + TinyUrl.getParametersByUrn(tiny_urn)
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
return HttpResponseRedirect(response_dct['extra_url'] + parameters)
-def route(request, map_name, lon1, lat1, lonlat_steps, lon2, lat2,
+class CategoryDirectoryView(ListView):
+ template_name = "chimere/category_directory.html"
+
+ def get_queryset(self):
+ self.area_name = self.kwargs.get('area_name', None)
+ if self.area_name:
+ self.area_name = self.area_name.split('/')[0]
+ area = get_object_or_404(Area, urn=self.area_name, available=True)
+ q = area.subcategories.filter(available=True,
+ category__available=True
+ ).order_by('category__order', 'category__id', 'order')
+ if q.count():
+ return q
+ return SubCategory.objects.filter(available=True,
+ category__available=True
+ ).order_by('category__order', 'category__id', 'order')
+
+ def get_context_data(self, *args, **kwargs):
+ context = super(CategoryDirectoryView, self).get_context_data(
+ *args, **kwargs)
+ new_context, redirect = get_base_response(self.request, self.area_name)
+ context.update(new_context)
+ context.update({
+ 'actions':actions(self.area_name),
+ 'action_selected':('categories',),
+ })
+ return context
+
+class CategoryView(TemplateView):
+ template_name = "chimere/category_directory_detail.html"
+
+ def get_geo_items(self):
+ # TODO: simplify on v2.3 when slug are available
+ category_slug = self.kwargs.get('category_slug')
+ self.area_name = self.kwargs.get('area_name', None)
+ q = None
+ if self.area_name:
+ self.area_name = self.area_name.split('/')[0]
+ area = get_object_or_404(Area, urn=self.area_name, available=True)
+ q = area.subcategories.filter(available=True,
+ category__available=True)
+ if not q.count():
+ q = None
+ if not q:
+ q = SubCategory.objects.filter(available=True,
+ category__available=True)
+ self.category = None
+ for subcat in q:
+ if defaultfilters.slugify(subcat.name) == category_slug:
+ self.category = subcat
+ break
+ if not self.category:
+ raise Http404(_("Category does not exist"))
+
+ items = _getGeoObjects(self.area_name, [unicode(self.category.pk)],
+ getjson=False, item_types=('Marker',))
+ return items
+
+ def get_context_data(self, *args, **kwargs):
+ context = super(CategoryView, self).get_context_data(
+ *args, **kwargs)
+ self.items = self.get_geo_items()
+ new_context, redirect = get_base_response(self.request, self.area_name)
+ context.update(new_context)
+ context.update({
+ 'actions':actions(self.area_name),
+ 'action_selected':('categories',),
+ 'category':self.category,
+ 'items':self.items
+ })
+ return context
+
+def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2,
transport='foot', speed=''):
'''
Get the JSON for a route
@@ -893,18 +939,14 @@ def route(request, map_name, lon1, lat1, lonlat_steps, lon2, lat2,
message)
return HttpResponse(data)
-def get_json(request, map_name='', app_name='', filename=''):
- return HttpResponse(open(settings.STATIC_ROOT+app_name+'/json/'+filename+'.json'),
- 'application/javascript', status=200)
-
-def rss(request, map_name='', actions=default_actions):
+def rss(request, area_name=''):
'''
Redirect to RSS subscription page
'''
- response_dct, redir = get_base_response(request, map_name)
+ response_dct, redir = get_base_response(request, area_name)
if redir:
return redir
- response_dct.update({'actions':actions(request.user, response_dct['map_name']),
+ response_dct.update({'actions':actions(response_dct['area_name']),
'action_selected':('rss',),
'category_rss_feed':'',})
# If the form has been submited
@@ -926,14 +968,14 @@ def rss(request, map_name='', actions=default_actions):
# User wants to follow all the new POI situated in a defined area
elif request.POST['rss_category'] == 'area':
# An unbound form
- form = MapForm()
+ form = AreaForm()
area_widget = AreaWidget().render('area', None)
response_dct.update({
'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,
'extra_head':form.media,
'form':form,
'category_rss_feed':'area',
- 'map_id':Map.getAvailable(),
+ 'area_id':Area.getAvailable(),
'area_widget':area_widget
})
return render_to_response('chimere/feeds/rss.html',
@@ -964,10 +1006,10 @@ def rss(request, map_name='', actions=default_actions):
kwargs={'category_id':cat_id})
return redirect(feeds_link)
- # User has specified the ID of the map he wants to follow
- if 'id_map' in request.POST and request.POST['id_map'] != '':
- feeds_link = reverse('chimere:feeds-mapid',
- kwargs={'map_id':request.POST['id_map']})
+ # User has specified the ID of the area he wants to follow
+ if 'id_area' in request.POST and request.POST['id_area'] != '':
+ feeds_link = reverse('chimere:feeds-areaid',
+ kwargs={'area_id':request.POST['id_area']})
return redirect(feeds_link)
# User has specified the area he wants to follow => we redirect him
@@ -1002,12 +1044,12 @@ def rss(request, map_name='', actions=default_actions):
context_instance=RequestContext(request))
if request.GET['rss_category'] == 'area':
# An unbound form
- form = MapForm()
+ form = AreaForm()
response_dct.update({'map_layer':settings.MAP_LAYER,
'extra_head':form.media,
'form':form,
'category_rss_feed':'area',
- 'map_id':Map.getAvailable(),
+ 'area_id':Area.getAvailable(),
'area_widget':AreaWidget().render('area', None)})
return render_to_response('chimere/feeds/rss.html', response_dct,
context_instance=RequestContext(request))
@@ -1026,7 +1068,11 @@ if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \
from haystack.views import SearchView as HaystackSearchView
from haystack.query import SearchQuerySet
class SearchView(HaystackSearchView):
- pass
+ def extra_context(self, *args, **kwargs):
+ context = super(SearchView, self).extra_context(*args, **kwargs)
+ context["autocomplete"] = settings.HAYSTACK_AUTOCOMPLETE \
+ if hasattr(settings, 'HAYSTACK_AUTOCOMPLETE') else False
+ return context
def autocomplete(request):
sqs = SearchQuerySet().autocomplete(
content_auto=request.GET.get('q', ''))[:5]