From be70ae3016861cb13f1600c266522782b8e4dc90 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 22 Nov 2012 20:13:02 +0100 Subject: Admin: improve layout of markers and routes --- chimere/admin.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index e611ee0..b4231a7 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -165,8 +165,39 @@ class MarkerAdmin(admin.ModelAdmin): readonly_fields = ['submiter_email', 'submiter_comment', 'import_source', 'ref_item', 'modified_since_import'] form = MarkerAdminForm + fieldsets = ((None, { + 'fields': ['point', 'name', 'status', 'categories', + 'description', 'start_date', 'end_date'] + }), + (_(u"Submiter"), { + 'classes':('collapse',), + 'fields': ('submiter_name', 'submiter_email', + 'submiter_comment') + }), + (_(u"Import"), { + 'classes':('collapse',), + 'fields': ('modified_since_import', 'import_source', + 'origin', 'license') + }), + (_(u"Advanced options"), { + 'classes':('collapse',), + 'fields': ('ref_item', 'route',) + }), + ) inlines = [MultimediaInline, PictureInline] + def __init__(self, *args, **kwargs): + """ + Manage properties in fieldsets. + """ + main_fields = self.fieldsets[0][1]['fields'] + for pm in PropertyModel.objects.filter(available=True).order_by('order' + ).all(): + pm_name = pm.getNamedId() + if pm_name not in main_fields: + main_fields.append(pm_name) + super(MarkerAdmin, self).__init__(*args, **kwargs) + def queryset(self, request): qs = self.model._default_manager.get_query_set() if not request.user.is_superuser: @@ -192,6 +223,26 @@ class RouteAdmin(admin.ModelAdmin): readonly_fields = ('associated_file',) actions = [validate, disable, managed_modified, export_to_kml, export_to_shapefile, export_to_csv] + fieldsets = ((None, { + 'fields': ['route', 'name', 'status', 'categories', + 'start_date', 'end_date'] + }), + (_(u"Submiter"), { + 'classes':('collapse',), + 'fields': ('submiter_name', 'submiter_email', + 'submiter_comment') + }), + (_(u"Import"), { + 'classes':('collapse',), + 'fields': ('modified_since_import', 'import_source', + 'origin', 'license') + }), + (_(u"Advanced options"), { + 'classes':('collapse',), + 'fields': ('ref_item', 'associated_file', + 'has_associated_marker') + }), + ) def queryset(self, request): qs = self.model._default_manager.get_query_set() -- cgit v1.2.3 From 4064b6021750d693f905e903378901312a86e6d2 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 23 Nov 2012 03:44:34 +0100 Subject: OSM export: improve admin form --- chimere/admin.py | 30 ++++++++++++++++++++++++------ chimere/forms.py | 17 +++++++++++++++++ chimere/static/chimere/css/forms.css | 10 ++++++++++ chimere/templates/admin/osm_export.html | 30 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 chimere/templates/admin/osm_export.html (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index b4231a7..ff689af 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -38,7 +38,7 @@ except ImportError: from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ NewsAdminForm, CategoryAdminForm, ImporterAdminForm, \ - PictureFileAdminForm, MultimediaFileAdminForm + PictureFileAdminForm, MultimediaFileAdminForm, OSMForm from chimere.models import Category, Icon, SubCategory, Marker, \ PropertyModel, News, Route, Area, ColorTheme, Color, \ MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ @@ -290,11 +290,29 @@ def cancel_export(modeladmin, request, queryset): cancel_export.short_description = _(u"Cancel export") def export_to_osm(modeladmin, request, queryset): - importers = modeladmin.model.objects.filter(importer_type='OSM') - for importer in queryset: - importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0]) - importer.save() - tasks.exporting(importer.pk) + if queryset.count() > 1: + messages.error(request, _(u"Can manage only one OSM export at a time.")) + return HttpResponseRedirect(request.get_full_path()) + importer = queryset.all()[0] + if Marker.objects.filter(categories__in=importer.categories.all(), + status='I').count(): + messages.error(request, _(u"You must treat all item with the status "\ + u"\"imported\" before exporting to OSM.")) + return HttpResponseRedirect(request.get_full_path()) + if importer.importer_type != 'OSM': + messages.error(request, _(u"Only OSM importer are managed for export.")) + return HttpResponseRedirect(request.get_full_path()) + #for importer in queryset: + # importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0]) + # importer.save() + # tasks.exporting(importer.pk) + form = OSMForm() + item_nb = Marker.objects.filter(categories__in=importer.categories.all(), + not_for_osm=False).count() + msg_item = _(u"%s point(s) of interest concerned by this export") % item_nb + return render_to_response('admin/osm_export.html', {'importer':importer, + 'form':form, 'msg_item':msg_item}, + context_instance=RequestContext(request)) export_to_osm.short_description = _(u"Export to osm") class ImporterAdmin(admin.ModelAdmin): diff --git a/chimere/forms.py b/chimere/forms.py index a1e9319..597975d 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -89,6 +89,23 @@ class ContactForm(forms.Form): email = forms.EmailField(label=_("Email (optional)"), required=False) content = forms.CharField(label=_("Object"), widget=forms.Textarea) +class OSMForm(forms.Form): + """ + OSM export form + """ + email = forms.EmailField(label=_("OSM user")) + password = forms.CharField(label=_(u"Password"), + widget=forms.PasswordInput(render_value=False)) + # API URL are hardcoded: the day the API change Chimère will need + # adaptations + api = forms.ChoiceField(label=_(u"API"), + choices=(('', '--'), + ('api06.dev.openstreetmap.org', + _(u"Test API - %s") % 'api06.dev.openstreetmap.org'), + ('api.openstreetmap.org/api', + _(u"Main API - %s") % 'api.openstreetmap.org/api'), + )) + class NewsAdminForm(forms.ModelForm): """ Main form for news diff --git a/chimere/static/chimere/css/forms.css b/chimere/static/chimere/css/forms.css index 58315cd..a763a34 100644 --- a/chimere/static/chimere/css/forms.css +++ b/chimere/static/chimere/css/forms.css @@ -161,3 +161,13 @@ form .aligned .input-osm p{ padding:0.2em; margin:0; } + +form .aligned p.help-osm{ + padding-left:0; + margin-left:0; +} + +form .aligned p.help-osm.errornote{ + padding-left:30px; + margin-left:0; +} diff --git a/chimere/templates/admin/osm_export.html b/chimere/templates/admin/osm_export.html new file mode 100644 index 0000000..42ea0f7 --- /dev/null +++ b/chimere/templates/admin/osm_export.html @@ -0,0 +1,30 @@ +{% extends "admin/base_site.html" %} +{% load chimere_tags i18n admin_static %} + +{% block extrahead %} + +{% endblock %} + + +{% block content %} +
+
+{% csrf_token %} + + + + +{{ form.as_table }} +
+
+ +

{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. If you are not sure of what you are doing: DON'T EXPORT TO OSM!{% endblocktrans %}

+ + +{% endblock %} -- cgit v1.2.3 From 7cc593fd4db11fb0ad60ad7875022f6b497ada08 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 23 Nov 2012 19:04:57 +0100 Subject: Fix category modification on amendment submission. --- chimere/admin.py | 9 +++++++-- chimere/models.py | 2 -- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index ff689af..4e175aa 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -118,8 +118,13 @@ def managed_modified(modeladmin, request, queryset): if not request.POST[k]: continue if hasattr(it_ref, k): - setattr(it_ref, k, getattr(it, k)) - it_ref.save() + c_value = getattr(it_ref, k) + if hasattr(c_value, 'select_related'): + c_value.clear() + for val in getattr(it, k).all(): + c_value.add(val) + else: + it_ref.save() elif k.startswith('property_'): try: pm = PropertyModel.get(pk=int(k[len('property_'):])) diff --git a/chimere/models.py b/chimere/models.py index 76e6821..8420255 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -1104,8 +1104,6 @@ class SimpleArea: # set union behave strangely. Doing it manualy... for c in set(SubCategory.objects.raw(sql)): subcats.add(c) - #if c not in subcats: - # new_subcats.append(c) return subcats class Layer(models.Model): -- cgit v1.2.3 From 8bcca56ce043e0e4312315d69e436935e28ad9dc Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 23 Nov 2012 21:25:27 +0100 Subject: Fix route rapprochement: prevent delete of associated marker --- chimere/admin.py | 19 ++++++++++++++++--- chimere/models.py | 2 +- chimere/tests.py | 32 +++++++++++++++++++++++++++++--- chimere/views.py | 4 +++- 4 files changed, 49 insertions(+), 8 deletions(-) (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 4e175aa..8fe2b77 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -112,9 +112,21 @@ def managed_modified(modeladmin, request, queryset): if request.POST.get('rapprochement'): couple = [(item, item_ref)] if hasattr(item, 'associated_marker'): - couple.append((item.associated_marker, item_ref.associated_marker)) - for it, it_ref in couple: - for k in request.POST: + couple.append((item.associated_marker.all()[0], + item_ref.associated_marker.all()[0])) + updated_keys = request.POST + updated_keys.pop('action') + updated_keys.pop('rapprochement') + updated_keys.pop('index') + updated_keys.pop('_selected_action') + for idx, cpl in enumerate(couple): + it, it_ref = cpl + # don't copy geometry of associated items + if idx: + for k in ('route', 'point'): + if k in updated_keys: + updated_keys.pop(k) + for k in updated_keys: if not request.POST[k]: continue if hasattr(it_ref, k): @@ -124,6 +136,7 @@ def managed_modified(modeladmin, request, queryset): for val in getattr(it, k).all(): c_value.add(val) else: + setattr(it_ref, k, getattr(it, k)) it_ref.save() elif k.startswith('property_'): try: diff --git a/chimere/models.py b/chimere/models.py index 8420255..065f7e9 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -960,7 +960,7 @@ def route_post_save(sender, **kwargs): marker_fields = [f.attname for f in Marker._meta.fields] route_fields = [f.attname for f in Route._meta.fields] marker_dct = dict([(k, getattr(instance, k)) for k in marker_fields - if k in route_fields and k not in ('id', 'ref_item_id')]) + if k in route_fields and k not in ('id', 'ref_item_id')]) marker_dct['point'] = "SRID=%d;POINT(%f %f)" % (instance.route.srid, instance.route[0][0], instance.route[0][1]) marker, created = Marker.objects.get_or_create(route=instance, diff --git a/chimere/tests.py b/chimere/tests.py index 5fd9f55..0bfd830 100644 --- a/chimere/tests.py +++ b/chimere/tests.py @@ -95,7 +95,7 @@ def route_setup(sub_categories=[]): current_date = datetime.datetime.now() routes = [] route_1 = Route.objects.create(name="Route 1", status='A', - has_associated_marker=False, route='SRID=4326;LINESTRING(-1 1, 1 -1)') + has_associated_marker=True, route='SRID=4326;LINESTRING(-1 1, 1 -1)') route_1.categories.add(sub_categories[0]) routes.append(route_1) route_2 = Route.objects.create(name="Route 2", status='A', @@ -358,13 +358,15 @@ class NewsTest(TestCase): class RapprochementTest(TestCase): def setUp(self): self.areas = areas_setup() - self.markers = marker_setup() + self.subcategories = subcategory_setup() + self.markers = marker_setup(self.subcategories) + self.routes = route_setup(self.subcategories) self.adminuser = User.objects.create_superuser('admin', 'admin@test.com', 'pass') self.client.login(username='admin', password='pass') - def test_managed_modified(self): + def test_managed_modified_markers(self): ref_marker = self.markers[0] new_vals = {'name':"Marker 1 - modified", 'point':GEOSGeometry('SRID=4326;POINT(-4 48)')} @@ -384,6 +386,30 @@ class RapprochementTest(TestCase): for k in new_vals: self.assertEqual(getattr(ref_marker, k), new_vals[k]) + def test_managed_modified_routes(self): + ref_route = self.routes[0] + new_vals = {'name':"Route 1 - modified", + 'route':GEOSGeometry('SRID=4326;LINESTRING(1 1,2 2)')} + values = {'status':'M', 'ref_item':ref_route, + 'has_associated_marker':True} + values.update(new_vals) + modified_route = Route.objects.create(**values) + modified_route.categories.add(self.subcategories[1]) + response = self.client.post('/admin/chimere/route/', + data={'action':['managed_modified'], + 'index':0, 'rapprochement':1, + 'name':1, 'route':1, 'categories':1, + '_selected_action':[unicode(ref_route.pk)] + }) + ref_route = Route.objects.get(pk=ref_route.pk) + self.assertEqual(Route.objects.filter(ref_item=ref_route, + status='M').count(), 0) + self.assertEqual(ref_route.name, new_vals['name']) + self.assertEqual(ref_route.route.wkt, new_vals['route'].wkt) + self.assertEqual(ref_route.categories.all()[0], self.subcategories[1]) + self.assertEqual(ref_route.associated_marker.all()[0].name, + ref_route.name) + class RouteTest(TestCase): def setUp(self): self.subcategories = subcategory_setup() diff --git a/chimere/views.py b/chimere/views.py index 99ecc89..db63809 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -187,7 +187,6 @@ def get_edit_page(redirect_url, item_cls, item_form, init_item.submiter_session_key == \ request.session.session_key): inst = init_item - form = item_form(request.POST, request.FILES, instance=inst, subcategories=listed_subcats) formset_multi = multimediafile_formset(request.POST, request.FILES, @@ -206,6 +205,9 @@ def get_edit_page(redirect_url, item_cls, item_form, item.ref_item = ref_item if item.pk != ref_item.pk: item.status = 'M' + if hasattr(ref_item, 'has_associated_marker'): + item.has_associated_marker = \ + ref_item.has_associated_marker elif not item.ref_item: # initialisation item.ref_item = item -- cgit v1.2.3 From 9edddaf1cce657e97f3550565e446d9a91e69fce Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 24 Nov 2012 02:09:54 +0100 Subject: Fix rapprochement - work on OSM export interface --- chimere/admin.py | 43 ++++++++++++++++++++++----------- chimere/forms.py | 4 +-- chimere/models.py | 2 +- chimere/tasks.py | 4 +-- chimere/templates/admin/osm_export.html | 3 ++- chimere/utils.py | 20 +++++++++++---- 6 files changed, 51 insertions(+), 25 deletions(-) (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 8fe2b77..931dcf1 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -114,11 +114,11 @@ def managed_modified(modeladmin, request, queryset): if hasattr(item, 'associated_marker'): couple.append((item.associated_marker.all()[0], item_ref.associated_marker.all()[0])) - updated_keys = request.POST - updated_keys.pop('action') - updated_keys.pop('rapprochement') - updated_keys.pop('index') - updated_keys.pop('_selected_action') + updated_keys = dict(request.POST) + # clean + for k in ('action', 'rapprochement', 'index', '_selected_action'): + if k in updated_keys: + updated_keys.pop(k) for idx, cpl in enumerate(couple): it, it_ref = cpl # don't copy geometry of associated items @@ -320,15 +320,30 @@ def export_to_osm(modeladmin, request, queryset): if importer.importer_type != 'OSM': messages.error(request, _(u"Only OSM importer are managed for export.")) return HttpResponseRedirect(request.get_full_path()) - #for importer in queryset: - # importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0]) - # importer.save() - # tasks.exporting(importer.pk) - form = OSMForm() - item_nb = Marker.objects.filter(categories__in=importer.categories.all(), - not_for_osm=False).count() - msg_item = _(u"%s point(s) of interest concerned by this export") % item_nb - return render_to_response('admin/osm_export.html', {'importer':importer, + item_nb = Marker.objects.filter(status='A', + categories=importer.categories.all(), + not_for_osm=False, modified_since_import=True, + route=None).count() + if not item_nb: + messages.error(request, _(u"No point of interest are concerned by this " + u"export.")) + return HttpResponseRedirect(request.get_full_path()) + form = None + if request.method == 'POST' and ( + 'email' in request.POST or 'api' in request.POST + or 'password' in request.POST): + form = OSMForm(request.POST) + if form.is_valid(): + importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0]) + importer.save() + tasks.exporting(importer.pk, form.cleaned_data) + messages.success(request, _(u"Export launched.")) + return HttpResponseRedirect(request.get_full_path()) + else: + form = OSMForm() + msg_item = _(u"%s point(s) of interest concerned by this export before "\ + u"bounding box filter.") % item_nb + return render_to_response('admin/osm_export.html', {'item':importer, 'form':form, 'msg_item':msg_item}, context_instance=RequestContext(request)) export_to_osm.short_description = _(u"Export to osm") diff --git a/chimere/forms.py b/chimere/forms.py index 597975d..d02d6ea 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -93,11 +93,11 @@ class OSMForm(forms.Form): """ OSM export form """ - email = forms.EmailField(label=_("OSM user")) + username = forms.EmailField(label=_("OSM user")) password = forms.CharField(label=_(u"Password"), widget=forms.PasswordInput(render_value=False)) # API URL are hardcoded: the day the API change Chimère will need - # adaptations + # adaptations not only on this portion... api = forms.ChoiceField(label=_(u"API"), choices=(('', '--'), ('api06.dev.openstreetmap.org', diff --git a/chimere/models.py b/chimere/models.py index 065f7e9..03b5dce 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -294,7 +294,7 @@ class GeographicItem(models.Model): import_source = models.CharField(_(u"Source"), max_length=200, blank=True, null=True) modified_since_import = models.BooleanField(_(u"Modified since last import"), - default=False) + default=True) not_for_osm = models.BooleanField(_(u"Not to be imported inside OSM"), default=False) origin = models.CharField(_(u"Origin"), max_length=100, diff --git a/chimere/tasks.py b/chimere/tasks.py index 53c0e5b..a74dce8 100644 --- a/chimere/tasks.py +++ b/chimere/tasks.py @@ -98,7 +98,7 @@ def importing(importer_pk): @task() @single_instance_task(60*10) -def exporting(importer_pk): +def exporting(importer_pk, extra_args=[]): try: importer = Importer.objects.get(pk=importer_pk) except ObjectDoesNotExist: @@ -111,7 +111,7 @@ def exporting(importer_pk): importer.save() error = None try: - updated_item, error = importer.manager.put() + updated_item, error = importer.manager.put(extra_args) except OsmApi.ApiError, error: pass if error: diff --git a/chimere/templates/admin/osm_export.html b/chimere/templates/admin/osm_export.html index 42ea0f7..dab123e 100644 --- a/chimere/templates/admin/osm_export.html +++ b/chimere/templates/admin/osm_export.html @@ -18,10 +18,11 @@
    +
  • {% trans "Only points of interest are managed by this export." %}
  • {{msg_item}}
  • {% trans "Before exporting to OSM an import is done to verify that no modification has been made. All pending imported item have to be validated before export." %}
-

{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. If you are not sure of what you are doing: DON'T EXPORT TO OSM!{% endblocktrans %}

+

{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. If you are not sure of what you are doing: DON'T EXPORT TO OSM!{% endblocktrans %}

diff --git a/chimere/utils.py b/chimere/utils.py index ed41a04..25b5900 100644 --- a/chimere/utils.py +++ b/chimere/utils.py @@ -67,7 +67,7 @@ class ImportManager: def get(self): pass - def put(self): + def put(self, extra_args={}): pass def create_or_update_item(self, cls, values, import_key, version=None, @@ -721,7 +721,7 @@ class OSMManager(ImportManager): items.append(item) return (new_item, updated_item, msg) - def put(self): + def put(self, extra_args={}): # first of all: reimport in order to verify that no changes has been # made since the last import from models import Marker @@ -735,9 +735,19 @@ class OSMManager(ImportManager): return 0, _(u"There are items from a former import not yet " u"validated - validate them before exporting") # start import - api = OsmApi.OsmApi(api=settings.CHIMERE_OSM_API_URL, - username=settings.CHIMERE_OSM_USER, - password=settings.CHIMERE_OSM_PASSWORD) + api = settings.CHIMERE_OSM_API_URL + username = settings.CHIMERE_OSM_USER + password = settings.CHIMERE_OSM_PASSWORD + if extra_args: + try: + api = extra_args['api'] + username = extra_args['username'] + password = extra_args['password'] + except KeyError: + return 0, _(u"Bad params - programming error") + api = OsmApi.OsmApi(api=api, + username=username, + password=password) api.ChangesetCreate({u"comment": u"Import from Chimère %s" % \ get_version()}) hooks = RE_HOOK.findall(self.importer_instance.filtr) -- cgit v1.2.3 From 1ac9350e74bce36eb8f64d8564a3c44e6072600e Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 24 Nov 2012 15:36:43 +0100 Subject: Admin: improve property model management * Add the ability to hide property model from the admin * Add a warning to the admin that it should reload the webserver --- chimere/admin.py | 7 ++-- .../templates/admin/chimere/managed_modified.html | 47 ++++++++++++++++++++++ chimere/templates/admin/chimere/osm_export.html | 31 ++++++++++++++ .../admin/chimere/propertymodel/change_form.html | 7 ++++ chimere/templates/admin/managed_modified.html | 47 ---------------------- chimere/templates/admin/osm_export.html | 31 -------------- example_project/settings.py | 4 ++ 7 files changed, 93 insertions(+), 81 deletions(-) create mode 100644 chimere/templates/admin/chimere/managed_modified.html create mode 100644 chimere/templates/admin/chimere/osm_export.html create mode 100644 chimere/templates/admin/chimere/propertymodel/change_form.html delete mode 100644 chimere/templates/admin/managed_modified.html delete mode 100644 chimere/templates/admin/osm_export.html (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 931dcf1..87d2e08 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -150,7 +150,7 @@ def managed_modified(modeladmin, request, queryset): item.delete() messages.success(request, _(u"Modified item traited.")) return HttpResponseRedirect(request.get_full_path()) - return render_to_response('admin/managed_modified.html', + return render_to_response('admin/chimere/managed_modified.html', {'item':item, 'item_ref':item_ref}, context_instance=RequestContext(request)) managed_modified.short_description = _(u"Managed modified items") @@ -343,7 +343,7 @@ def export_to_osm(modeladmin, request, queryset): form = OSMForm() msg_item = _(u"%s point(s) of interest concerned by this export before "\ u"bounding box filter.") % item_nb - return render_to_response('admin/osm_export.html', {'item':importer, + return render_to_response('admin/chimere/osm_export.html', {'item':importer, 'form':form, 'msg_item':msg_item}, context_instance=RequestContext(request)) export_to_osm.short_description = _(u"Export to osm") @@ -393,7 +393,8 @@ admin.site.register(Category, CategoryAdmin) admin.site.register(Icon, IconAdmin) admin.site.register(Marker, MarkerAdmin) admin.site.register(Route, RouteAdmin) -admin.site.register(PropertyModel, PropertyModelAdmin) +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/templates/admin/chimere/managed_modified.html b/chimere/templates/admin/chimere/managed_modified.html new file mode 100644 index 0000000..c55650d --- /dev/null +++ b/chimere/templates/admin/chimere/managed_modified.html @@ -0,0 +1,47 @@ +{% extends "admin/base_site.html" %} +{% load chimere_tags i18n admin_static %} + +{% block extrahead %} + + +{% endblock %} + + +{% block content %} +

{% trans "Be careful: after validation, the modified item will be deleted. There is no roll-back." %}

+
+
+{% csrf_token %} + + + + + + + + + + + + + + + + + +{% for property_ref in item_ref.getProperties %} +{% for property in item.getProperties %} +{% ifequal property_ref.propertymodel property.propertymodel %} + +{% endifequal %} +{% endfor %} +{% endfor %} + +
 {% trans "Reference" %}{% trans "Modified item" %}{% trans "Accept modification" %}
{% trans "Name" %}{{item_ref}}{{item}}
{% trans "Categories" %}{% for cat in item_ref.categories.all %}{%if forloop.counter0 %}, {%endif%}{{cat}}{%endfor%}{% for cat in item.categories.all %}{%if forloop.counter0 %}, {%endif%}{{cat}}{%endfor%}
{% trans "Emplacement" %}{{item_ref|ol_map:'map_ref_id'}}{{item|ol_map:'map_id'}}
{% trans "Description" %}{{item_ref.description|safe}}{{item.description|safe}}
{{property.propertymodel.name}}{{property_ref.value|safe}}{{property.value|safe}}
+
+ + +{% endblock %} diff --git a/chimere/templates/admin/chimere/osm_export.html b/chimere/templates/admin/chimere/osm_export.html new file mode 100644 index 0000000..dab123e --- /dev/null +++ b/chimere/templates/admin/chimere/osm_export.html @@ -0,0 +1,31 @@ +{% extends "admin/base_site.html" %} +{% load chimere_tags i18n admin_static %} + +{% block extrahead %} + +{% endblock %} + + +{% block content %} +
+
+{% csrf_token %} + + + + +{{ form.as_table }} +
+
+
    +
  • {% trans "Only points of interest are managed by this export." %}
  • +
  • {{msg_item}}
  • +
  • {% trans "Before exporting to OSM an import is done to verify that no modification has been made. All pending imported item have to be validated before export." %}
  • +
+

{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. If you are not sure of what you are doing: DON'T EXPORT TO OSM!{% endblocktrans %}

+ + +{% endblock %} diff --git a/chimere/templates/admin/chimere/propertymodel/change_form.html b/chimere/templates/admin/chimere/propertymodel/change_form.html new file mode 100644 index 0000000..0ebeab0 --- /dev/null +++ b/chimere/templates/admin/chimere/propertymodel/change_form.html @@ -0,0 +1,7 @@ +{% extends "admin/change_form.html" %} +{% load i18n %} +{% block after_field_sets %} +

+{% trans "After add/modification of property models you'll have to reload the webserver." %} +

+{% endblock %} diff --git a/chimere/templates/admin/managed_modified.html b/chimere/templates/admin/managed_modified.html deleted file mode 100644 index c55650d..0000000 --- a/chimere/templates/admin/managed_modified.html +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load chimere_tags i18n admin_static %} - -{% block extrahead %} - - -{% endblock %} - - -{% block content %} -

{% trans "Be careful: after validation, the modified item will be deleted. There is no roll-back." %}

-
-
-{% csrf_token %} - - - - - - - - - - - - - - - - - -{% for property_ref in item_ref.getProperties %} -{% for property in item.getProperties %} -{% ifequal property_ref.propertymodel property.propertymodel %} - -{% endifequal %} -{% endfor %} -{% endfor %} - -
 {% trans "Reference" %}{% trans "Modified item" %}{% trans "Accept modification" %}
{% trans "Name" %}{{item_ref}}{{item}}
{% trans "Categories" %}{% for cat in item_ref.categories.all %}{%if forloop.counter0 %}, {%endif%}{{cat}}{%endfor%}{% for cat in item.categories.all %}{%if forloop.counter0 %}, {%endif%}{{cat}}{%endfor%}
{% trans "Emplacement" %}{{item_ref|ol_map:'map_ref_id'}}{{item|ol_map:'map_id'}}
{% trans "Description" %}{{item_ref.description|safe}}{{item.description|safe}}
{{property.propertymodel.name}}{{property_ref.value|safe}}{{property.value|safe}}
-
- - -{% endblock %} diff --git a/chimere/templates/admin/osm_export.html b/chimere/templates/admin/osm_export.html deleted file mode 100644 index dab123e..0000000 --- a/chimere/templates/admin/osm_export.html +++ /dev/null @@ -1,31 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load chimere_tags i18n admin_static %} - -{% block extrahead %} - -{% endblock %} - - -{% block content %} -
-
-{% csrf_token %} - - - - -{{ form.as_table }} -
-
-
    -
  • {% trans "Only points of interest are managed by this export." %}
  • -
  • {{msg_item}}
  • -
  • {% trans "Before exporting to OSM an import is done to verify that no modification has been made. All pending imported item have to be validated before export." %}
  • -
-

{% blocktrans %}Ensure that all the data exported to OSM have an appropriate license. You can exclude some points of interest by checking the checkbox "Not to be imported in OSM" in the point of interest form. If you are not sure of what you are doing: DON'T EXPORT TO OSM!{% endblocktrans %}

- - -{% endblock %} diff --git a/example_project/settings.py b/example_project/settings.py index e6e0430..c48a847 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -69,6 +69,10 @@ CHIMERE_OSM_API_URL = 'api06.dev.openstreetmap.org' # test URL CHIMERE_OSM_USER = 'test' CHIMERE_OSM_PASSWORD = 'test' +# as the web server need to be reloaded when property models are changed +# it could be a good idea to hide it to an admin who could'nt do that +CHIMERE_HIDE_PROPERTYMODEL = False + # encoding for shapefile import CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1' -- cgit v1.2.3 From 8a4293f93328ad4aca63a9019f68b41e004fbf18 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 24 Nov 2012 23:26:08 +0100 Subject: Update french translation --- chimere/admin.py | 4 +- chimere/locale/fr/LC_MESSAGES/django.po | 450 ++++++++++++++++++++------------ 2 files changed, 283 insertions(+), 171 deletions(-) (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 87d2e08..1d3dcbe 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -187,7 +187,7 @@ class MarkerAdmin(admin.ModelAdmin): 'fields': ['point', 'name', 'status', 'categories', 'description', 'start_date', 'end_date'] }), - (_(u"Submiter"), { + (_(u"Submitter"), { 'classes':('collapse',), 'fields': ('submiter_name', 'submiter_email', 'submiter_comment') @@ -245,7 +245,7 @@ class RouteAdmin(admin.ModelAdmin): 'fields': ['route', 'name', 'status', 'categories', 'start_date', 'end_date'] }), - (_(u"Submiter"), { + (_(u"Submitter"), { 'classes':('collapse',), 'fields': ('submiter_name', 'submiter_email', 'submiter_comment') diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index cd035d2..5cd7bfc 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -7,18 +7,18 @@ msgid "" msgstr "" "Project-Id-Version: 0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-11-22 02:05+0100\n" +"POT-Creation-Date: 2012-11-24 16:10+0100\n" "PO-Revision-Date: 2010-03-20 20:00+0100\n" "Last-Translator: Étienne Loks \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:8 models.py:633 +#: __init__.py:8 models.py:632 msgid "Multimedia files" msgstr "Fichiers multimedias" -#: __init__.py:9 models.py:689 +#: __init__.py:9 models.py:688 msgid "Picture files" msgstr "Fichiers d'image" @@ -50,7 +50,7 @@ msgstr "Nous contacter" msgid "Disable" msgstr "Désactiver" -#: admin.py:60 templates/admin/managed_modified.html:44 +#: admin.py:60 templates/admin/chimere/managed_modified.html:44 #: templates/chimere/feeds/rss.html:70 msgid "Validate" msgstr "Valider" @@ -69,33 +69,72 @@ msgstr "Exporter en CSV" #: admin.py:99 msgid "Only one item can be managed at a time." -msgstr "Seul élément à la fois peut-être géré." +msgstr "Seul un élément à la fois peut-être géré." #: admin.py:108 msgid "No modified item associated to the selected item." msgstr "Pas d'élément modifié associé à l'élément sélectionné." -#: admin.py:133 +#: admin.py:151 msgid "Modified item traited." msgstr "Élément modifié traité." -#: admin.py:138 +#: admin.py:156 msgid "Managed modified items" msgstr "Gérer les éléments modifiés" -#: admin.py:227 +#: admin.py:190 admin.py:248 +msgid "Submitter" +msgstr "Demandeur" + +#: admin.py:195 admin.py:253 admin.py:296 msgid "Import" msgstr "Import" -#: admin.py:233 +#: admin.py:200 admin.py:258 +msgid "Advanced options" +msgstr "Options avancées" + +#: admin.py:302 msgid "Cancel import" msgstr "Annuler l'import" -#: admin.py:239 +#: admin.py:308 msgid "Cancel export" msgstr "Annuler l'export" -#: admin.py:247 +#: admin.py:312 +msgid "Can manage only one OSM export at a time." +msgstr "Ne peux gérer qu'un seul export OSM à la fois." + +#: admin.py:317 +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:321 +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:328 +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:340 +msgid "Export launched." +msgstr "Export lancé." + +#: admin.py:344 +#, 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:349 msgid "Export to osm" msgstr "Exporter vers osm" @@ -111,98 +150,120 @@ 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:76 +#: forms.py:77 msgid "New submission for" msgstr "Nouvelle proposition pour" -#: forms.py:77 +#: forms.py:78 #, 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:79 +#: forms.py:80 msgid "To valid, precise or unvalid this item: " msgstr "Pour valider, préciser ou rejeter cet élément : " -#: forms.py:89 +#: forms.py:90 msgid "Email (optional)" msgstr "Courriel (optionnel) " -#: forms.py:90 +#: forms.py:91 msgid "Object" msgstr "Objet" -#: forms.py:118 forms.py:122 +#: forms.py:97 +msgid "OSM user" +msgstr "Utilisateur OSM" + +#: forms.py:98 models.py:1305 +msgid "Password" +msgstr "Mot de passe" + +#: forms.py:102 +msgid "API" +msgstr "API" + +#: forms.py:105 +#, python-format +msgid "Test API - %s" +msgstr "API de test - %s" + +#: forms.py:107 +#, python-format +msgid "Main API - %s" +msgstr "API principale - %s" + +#: forms.py:136 forms.py:140 msgid "" "For OSM import you must be provide a filter. Select an area and node/way " "filter." msgstr "" -"Pour les imports OSM vous devez fournir un filtre. Sélectionnez une zone " -" et un filtre sur les nœuds/routes." +"Pour les imports OSM vous devez fournir un filtre. Sélectionnez une zone et " +"un filtre sur les nœuds/routes." -#: forms.py:126 +#: forms.py:144 msgid "Shapefiles must be provided in a zipped archive." msgstr "" "Les fichiers Shapefiles doivent être fournis regroupés dans une archive zip." -#: forms.py:130 +#: forms.py:148 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:135 +#: forms.py:153 msgid "You have to set \"source\" or \"source file\"." msgstr "Vous devez spécifier le champ « Source » ou « Fichier source »." -#: forms.py:193 +#: forms.py:211 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:197 +#: forms.py:215 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:207 +#: forms.py:225 msgid "This field is mandatory for the selected categories" msgstr "Ce champ est obligatoire pour les catégories sélectionnées" -#: forms.py:432 +#: forms.py:453 msgid "File" msgstr "Fichier" -#: forms.py:438 +#: forms.py:459 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:443 models.py:51 models.py:106 models.py:127 models.py:140 -#: models.py:155 models.py:272 models.py:580 models.py:623 models.py:666 -#: models.py:782 models.py:1108 models.py:1120 models.py:1293 utils.py:457 -#: templates/admin/managed_modified.html:23 templates/chimere/edit.html:39 -#: templates/chimere/edit_route.html:36 +#: forms.py:464 models.py:51 models.py:106 models.py:127 models.py:140 +#: models.py:155 models.py:272 models.py:579 models.py:622 models.py:665 +#: models.py:781 models.py:1110 models.py:1122 models.py:1295 utils.py:461 +#: templates/admin/chimere/managed_modified.html:23 +#: templates/chimere/edit.html:39 templates/chimere/edit_route.html:36 msgid "Name" msgstr "Nom" -#: forms.py:452 models.py:1157 +#: forms.py:473 models.py:1159 msgid "Area" msgstr "Zone" -#: forms.py:492 +#: forms.py:513 msgid "No area selected." msgstr "Pas de zone sélectionnée." -#: forms.py:499 +#: forms.py:520 #, python-format msgid "The area \"%s\" has the same order, you need to choose another one." msgstr "" "La zone « %s » a le même numéro d'ordre, vous devez un choisir un autre." -#: models.py:52 models.py:128 models.py:156 models.py:283 models.py:584 -#: models.py:1126 models.py:1295 +#: models.py:52 models.py:128 models.py:156 models.py:283 models.py:583 +#: models.py:1128 models.py:1297 msgid "Available" msgstr "Disponible" -#: models.py:53 models.py:1304 +#: models.py:53 models.py:1306 msgid "Date" msgstr "Date" @@ -230,8 +291,8 @@ msgstr "Thème de couleur" msgid "Code" msgstr "Code" -#: models.py:116 models.py:129 models.py:162 models.py:625 models.py:681 -#: models.py:1125 models.py:1282 models.py:1294 +#: models.py:116 models.py:129 models.py:162 models.py:624 models.py:680 +#: models.py:1127 models.py:1284 models.py:1296 msgid "Order" msgstr "Ordre" @@ -243,15 +304,15 @@ msgstr "Couleur" msgid "Category" msgstr "Catégorie" -#: models.py:141 models.py:576 models.py:667 models.py:848 +#: models.py:141 models.py:575 models.py:666 models.py:847 msgid "Image" msgstr "Image" -#: models.py:143 models.py:669 models.py:850 +#: models.py:143 models.py:668 models.py:849 msgid "Height" msgstr "Hauteur" -#: models.py:144 models.py:670 models.py:851 +#: models.py:144 models.py:669 models.py:850 msgid "Width" msgstr "Largeur" @@ -267,7 +328,7 @@ msgstr "Disponible pour soumission" msgid "Marker" msgstr "Point d'intérêt" -#: models.py:164 models.py:844 models.py:861 +#: models.py:164 models.py:843 models.py:860 #: templates/chimere/edit_route.html:27 msgid "Route" msgstr "Trajet" @@ -328,7 +389,7 @@ msgstr "Licence" msgid "Associated subcategories" msgstr "Sous-catégories associées" -#: models.py:248 utils.py:461 +#: models.py:248 utils.py:465 msgid "State" msgstr "État" @@ -400,187 +461,187 @@ msgstr "Modifié depuis le dernier import" msgid "Not to be imported inside OSM" msgstr "À ne pas importer dans OSM" -#: models.py:305 templates/chimere/edit.html:56 +#: models.py:304 templates/chimere/edit.html:56 #: templates/chimere/edit_route.html:52 msgid "Start date" msgstr "Date de début" -#: models.py:306 +#: models.py:305 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:308 templates/chimere/edit.html:62 +#: models.py:307 templates/chimere/edit.html:62 #: templates/chimere/edit_route.html:58 msgid "End date" msgstr "Date de fin" -#: models.py:309 +#: models.py:308 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:355 +#: models.py:354 msgid "Reference marker" msgstr "Point d'intérêt de référence" -#: models.py:356 utils.py:463 +#: models.py:355 utils.py:467 msgid "Localisation" msgstr "Localisation" -#: models.py:358 +#: models.py:357 msgid "Available Date" msgstr "Date de mise en disponibilité" -#: models.py:362 utils.py:462 templates/admin/managed_modified.html:31 +#: models.py:361 utils.py:466 templates/admin/chimere/managed_modified.html:31 #: templates/chimere/edit.html:49 templates/chimere/edit_route.html:46 msgid "Description" msgstr "Description" -#: models.py:424 models.py:1329 +#: models.py:423 models.py:1331 msgid "Point of interest" msgstr "Point d'intérêt" -#: models.py:574 +#: models.py:573 msgid "Audio" msgstr "Audio" -#: models.py:575 +#: models.py:574 msgid "Video" msgstr "Vidéo" -#: models.py:577 +#: models.py:576 msgid "Other" msgstr "Autre" -#: models.py:578 +#: models.py:577 msgid "Media type" msgstr "Type de media" -#: models.py:581 +#: models.py:580 msgid "Mime type" msgstr "Type mime" -#: models.py:583 +#: models.py:582 msgid "Inside an iframe" msgstr "À l'intérieur d'un iframe" -#: models.py:587 +#: models.py:586 msgid "Multimedia type" msgstr "Type de multimedia" -#: models.py:588 +#: models.py:587 msgid "Multimedia types" msgstr "Types de multimedia" -#: models.py:624 +#: models.py:623 msgid "Url" msgstr "Url" -#: models.py:627 models.py:671 +#: models.py:626 models.py:670 msgid "Display inside the description?" msgstr "Apparaît dans la description ?" -#: models.py:632 +#: models.py:631 msgid "Multimedia file" msgstr "Fichier multimedia" -#: models.py:673 +#: models.py:672 msgid "Thumbnail" msgstr "Miniature" -#: models.py:677 +#: models.py:676 msgid "Thumbnail height" msgstr "Hauteur de la miniature" -#: models.py:679 +#: models.py:678 msgid "Thumbnail width" msgstr "Largeur de la miniature" -#: models.py:688 +#: models.py:687 msgid "Picture file" msgstr "Fichier d'image" -#: models.py:783 +#: models.py:782 msgid "Raw file (gpx or kml)" msgstr "Fichier brut (gpx ou kml)" -#: models.py:785 +#: models.py:784 msgid "Simplified file" msgstr "Fichier simplifié" -#: models.py:787 +#: models.py:786 msgid "KML" msgstr "KML" -#: models.py:787 +#: models.py:786 msgid "GPX" msgstr "GPX" -#: models.py:792 +#: models.py:791 msgid "Route file" msgstr "Fichier de trajet" -#: models.py:793 +#: models.py:792 msgid "Route files" msgstr "Fichiers de trajet" -#: models.py:843 +#: models.py:842 msgid "Reference route" msgstr "Trajet de référence" -#: models.py:847 +#: models.py:846 msgid "Associated file" msgstr "Fichier associé" -#: models.py:852 +#: models.py:851 msgid "Has an associated marker" msgstr "Dispose d'un marqueur associé" -#: models.py:1109 +#: models.py:1111 msgid "Layer code" msgstr "Code pour la couche" -#: models.py:1115 +#: models.py:1117 msgid "Layer" msgstr "Couche" -#: models.py:1121 +#: models.py:1123 msgid "Area urn" msgstr "Urn de la zone" -#: models.py:1123 templates/chimere/blocks/welcome.html:3 +#: models.py:1125 templates/chimere/blocks/welcome.html:3 msgid "Welcome message" msgstr "Message d'accueil" -#: models.py:1127 +#: models.py:1129 msgid "Upper left corner" msgstr "Coin en haut à gauche" -#: models.py:1129 +#: models.py:1131 msgid "Lower right corner" msgstr "Coin en bas à droite" -#: models.py:1131 +#: models.py:1133 msgid "Default area" msgstr "Zone par défaut" -#: models.py:1132 +#: models.py:1134 msgid "Only one area is set by default" msgstr "Seule une zone est définie par défaut" -#: models.py:1136 +#: models.py:1138 msgid "Sub-categories checked by default" msgstr "Sous-catégories cochées par défaut" -#: models.py:1138 +#: models.py:1140 msgid "Sub-categories dynamicaly displayed" msgstr "Sous-categories affichées dynamiquement" -#: models.py:1139 +#: models.py:1141 msgid "" "If checked, categories are only displayed in the menu if they are available " "on the current extent." @@ -588,68 +649,64 @@ msgstr "" "Si coché, les catégories sont disponibles sur le menu seulement si elles " "apparaissent sur la zone affichée." -#: models.py:1143 models.py:1298 +#: models.py:1145 models.py:1300 msgid "Restricted to theses sub-categories" msgstr "Restreindre à ces sous-categories" -#: models.py:1144 +#: models.py:1146 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:1146 +#: models.py:1148 msgid "Link to an external CSS" msgstr "Lien vers une feuille de style externe" -#: models.py:1148 +#: models.py:1150 msgid "Restrict to the area extent" msgstr "Restreindre à l'étendue de la zone" -#: models.py:1283 +#: models.py:1285 msgid "Default layer" msgstr "Couche par défaut" -#: models.py:1287 models.py:1288 +#: models.py:1289 models.py:1290 msgid "Layers" msgstr "Couches" -#: models.py:1296 +#: models.py:1298 msgid "Mandatory" msgstr "Obligatoire" -#: models.py:1299 +#: models.py:1301 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:1301 +#: models.py:1303 msgid "Text" msgstr "Texte" -#: models.py:1302 +#: models.py:1304 msgid "Long text" msgstr "Texte long" -#: models.py:1303 -msgid "Password" -msgstr "Mot de passe" - -#: models.py:1309 +#: models.py:1311 msgid "Type" msgstr "Type" -#: models.py:1314 models.py:1331 +#: models.py:1316 models.py:1333 msgid "Property model" msgstr "Modèle de propriété" -#: models.py:1332 +#: models.py:1334 msgid "Value" msgstr "Valeur" -#: models.py:1336 +#: models.py:1338 msgid "Property" msgstr "Propriété" @@ -719,48 +776,53 @@ msgstr "Mauvais fichier XML" msgid "Error while reading the data source." msgstr "Erreur lors de la lecture de la source." -#: utils.py:339 +#: utils.py:322 +#, 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:343 msgid "Type of geographic item of this shapefile is not managed by Chimère." msgstr "" "Les types des éléments géographiques de ce fichier Shapefile ne sont pas " "gérés par Chimère." -#: utils.py:359 +#: utils.py:363 msgid "Bad Shapefile" msgstr "Mauvais fichier Shapefile" -#: utils.py:401 +#: utils.py:405 msgid "Could not create file!" msgstr "Ne peut pas créer le fichier !" -#: utils.py:412 +#: utils.py:416 msgid "Failed to create field" msgstr "Ne peut pas créer un champ" -#: utils.py:458 templates/admin/managed_modified.html:25 +#: utils.py:462 templates/admin/chimere/managed_modified.html:25 #: templates/chimere/edit.html:44 templates/chimere/edit_route.html:41 #: templates/chimere/main_map.html:13 #: templates/chimere/main_map_simple.html:10 msgid "Categories" msgstr "Catégories" -#: utils.py:491 +#: utils.py:495 msgid "Invalid CSV format" msgstr "Fichier CSV non valide" -#: utils.py:566 +#: utils.py:570 msgid "RSS feed is not well formed" msgstr "Flux RSS non valide" -#: utils.py:636 +#: utils.py:645 msgid "Nothing to import" msgstr "Rien à importer" -#: utils.py:724 +#: utils.py:733 msgid "New items imported - validate them before exporting" msgstr "Nouveaux éléments importés - valider ceux-ci avant d'exporter" -#: utils.py:726 +#: utils.py:735 msgid "" "There are items from a former import not yet validated - validate them " "before exporting" @@ -768,15 +830,19 @@ msgstr "" "Il y a des éléments d'un import précédent pas encore validé - Validez les " "avant d'exporter" -#: utils.py:738 +#: utils.py:747 +msgid "Bad params - programming error" +msgstr "Mauvais paramètres - erreur de programmation" + +#: utils.py:757 msgid "Bad param" msgstr "Mauvais paramètre" -#: utils.py:753 +#: utils.py:772 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:755 +#: utils.py:774 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" @@ -785,19 +851,19 @@ msgstr "" "vouloir lancer la requête sur la planète entière fixez la « bounding box » " "à -180,-90,180,90" -#: views.py:236 +#: views.py:238 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:321 +#: views.py:323 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:431 +#: views.py:433 msgid "Comments/request on the map" msgstr "Commentaires/requètes sur la carte" -#: views.py:434 +#: views.py:436 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." @@ -806,48 +872,48 @@ msgstr "" "laissé votre courriel vous serez peut-être contacté bientôt pour plus de " "détails." -#: views.py:438 +#: views.py:440 msgid "Temporary error. Renew your message later." msgstr "Erreur temporaire. Réenvoyez votre message plus tard." -#: views.py:572 +#: views.py:576 msgid "No category available in this area." msgstr "Pas de catégorie disponible sur cette zone." -#: views.py:680 +#: views.py:684 msgid "Incorrect choice in the list" msgstr "Choix incorrect dans la liste" -#: widgets.py:217 +#: widgets.py:216 msgid "Latitude" msgstr "Latitude" -#: widgets.py:217 +#: widgets.py:216 msgid "Longitude" msgstr "Longitude" -#: widgets.py:242 +#: widgets.py:240 msgid "Invalid point" msgstr "Point invalide" -#: widgets.py:294 +#: widgets.py:292 msgid "Creation mode" msgstr "Mode création" -#: widgets.py:295 +#: widgets.py:293 msgid "To start drawing the route click on the toggle button: \"Draw\"." msgstr "" "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:297 +#: widgets.py:295 msgid "Then click on the map to begin the drawing." msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:298 +#: widgets.py:296 msgid "You can add points by clicking again." msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:299 +#: widgets.py:297 msgid "" "To finish the drawing double click. When the drawing is finished you can " "edit it." @@ -855,7 +921,7 @@ msgstr "" "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez " "toujours l'éditer." -#: widgets.py:301 +#: widgets.py:299 msgid "" "While creating to undo a drawing click again on the toggle button \"Stop " "drawing\"." @@ -863,17 +929,17 @@ msgstr "" "En mode création vous pouvez annuler un tracé en appuyant sur le bouton " "« Arrêter le tracé »." -#: widgets.py:306 +#: widgets.py:304 msgid "Modification mode" msgstr "Mode modification" -#: widgets.py:307 +#: widgets.py:305 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:308 +#: widgets.py:306 msgid "" "To delete a point move the mouse cursor over it and press the \"d\" or \"Del" "\" key." @@ -881,7 +947,7 @@ msgstr "" "Pour supprimer un point, mettez le curseur de la souris sur celui-ci et " "appuyez sur le touche « d » ou « Suppr »." -#: widgets.py:310 +#: widgets.py:308 msgid "" "To add a point click in the middle of a segment and drag the new point to " "the desired position" @@ -890,94 +956,93 @@ msgstr "" "maintenez le bouton appuyé et déplacez le nouveau point à la position " "désirée." -#: widgets.py:317 +#: widgets.py:315 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:320 +#: widgets.py:318 msgid "Upload a route file (GPX or KML)" msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:321 +#: widgets.py:319 msgid "or" msgstr "ou" -#: widgets.py:326 +#: widgets.py:324 msgid "Start \"hand\" drawing" msgstr "Commencer le tracé manuellement" -#: widgets.py:349 +#: widgets.py:347 msgid "Move on the map" msgstr "Se déplacer" -#: widgets.py:349 +#: widgets.py:347 msgid "Draw" msgstr "Tracer" -#: widgets.py:439 +#: widgets.py:437 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:496 +#: widgets.py:494 msgid "Type:" msgstr "Type :" -#: widgets.py:496 +#: widgets.py:494 msgid "Node" msgstr "Nœud" -#: widgets.py:497 +#: widgets.py:495 msgid "Way" msgstr "Route" -#: widgets.py:508 +#: widgets.py:506 msgid "" "Enter an OSM \"tag=value\" string such as \"amenity=pub\". A list of common " "tag is available here." msgstr "" "Entrez une chaîne OSM de type \"clé=valeur\" telle que \"amenity=pub\". Une " -"liste des clés est disponible " -"" -"ici." +"liste des clés est disponible ici." -#: widgets.py:515 +#: widgets.py:513 msgid "Tag:" msgstr "Clé/valeur :" -#: widgets.py:519 +#: widgets.py:517 msgid "You have to select an area." msgstr "Vous devez sélectionner une zone." -#: widgets.py:521 +#: widgets.py:519 msgid "You have to select a type." msgstr "Vous devez sélectionner un type." -#: widgets.py:523 +#: widgets.py:521 msgid "You have to insert a filter tag." msgstr "Vous devez saisir une clé=valeur." -#: widgets.py:525 +#: widgets.py:523 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:528 +#: widgets.py:526 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:536 +#: widgets.py:534 msgid "Refresh" msgstr "Rafraîchir" -#: widgets.py:599 +#: widgets.py:600 msgid "Select..." msgstr "Sélectionner..." @@ -993,7 +1058,7 @@ msgstr "Erreur interne du serveur" msgid "Chimère administration" msgstr "Administration de Chimère" -#: templates/admin/managed_modified.html:11 +#: templates/admin/chimere/managed_modified.html:11 msgid "" "Be careful: after validation, the modified item will be deleted. There is no " "roll-back." @@ -1001,26 +1066,65 @@ msgstr "" "Attention: après validation, l'élément modifié sera supprimé. Il n'y a pas " "d'annulation possible." -#: templates/admin/managed_modified.html:20 +#: templates/admin/chimere/managed_modified.html:20 msgid "Reference" msgstr "Référence" -#: templates/admin/managed_modified.html:20 +#: templates/admin/chimere/managed_modified.html:20 msgid "Modified item" msgstr "Élément modifié" -#: templates/admin/managed_modified.html:20 +#: templates/admin/chimere/managed_modified.html:20 msgid "Accept modification" msgstr "Accepter la modification" -#: templates/admin/managed_modified.html:30 +#: templates/admin/chimere/managed_modified.html:30 msgid "Emplacement" msgstr "Emplacement" -#: templates/admin/managed_modified.html:43 +#: templates/admin/chimere/managed_modified.html:43 +#: templates/admin/chimere/osm_export.html:27 msgid "Back to list" msgstr "Retourner à la liste" +#: templates/admin/chimere/osm_export.html:21 +msgid "Only points of interest are managed by this export." +msgstr "Seuls les points d'intérêt sont gérés par cet export." + +#: templates/admin/chimere/osm_export.html:23 +msgid "" +"Before exporting to OSM an import is done to verify that no modification has " +"been made. All pending imported item have to be validated before export." +msgstr "" +"Préalablement à tout export vers OSM, un import est réalisé pour vérifier " +"qu'aucune modification n'a été faite sur les données nous concernant. Par " +"ailleurs toutes les données importées doivent être traitées avant l'export." + +#: templates/admin/chimere/osm_export.html:25 +msgid "" +"Ensure that all the data exported to OSM have an appropriate license. You " +"can exclude some points of interest by checking the checkbox \"Not to be " +"imported in OSM\" in the point of interest form. If you are not sure " +"of what you are doing: DON'T EXPORT TO OSM!" +msgstr "" +"Vérifiez que toutes les données à exporter vers OSM ont une licence " +"compatible. Vous pouvez exclure certains points d'intérêt en cochant la " +"case « Ne pas importer dans OSM » sur le formulaire de point d'intérêt. " +"Si vous n'êtes pas sûr de ce que vous êtes entrain de faire : " +"N'IMPORTEZ PAS DANS OSM !" + +#: templates/admin/chimere/osm_export.html:28 +msgid "Export to OSM" +msgstr "Exporter vers OSM" + +#: templates/admin/chimere/propertymodel/change_form.html:5 +msgid "" +"After add/modification of property models you'll have to reload the " +"webserver." +msgstr "" +"Après ajout/modification de modèle de propriété vous aurez à recharger le " +"serveur web." + #: templates/chimere/base.html:11 msgid "You must enable JavaScript in your browser to display Chimère." msgstr "" @@ -1130,6 +1234,10 @@ msgstr "Proposez" msgid "Add/modify a route" msgstr "Ajout ou modifier un trajet" +#: templates/chimere/main_map.html:27 +msgid "Simple map" +msgstr "Carte simple" + #: templates/chimere/upload_file.html:13 msgid "Thank you for your submission!" msgstr "Merci pour votre proposition !" @@ -1160,7 +1268,7 @@ msgstr "Zoomer sur" msgid "Tell me more..." msgstr "En savoir plus..." -#: templates/chimere/blocks/categories.html:27 +#: templates/chimere/blocks/categories.html:28 msgid "Display markers and routes waiting for validation" msgstr "" "Afficher les points remarquables et les trajets en attente de validation" @@ -1173,6 +1281,10 @@ msgstr "Ce site utilise Chimère" msgid "Map" msgstr "Carte" +#: templates/chimere/blocks/inline_formset.html:22 +msgid "Add" +msgstr "Ajouter" + #: templates/chimere/blocks/map.html:9 msgid "Loading of the map in progress" msgstr "Chargement de la carte en cours" -- cgit v1.2.3 From c978532f9ac828a812acb6fbb12da978eb55dc28 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 29 Aug 2012 19:29:48 +0200 Subject: Manage auto-detection of multimedia type by extension - improvement on alternate multimedia widget Conflicts: chimere/admin.py chimere/forms.py chimere/models.py chimere/templates/chimere/blocks/alternate_multimedia.html chimere/templatetags/chimere_tags.py --- chimere/admin.py | 6 + chimere/fixtures/initial_data.json | 91 ++++++++++++++ chimere/forms.py | 31 ++++- chimere/models.py | 15 ++- .../chimere/blocks/alternate_multimedia.html | 135 +++++++++++++++++++++ chimere/templatetags/chimere_tags.py | 8 +- 6 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 chimere/templates/chimere/blocks/alternate_multimedia.html (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 1d3dcbe..147314e 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -387,6 +387,12 @@ class ColorThemeAdmin(admin.ModelAdmin): class IconAdmin(admin.ModelAdmin): exclude = ['height', 'width'] +class PropertyModelChoiceInline(admin.TabularInline): + model = PropertyModelChoice + extra = 1 +class PropertyModelAdmin(admin.ModelAdmin): + inlines = [PropertyModelChoiceInline] + # register of differents database fields admin.site.register(News, NewsAdmin) admin.site.register(Category, CategoryAdmin) diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json index 248349d..883e499 100644 --- a/chimere/fixtures/initial_data.json +++ b/chimere/fixtures/initial_data.json @@ -164,6 +164,97 @@ "mime_type": "" } }, + { + "pk": 16, + "model": "chimere.multimediatype", + "fields": { + "available": false, + "media_type": "O", + "iframe": false, + "name": "auto", + "mime_type": "" + } + }, + { + "pk": 1, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 7, + "name": "mkv" + } + }, + { + "pk": 3, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 2, + "name": "mp3" + } + }, + { + "pk": 4, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 3, + "name": "ogg" + } + }, + { + "pk": 5, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 5, + "name": "mp4" + } + }, + { + "pk": 6, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 4, + "name": "mpg" + } + }, + { + "pk": 7, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 4, + "name": "mpeg" + } + }, + { + "pk": 8, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 8, + "name": "avi" + } + }, + { + "pk": 9, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 6, + "name": "ogm" + } + }, + { + "pk": 10, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 6, + "name": "ogv" + } + }, + { + "pk": 11, + "model": "chimere.multimediaextension", + "fields": { + "multimedia_type": 13, + "name": "webm" + } + } { "pk": 1, "model": "chimere.layer", diff --git a/chimere/forms.py b/chimere/forms.py index efea3dd..813f0f8 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -32,8 +32,9 @@ from django.contrib.admin.widgets import AdminDateWidget from django.core.mail import EmailMessage, BadHeaderError from chimere.models import Marker, Route, PropertyModel, Property, Area,\ - News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ - PictureFile, Importer, IMPORTER_CHOICES + News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ + PictureFile, Importer, IMPORTER_CHOICES, PropertyModelChoice, IFRAME_LINKS,\ + MultimediaExtension from chimere.widgets import AreaField, PointField, TextareaWidget, \ ImportFiltrWidget, TextareaAdminWidget, DatePickerWidget, \ ImporterChoicesWidget, RE_XAPI @@ -425,7 +426,31 @@ class MultimediaFileForm(BaseFileForm): def __init__(self, *args, **kwargs): super(MultimediaFileForm, self).__init__(*args, **kwargs) self.fields['multimedia_type'].widget.choices = \ - MultimediaType.get_tuples() + MultimediaType.get_tuples() + + def clean(self): + if not self.cleaned_data.get('multimedia_type') or\ + not self.cleaned_data.get('url'): + return self.cleaned_data + if self.cleaned_data['multimedia_type'].name != 'auto': + return self.cleaned_data + url = self.cleaned_data['url'] + for mm_type in IFRAME_LINKS: + res, embeded_url = IFRAME_LINKS[mm_type] + if [r for r in res if r.search(url)]: + multimedia_type = MultimediaType.objects.get( + name__iexact=mm_type) + self.cleaned_data['multimedia_type'] = multimedia_type + return self.cleaned_data + ext = url.split(".")[-1] + q = MultimediaExtension.objects.filter(name__iendswith=ext) + if q.count(): + self.cleaned_data['multimedia_type'] = q.all()[0].multimedia_type + else: + # default to an iframe + self.cleaned_data['multimedia_type'] = \ + MultimediaType.objects.filter(name__iexact='iframe').all()[0] + return self.cleaned_data MultimediaFileFormSet = formset_factory(MultimediaFileForm, can_delete=True) diff --git a/chimere/models.py b/chimere/models.py index 03b5dce..6b7ffb9 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -607,7 +607,7 @@ IFRAME_LINKS = { 'youtube':((re.compile(r'youtube.com\/watch\?v=([A-Za-z0-9_-]*)'), re.compile(r'youtu.be\/([A-Za-z0-9_-]*)'), re.compile(r'youtube.com\/embed\/([A-Za-z0-9_-]*)')), - "http://www.youtube.com/embed/%s"), + "http://www.youtube.com/embed/%s"), 'dailymotion':( (re.compile(r'dailymotion.com/video/([A-Za-z0-9]*)_[A-Za-z0-9_-]*'), re.compile(r'dailymotion.com/embed/video/([A-Za-z0-9]*)'), @@ -618,6 +618,19 @@ IFRAME_LINKS = { "http://player.vimeo.com/video/%s") } +class MultimediaExtension(models.Model): + name = models.CharField(_(u"Extension name"), max_length=6) + multimedia_type = models.ForeignKey(MultimediaType, + verbose_name=_(u"Associated multimedia type"), + related_name='extensions') + + class Meta: + verbose_name = _(u"Multimedia extension") + verbose_name_plural = _(u"Multimedia extensions") + + def __unicode__(self): + return self.name + class MultimediaFile(models.Model): name = models.CharField(_(u"Name"), max_length=150) url = models.URLField(_(u"Url"), max_length=200) diff --git a/chimere/templates/chimere/blocks/alternate_multimedia.html b/chimere/templates/chimere/blocks/alternate_multimedia.html new file mode 100644 index 0000000..0662750 --- /dev/null +++ b/chimere/templates/chimere/blocks/alternate_multimedia.html @@ -0,0 +1,135 @@ +{% load i18n %} +
+ {% for formset in formsets %} + {{ formset.management_form }} + {% if formset.errors %}
+ {% for dict in formset.errors %} + {% for error in dict.values %} + {{ error }} + {% endfor %} + {% endfor %} +
{% endif %} + {% endfor %} +
    + {% for formset in formsets %} + {% for frm in formset%} + {% if not forloop.last %} +
  • + {%if forloop.first %}{% for hidden in frm.hidden_fields %} + {{ hidden }} + {% endfor %}{% endif %} + {% for field in frm.visible_fields %} + {% if field.name == "name" %} + {{ field.field.value }} + {% endif %} + + {% endfor %} +
  • + {% endif %} + {% endfor %} + {% endfor %} +
+ +
+
+
{% trans "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu luctus ipsum. Donec vel urna a turpis consectetur consectetur. Vestibulum ut enim vel odio porta vulputate." %} +
+
+ + +
+
+ {% trans "Image" %} + {% trans "Audio, video, other..." %} +
+
+ +

{% trans "Or" %}

+ +
+ +
+ + diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 7753bc0..2b806ca 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse from django.db.models import Q, Count from django.template.loader import render_to_string -from chimere.models import Marker, Area, News, SubCategory +from chimere.models import Marker, Area, News, SubCategory, MultimediaType from chimere.widgets import get_map_layers log = getLogger(__name__) @@ -203,6 +203,12 @@ def multimedia_render(context, multimedia_file): context['multimedia_item'] = multimedia_file return context +@register.inclusion_tag('chimere/blocks/alternate_multimedia.html') +def alternate_multimedia(formset_multi, formset_picture): + return {'formsets':[formset_multi, formset_picture], + "STATIC_URL": settings.STATIC_URL, + 'auto_type_id':MultimediaType.objects.get(name='auto').pk} + @register.simple_tag def get_tinyfied_url(marker, area_name=''): if not marker or not hasattr(marker, 'get_absolute_url'): -- cgit v1.2.3 From 655238608edfa82a37e86294c9a4960df3bf9af7 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 26 Nov 2012 17:27:30 +0100 Subject: Fix auto-recognition of multimedia files --- chimere/admin.py | 6 - chimere/fixtures/initial_data.json | 2 +- chimere/forms.py | 34 +-- ...ion__chg_field_multimediafile_multimedia_typ.py | 252 +++++++++++++++++++++ chimere/models.py | 48 ++-- 5 files changed, 293 insertions(+), 49 deletions(-) create mode 100644 chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py (limited to 'chimere/admin.py') diff --git a/chimere/admin.py b/chimere/admin.py index 147314e..1d3dcbe 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -387,12 +387,6 @@ class ColorThemeAdmin(admin.ModelAdmin): class IconAdmin(admin.ModelAdmin): exclude = ['height', 'width'] -class PropertyModelChoiceInline(admin.TabularInline): - model = PropertyModelChoice - extra = 1 -class PropertyModelAdmin(admin.ModelAdmin): - inlines = [PropertyModelChoiceInline] - # register of differents database fields admin.site.register(News, NewsAdmin) admin.site.register(Category, CategoryAdmin) diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json index 883e499..41df8cf 100644 --- a/chimere/fixtures/initial_data.json +++ b/chimere/fixtures/initial_data.json @@ -254,7 +254,7 @@ "multimedia_type": 13, "name": "webm" } - } + }, { "pk": 1, "model": "chimere.layer", diff --git a/chimere/forms.py b/chimere/forms.py index 813f0f8..eb64a04 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -33,8 +33,7 @@ from django.core.mail import EmailMessage, BadHeaderError from chimere.models import Marker, Route, PropertyModel, Property, Area,\ News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \ - PictureFile, Importer, IMPORTER_CHOICES, PropertyModelChoice, IFRAME_LINKS,\ - MultimediaExtension + PictureFile, Importer, IMPORTER_CHOICES, IFRAME_LINKS, MultimediaExtension from chimere.widgets import AreaField, PointField, TextareaWidget, \ ImportFiltrWidget, TextareaAdminWidget, DatePickerWidget, \ ImporterChoicesWidget, RE_XAPI @@ -414,6 +413,11 @@ class MultimediaFileAdminForm(forms.ModelForm): '%schimere/js/menu-sort.js' % settings.STATIC_URL, ] + def __init__(self, *args, **kwargs): + super(MultimediaFileAdminForm, self).__init__(*args, **kwargs) + self.fields['multimedia_type'].widget.choices = \ + MultimediaType.get_tuples() + class MultimediaFileForm(BaseFileForm): """ Form for a multimedia file @@ -427,30 +431,8 @@ class MultimediaFileForm(BaseFileForm): super(MultimediaFileForm, self).__init__(*args, **kwargs) self.fields['multimedia_type'].widget.choices = \ MultimediaType.get_tuples() - - def clean(self): - if not self.cleaned_data.get('multimedia_type') or\ - not self.cleaned_data.get('url'): - return self.cleaned_data - if self.cleaned_data['multimedia_type'].name != 'auto': - return self.cleaned_data - url = self.cleaned_data['url'] - for mm_type in IFRAME_LINKS: - res, embeded_url = IFRAME_LINKS[mm_type] - if [r for r in res if r.search(url)]: - multimedia_type = MultimediaType.objects.get( - name__iexact=mm_type) - self.cleaned_data['multimedia_type'] = multimedia_type - return self.cleaned_data - ext = url.split(".")[-1] - q = MultimediaExtension.objects.filter(name__iendswith=ext) - if q.count(): - self.cleaned_data['multimedia_type'] = q.all()[0].multimedia_type - else: - # default to an iframe - self.cleaned_data['multimedia_type'] = \ - MultimediaType.objects.filter(name__iexact='iframe').all()[0] - return self.cleaned_data + # this can be auto detect + self.fields['multimedia_type'].required = False MultimediaFileFormSet = formset_factory(MultimediaFileForm, can_delete=True) diff --git a/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py b/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py new file mode 100644 index 0000000..0b26a27 --- /dev/null +++ b/chimere/migrations/0039_auto__add_multimediaextension__chg_field_multimediafile_multimedia_typ.py @@ -0,0 +1,252 @@ +# -*- 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 model 'MultimediaExtension' + db.create_table('chimere_multimediaextension', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=6)), + ('multimedia_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='extensions', to=orm['chimere.MultimediaType'])), + )) + db.send_create_signal('chimere', ['MultimediaExtension']) + + + # Changing field 'MultimediaFile.multimedia_type' + db.alter_column('chimere_multimediafile', 'multimedia_type_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['chimere.MultimediaType'], null=True)) + + def backwards(self, orm): + # Deleting model 'MultimediaExtension' + db.delete_table('chimere_multimediaextension') + + + # User chose to not deal with backwards NULL issues for 'MultimediaFile.multimedia_type' + raise RuntimeError("Cannot reverse this migration. 'MultimediaFile.multimedia_type' and its values cannot be restored.") + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'default': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'default_subcategories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False', 'blank': 'True'}), + 'dynamic_categories': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'external_css': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layers': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'through': "orm['chimere.AreaLayers']", 'to': "orm['chimere.Layer']"}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'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'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'default_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'origin': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'source_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'zipped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'chimere.layer': { + 'Meta': {'object_name': 'Layer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer_code': ('django.db.models.fields.TextField', [], {'max_length': '300'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'modified_since_import': ('django.db.models.fields.BooleanField', [], {'default': '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', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.picturefile': { + 'Meta': {'object_name': 'PictureFile'}, + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pictures'", 'to': "orm['chimere.Marker']"}), + 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'thumbnailfile': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'thumbnailfile_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'thumbnailfile_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.property': { + 'Meta': {'object_name': 'Property'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Marker']"}), + 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.PropertyModel']"}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'chimere.propertymodel': { + 'Meta': {'ordering': "('order',)", 'object_name': 'PropertyModel'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mandatory': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'subcategories': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'properties'", 'blank': 'True', 'to': "orm['chimere.SubCategory']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '1'}) + }, + 'chimere.route': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Route'}, + 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.RouteFile']", 'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + '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'}), + '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'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subcategories'", 'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1000'}), + 'submission': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] \ No newline at end of file diff --git a/chimere/models.py b/chimere/models.py index 6b7ffb9..63529ee 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -593,7 +593,7 @@ class MultimediaType(models.Model): def get_tuples(cls): vals = cls.objects.filter(available=True).order_by('media_type', 'name') - tuples, c_tpe = [('', '--')], None + tuples, c_tpe = [('', _("Automatic recognition"))], None media_type_dct = dict(cls.MEDIA_TYPES) for tpe, pk, name in [(media_type_dct[v.media_type], v.pk, v.name) for v in vals]: @@ -635,7 +635,7 @@ class MultimediaFile(models.Model): name = models.CharField(_(u"Name"), max_length=150) url = models.URLField(_(u"Url"), max_length=200) order = models.IntegerField(_(u"Order"), default=1) - multimedia_type = models.ForeignKey(MultimediaType) + multimedia_type = models.ForeignKey(MultimediaType, blank=True, null=True) miniature = models.BooleanField(_(u"Display inside the description?"), default=settings.CHIMERE_MINIATURE_BY_DEFAULT) marker = models.ForeignKey(Marker, related_name='multimedia_files') @@ -647,24 +647,40 @@ class MultimediaFile(models.Model): def __unicode__(self): return self.name or u"" - def save(self, *args, **kwargs): - # manage iframe of video providers - if self.multimedia_type.name.lower() in IFRAME_LINKS: - regexps, lnk = IFRAME_LINKS[self.multimedia_type.name.lower()] - key = None - for regexp in regexps: - key = regexp.findall(self.url) - if key: - key = key[0] - break - if key: - self.url = lnk % key - super(MultimediaFile, self).save(*args, **kwargs) - def multimediafile_post_save(sender, **kwargs): if not kwargs['instance'] or not kwargs['created']: return multimediafile = kwargs['instance'] + # auto recognition of file types + if not multimediafile.multimedia_type: + url = multimediafile.url + for mm_type in IFRAME_LINKS: + res, embeded_url = IFRAME_LINKS[mm_type] + if [r for r in res if r.search(url)]: + multimedia_type = MultimediaType.objects.get( + name__iexact=mm_type) + multimediafile.multimedia_type = multimedia_type + if not multimediafile.multimedia_type: + ext = url.split(".")[-1] + q = MultimediaExtension.objects.filter(name__iendswith=ext) + if q.count(): + multimediafile.multimedia_type = q.all()[0].multimedia_type + else: + # default to an iframe + multimediafile.multimedia_type = \ + MultimediaType.objects.filter(name__iexact='iframe').all()[0] + # manage iframe of video providers + if multimediafile.multimedia_type.name.lower() in IFRAME_LINKS: + regexps, lnk = IFRAME_LINKS[multimediafile.multimedia_type.name.lower()] + key = None + for regexp in regexps: + key = regexp.findall(multimediafile.url) + if key: + key = key[0] + break + if key: + multimediafile.url = lnk % key + mfs = MultimediaFile.objects.filter(marker=multimediafile.marker).exclude( pk=multimediafile.pk).order_by('order') for idx, mf in enumerate(mfs.all()): -- cgit v1.2.3