Added Geo and Years tables
authorveltr
Tue, 20 Aug 2013 18:54:03 +0200
changeset 96 eca960eac58b
parent 95 b0ea2dcff0ce
child 97 e7c675c54816
Added Geo and Years tables
src/jocondelab/management/commands/import_dbpedia_geo_years.py
src/jocondelab/migrations/0006_auto__add_geo__add_years.py
src/jocondelab/models/__init__.py
src/jocondelab/models/data.py
src/jocondelab/static/jocondelab/css/front-common.css
src/jocondelab/static/jocondelab/css/front-search.css
src/jocondelab/static/jocondelab/img/search-icon.png
src/jocondelab/static/jocondelab/js/front-common.js
src/jocondelab/templates/jocondelab/front_base.html
src/jocondelab/templates/jocondelab/front_search.html
src/jocondelab/urls.py
src/jocondelab/views/ajax.py
src/jocondelab/views/front_office.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/management/commands/import_dbpedia_geo_years.py	Tue Aug 20 18:54:03 2013 +0200
@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Aug 08, 2013
+
+@author: rvelt
+'''
+
+from core.utils import show_progress
+from core.wp_utils import get_dbpedia_lang
+from django.conf import settings
+from django.core.management.base import NoArgsCommand
+from core.models import Term
+from jocondelab.models import (DbpediaYears, DbpediaGeo)
+from django.db import transaction
+import re
+from SPARQLWrapper import SPARQLWrapper2
+from optparse import make_option
+import traceback
+import sys
+import math
+from django.utils.http import urlunquote
+
+class Command(NoArgsCommand):
+    
+    help = "Import tag metadata from dbpedia"
+    
+    
+    def handle_noargs(self, **options):
+        
+        endpoints = {}
+        qs = Term.objects.exclude(dbpedia_uri=None).order_by('-nb_notice')
+        count = qs.count()
+        writer = None
+        
+        yearre = re.compile("^-?\d+")
+        sylbls = [  "birthdate", "startyear" ]
+        eylbls = [ "deathdate", "endyear" ]
+        
+        for i,obj in enumerate(qs):
+            writer = show_progress(i+1, count, obj.dbpedia_uri, 50, writer)
+            dbp_lang = get_dbpedia_lang(obj.dbpedia_uri)
+            if dbp_lang is None:
+                print("Lang unknown for %s, continue" % obj.dbpedia_uri)
+                continue
+            endpoint = endpoints.get(dbp_lang, None)
+            if endpoint is None:
+                dbpedia_sparql_url = settings.WIKIPEDIA_URLS.get(dbp_lang,{}).get('dbpedia_sparql_url', None)
+                if dbpedia_sparql_url is None:
+                    print("Lang unknown for %s, continue" % obj.dbpedia_uri)
+                    continue
+                endpoint = endpoints.setdefault(dbp_lang, SPARQLWrapper2(dbpedia_sparql_url))
+            try:
+                with transaction.commit_on_success():
+                    uri = urlunquote(obj.dbpedia_uri)
+                    sparql = u"""
+    select distinct * where {
+        OPTIONAL {
+          <%s> dbpedia-owl:activeYearsStartYear ?startyear .
+        }
+        OPTIONAL {
+          <%s> dbpedia-owl:activeYearsEndYear ?endyear .
+        }
+        OPTIONAL {
+          <%s> dbpedia-owl:birthDate ?birthdate .
+        }
+        OPTIONAL {
+          <%s> dbpedia-owl:deathDate ?deathdate .
+        }
+        OPTIONAL {
+          <%s> geo:lat ?latitude .
+          <%s> geo:long ?longitude .
+        }
+    }
+                    """%(6*(uri,))
+                    endpoint.setQuery(sparql)
+                    results = endpoint.query()
+                    
+                    if len(results.bindings):
+                        binding = results.bindings[0]
+                        syv = None
+                        eyv = None
+                        for lbl in sylbls:
+                            if lbl in binding:
+                                syv = yearre.findall(binding[lbl].value)
+                                break
+                        for lbl in eylbls:
+                            if lbl in binding:
+                                eyv = yearre.findall(binding[lbl].value)
+                                break
+                        if syv and eyv:
+                            sy = syv[0]
+                            ey = eyv[0]
+                            dbyr, created = DbpediaYears.objects.get_or_create(term = obj, defaults={'start_year': sy, 'end_year': ey})
+                            if not created:
+                                dbyr.start_year = sy
+                                dbyr.end_year = ey
+                                dbyr.save()
+                        
+                        lat = float(binding["latitude"].value) if "latitude" in binding else None
+                        lng = float(binding["longitude"].value) if "longitude" in binding else None
+                        
+                        if (lat is not None) and (not math.isnan(lat)) and (lng is not None) and (not math.isnan(lng)):
+                            dbgeo, created = DbpediaGeo.objects.get_or_create(term = obj, defaults={'latitude': lat, 'longitude': lng})
+                            if not created:
+                                dbgeo.latitude = lat
+                                dbgeo.longitude = lng
+                                dbgeo.save()
+                        
+            except Exception as e:
+                print "\nError processing resource %s : %s" %(obj.dbpedia_uri,unicode(e))
+                traceback.print_exception(type(e), e, sys.exc_info()[2])
+                
+        
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/migrations/0006_auto__add_geo__add_years.py	Tue Aug 20 18:54:03 2013 +0200
@@ -0,0 +1,274 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'DbpediaYears'
+        db.create_table(u'jocondelab_dbpediayears', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('term', self.gf('django.db.models.fields.related.ForeignKey')(related_name='years', unique=True, to=orm['core.Term'])),
+            ('start_year', self.gf('django.db.models.fields.IntegerField')(db_index=True)),
+            ('end_year', self.gf('django.db.models.fields.IntegerField')(db_index=True)),
+        ))
+        db.send_create_signal('jocondelab', ['DbpediaYears'])
+
+        # Adding model 'DbpediaGeo'
+        db.create_table(u'jocondelab_dbpediageo', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('term', self.gf('django.db.models.fields.related.ForeignKey')(related_name='geo', unique=True, to=orm['core.Term'])),
+            ('latitude', self.gf('django.db.models.fields.FloatField')(db_index=True)),
+            ('longitude', self.gf('django.db.models.fields.FloatField')(db_index=True)),
+        ))
+        db.send_create_signal('jocondelab', ['DbpediaGeo'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'DbpediaYears'
+        db.delete_table(u'jocondelab_dbpediayears')
+
+        # Deleting model 'DbpediaGeo'
+        db.delete_table(u'jocondelab_dbpediageo')
+
+
+    models = {
+        u'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        u'auth.permission': {
+            'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        u'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'core.autrnoticeterm': {
+            'Meta': {'object_name': 'AutrNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.domnnoticeterm': {
+            'Meta': {'object_name': 'DomnNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.ecolnoticeterm': {
+            'Meta': {'object_name': 'EcolNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.epoqnoticeterm': {
+            'Meta': {'object_name': 'EpoqNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.lieuxnoticeterm': {
+            'Meta': {'object_name': 'LieuxNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.notice': {
+            'Meta': {'object_name': 'Notice'},
+            'adpt': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'appl': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'aptn': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'attr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'autr': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'autr_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'autr+'", 'symmetrical': 'False', 'through': "orm['core.AutrNoticeTerm']", 'to': "orm['core.Term']"}),
+            'bibl': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'comm': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'contact': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'coor': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'copy': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'dacq': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'data': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'dation': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'ddpt': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'decv': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'deno': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'depo': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'desc': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'desy': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'dims': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'dmaj': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'dmis': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'domn': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'domn_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'domn+'", 'symmetrical': 'False', 'through': "orm['core.DomnNoticeTerm']", 'to': "orm['core.Term']"}),
+            'drep': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'ecol': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'ecol_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ecol+'", 'symmetrical': 'False', 'through': "orm['core.EcolNoticeTerm']", 'to': "orm['core.Term']"}),
+            'epoq': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'epoq_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'epoq+'", 'symmetrical': 'False', 'through': "orm['core.EpoqNoticeTerm']", 'to': "orm['core.Term']"}),
+            'etat': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'expo': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'gene': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'geohi': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'hist': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'insc': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'inv': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'labo': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'lieux': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'lieux_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'lieux+'", 'symmetrical': 'False', 'through': "orm['core.LieuxNoticeTerm']", 'to': "orm['core.Term']"}),
+            'loca': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'loca2': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'mill': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'milu': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'mosa': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'msgcom': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'museo': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'nsda': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'onom': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'paut': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'pdat': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'pdec': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'peoc': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'peri': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'peri_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'peri+'", 'symmetrical': 'False', 'through': "orm['core.PeriNoticeTerm']", 'to': "orm['core.Term']"}),
+            'peru': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'phot': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'pins': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'plieux': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'prep': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'puti': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'reda': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'ref': ('django.db.models.fields.CharField', [], {'max_length': '20', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'refim': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'repr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'repr_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'repr+'", 'symmetrical': 'False', 'through': "orm['core.ReprNoticeTerm']", 'to': "orm['core.Term']"}),
+            'srep': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'srep_terms': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'srep+'", 'symmetrical': 'False', 'through': "orm['core.SrepNoticeTerm']", 'to': "orm['core.Term']"}),
+            'stat': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'tech': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'tico': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'titr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'util': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'video': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'www': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'core.noticeterm': {
+            'Meta': {'object_name': 'NoticeTerm'},
+            'graph': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'notice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Notice']"}),
+            'term': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Term']"})
+        },
+        'core.perinoticeterm': {
+            'Meta': {'object_name': 'PeriNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.reprnoticeterm': {
+            'Meta': {'object_name': 'ReprNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.srepnoticeterm': {
+            'Meta': {'object_name': 'SrepNoticeTerm', '_ormbases': ['core.NoticeTerm']},
+            u'noticeterm_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['core.NoticeTerm']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'core.term': {
+            'Meta': {'object_name': 'Term'},
+            'alternative_wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'alternative_wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'lang': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            u'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            u'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'link_semantic_level': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'nb_notice': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'normalized_label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'notices': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'terms+'", 'symmetrical': 'False', 'through': "orm['core.NoticeTerm']", 'to': "orm['core.Notice']"}),
+            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['core.Term']"}),
+            u'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'thesaurus': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Thesaurus']"}),
+            u'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'uri': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'url_status': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'validated': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'validation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'validator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.User']", 'null': 'True', 'blank': 'True'}),
+            'wikipedia_edition': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'wikipedia_revision_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'wp_alternative_label': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'wp_label': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'core.thesaurus': {
+            'Meta': {'ordering': "['label']", 'object_name': 'Thesaurus'},
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'uri': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'core.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'jocondelab.country': {
+            'Meta': {'object_name': 'Country'},
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'iso_code_2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'db_index': 'True'}),
+            'iso_code_3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'})
+        },
+        'jocondelab.dbpediafields': {
+            'Meta': {'object_name': 'DbpediaFields'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'db_index': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'term': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dbpedia_fields'", 'to': "orm['core.Term']"}),
+            'thumbnail': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'jocondelab.dbpediageo': {
+            'Meta': {'object_name': 'DbpediaGeo'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'latitude': ('django.db.models.fields.FloatField', [], {'db_index': 'True'}),
+            'longitude': ('django.db.models.fields.FloatField', [], {'db_index': 'True'}),
+            'term': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'geo'", 'unique': 'True', 'to': "orm['core.Term']"})
+        },
+        'jocondelab.dbpediayears': {
+            'Meta': {'object_name': 'DbpediaYears'},
+            'end_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'start_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'term': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'years'", 'unique': 'True', 'to': "orm['core.Term']"})
+        },
+        'jocondelab.termlinks': {
+            'Meta': {'object_name': 'TermLinks'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'termlinks_objects'", 'to': "orm['core.Term']"}),
+            'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'termlinks_subjects'", 'to': "orm['core.Term']"})
+        }
+    }
+
+    complete_apps = ['jocondelab']
\ No newline at end of file
--- a/src/jocondelab/models/__init__.py	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/models/__init__.py	Tue Aug 20 18:54:03 2013 +0200
@@ -1,3 +1,3 @@
-__all__ = ['Country', 'DbpediaFields', 'TermLinks']
+__all__ = ['Country', 'DbpediaFields', 'TermLinks', 'DbpediaYears', 'DbpediaGeo']
 
-from jocondelab.models.data import Country, DbpediaFields, TermLinks
\ No newline at end of file
+from jocondelab.models.data import Country, DbpediaFields, TermLinks, DbpediaYears, DbpediaGeo
\ No newline at end of file
--- a/src/jocondelab/models/data.py	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/models/data.py	Tue Aug 20 18:54:03 2013 +0200
@@ -35,3 +35,19 @@
      
     class Meta:
         app_label = 'jocondelab'
+
+class DbpediaYears(models.Model):
+    term = models.ForeignKey(Term, unique=True, blank=False, null=False, db_index=True, related_name="years")
+    start_year = models.IntegerField(null=False, blank=False, db_index=True)
+    end_year = models.IntegerField(null=False, blank=False, db_index=True)
+    
+    class Meta:
+        app_label = 'jocondelab'
+
+class DbpediaGeo(models.Model):
+    term = models.ForeignKey(Term, unique=True, blank=False, null=False, db_index=True, related_name="geo")
+    latitude = models.FloatField(null=False, blank=False, db_index=True)
+    longitude = models.FloatField(null=False, blank=False, db_index=True)
+    
+    class Meta:
+        app_label = 'jocondelab'
\ No newline at end of file
--- a/src/jocondelab/static/jocondelab/css/front-common.css	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/static/jocondelab/css/front-common.css	Tue Aug 20 18:54:03 2013 +0200
@@ -130,7 +130,7 @@
 }
 
 .main-title {
-    float: left; margin-top: 10px; height: 50px; line-height: 50px;
+    float: left; margin-top: 10px; height: 50px; line-height: 50px; overflow: hidden;
 }
 
 .main-title h1, .main-title h2 {
@@ -160,27 +160,42 @@
 }
 
 .header-search-input {
-    margin: 0 auto; width: 260px; max-width: 90%; line-height: 28px; height: 28px; font-size: 16px; font-family: 'OpenSans'; padding: 0 9px;
-    border-radius: 9px; box-shadow: 2px 2px 4px #333333 inset; background: #ffffff; border: none;
+    margin: 0 auto; width: 260px; max-width: 90%; line-height: 28px; height: 28px;
+    font-size: 16px; font-family: 'OpenSans'; padding: 0 9px; z-index: 1;
+    border-radius: 9px; box-shadow: 2px 2px 4px #333333 inset; border: none;
+    background: url(../img/search-icon.png) right center no-repeat #ffffff;
 }
 
 /* HEADER > FLAGS */
 
 .language-select {
-    position: absolute; top: 10px; height: 12px; right: 0;
+    position: absolute; text-align: right; top: 5px; height: 22px; right: 0; width: 28px;
 }
 
-.language-select form {
-    display: inline-block;
+.language-current {
+    display: block; margin: 5px 0;
+}
+
+.language-list {
+    position: absolute; top: 22px; right: 0; background: #ffffff; display: none;
+    font-size: 12px; width: 100px; box-shadow: 1px 1px 3px #333333; z-index: 2;
 }
 
-.langbutton {
-    width: 18px; height: 12px; border: none; padding: 0; text-indent: -9999px; margin: 0 0 0 5px;
-    opacity: .3;
+.language-select:hover .language-list {
+    display: block;
+}
+
+.language-item {
+    border-bottom: 1px solid #cccccc; height: 20px;
 }
 
-.langbutton.selected, .langbutton:hover {
-    opacity: 1;
+.language-label {
+    line-height: 20px; cursor: pointer;
+}
+
+.language-button {
+    width: 18px; height: 12px; border: none; padding: 0; text-indent: -9999px;
+    float: right; margin: 4px 4px 0 6px; cursor: pointer;
 }
 
 /* DBPEDIA OVERLAY */
--- a/src/jocondelab/static/jocondelab/css/front-search.css	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/static/jocondelab/css/front-search.css	Tue Aug 20 18:54:03 2013 +0200
@@ -41,7 +41,8 @@
 
 .big-search-input {
     margin: 0 auto; width: 80%; line-height: 32px; height: 32px; font-size: 16px; font-family: 'OpenSans'; padding: 0 9px;
-    border-radius: 9px; box-shadow: 2px 2px 4px #333333 inset; background: #ffffff; border: none;
+    border-radius: 9px; box-shadow: 2px 2px 4px #333333 inset; 
+    background: url(../img/search-icon.png) right center no-repeat #ffffff; border: none;
 }
 
 /* TERM CLOUD */
Binary file src/jocondelab/static/jocondelab/img/search-icon.png has changed
--- a/src/jocondelab/static/jocondelab/js/front-common.js	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-common.js	Tue Aug 20 18:54:03 2013 +0200
@@ -57,7 +57,7 @@
                 wkUrl += "wiki/" + encodeURI(label.replace(/ /g,'_'));
             } 
             $h2.text(uriData.l || uriData.lr || "");
-            $abstract.text((uriData.a || uriData.ar || "").replace(/^(.{240,260})\s.+$/,'$1…'));
+            $abstract.text((uriData.a || uriData.ar || "").replace(/^(.{240,260})\s.+$/,'$1…').substr(0,261));
             $source.attr("href", wkUrl);
             moveDbpediaPopin();
         }
@@ -119,5 +119,12 @@
     }, onDbpediaLeave);
     
     $(window).resize(moveDbpediaPopin).scroll(moveDbpediaPopin);
+        
+    $(".language-label").click(function() {
+       $(this).siblings(".language-button").click(); 
+    });
+    $(".language-current").click(function() {
+        $(".language-list").toggle();
+    })
     
-})
+});
--- a/src/jocondelab/templates/jocondelab/front_base.html	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_base.html	Tue Aug 20 18:54:03 2013 +0200
@@ -1,6 +1,6 @@
 {% load i18n %}
 <!doctype html>
-<html lang="{{LANGUAGE_CODE}}">
+<html lang="{% if lang %}{{lang}}{% else %}{{LANGUAGE_CODE}}{% endif %}">
     <head>
     {% block head %}
     	<meta charset="UTF-8" />
@@ -16,7 +16,6 @@
         
         {% block css_import %}
         <link rel="stylesheet" href="{{STATIC_URL}}jocondelab/css/smoothness/jquery-ui-1.10.3.custom.min.css" type="text/css"/>
-        <link rel="stylesheet" href="{{STATIC_URL}}jocondelab/css/front-common.css" type="text/css"/>
         {% endblock %}
         
         {% block css_declaration %}
@@ -38,15 +37,19 @@
                         <h1><a href="{% url 'multilingual_search' %}">Joconde<span class="title-lab">Lab</span></a></h1>
                         <h2 class="breadcrumbs">{% block breadcrumbs %}{% endblock %}</h2>
                     </div>
-                    <div class="language-select">
-                        <form action="{% url 'django.views.i18n.set_language' %}" method="post" id="lang_form">
+                    <form action="{% url 'django.views.i18n.set_language' %}" method="post" id="lang_form" class="language-select">
                         {% csrf_token %}
-                            {% get_language_info_list for LANGUAGES as languages %}
-                            {% for language in languages %}
-                                <input type="submit" name="language" class="langbutton{% if language.code == LANGUAGE_CODE %} selected{% endif %}" style="background-image: url({{STATIC_URL}}jocondelab/img/flag_{{ language.code }}.png)" value="{{ language.code }}" title="{{ language.name_local }}" />
-                            {% endfor %}
-                        </form>
-                    </div>
+                        <a class="language-current" href="#"><img src="{{STATIC_URL}}jocondelab/img/flag_{% if lang %}{{lang}}{% else %}{{LANGUAGE_CODE}}{% endif %}.png" /></a>
+                        <ul class="language-list">
+                        {% get_language_info_list for LANGUAGES as languages %}
+                        {% for language in languages %}
+                            <li class="language-item">
+                                <label for="language" class="language-label">{{ language.name_local }}</label>
+                                <input type="submit" name="language" class="language-button" style="background-image: url({{STATIC_URL}}jocondelab/img/flag_{{ language.code }}.png)" value="{{ language.code }}" title="{{ language.name_local }}" />
+                            </li>
+                        {% endfor %}
+                        </ul>
+                    </form>
                     {% block header_search %}
                     <form class="header-search-form" action="{% url 'multilingual_search' %}">
                         <input class="header-search-input" type="search" name="q" />
--- a/src/jocondelab/templates/jocondelab/front_search.html	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_search.html	Tue Aug 20 18:54:03 2013 +0200
@@ -33,6 +33,7 @@
             </ul>
             
             <div class="resultcount">{{rescount}} {% trans 'results' %} -- {{duration}} secondes</div>
+            <div>{{sql}}</div>
             
             <ul class="notice-list clearfix">
                 {% for notice in notices %}
--- a/src/jocondelab/urls.py	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/urls.py	Tue Aug 20 18:54:03 2013 +0200
@@ -33,5 +33,8 @@
     url(r'^bo/tree/(?P<thes_id>\d+)/$', login_required(ThesaurusTree.as_view()), name='term_tree'),
     url(r'^mlsearch/$', MultilingualSearch.as_view(), name='multilingual_search'),
     url(r'^notice/(?P<notice_id>\d+)/$', NoticeView.as_view(), name='front_notice'),
+    url(r'^ajax/years/$', 'jocondelab.views.ajax.years', name='ajax_years'),
+    url(r'^ajax/geocoords/$', 'jocondelab.views.ajax.geo_coords', name='ajax_geo_coords'),
+    url(r'^ajax/contents/$', 'jocondelab.views.ajax.contents_by_term', name='ajax_contents_by_term')
 )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/views/ajax.py	Tue Aug 20 18:54:03 2013 +0200
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Aug 20, 2013
+
+@author: rvelt
+'''
+
+from jocondelab.models import DbpediaYears, DbpediaGeo
+from core.models import Notice
+import django.utils.simplejson as json
+from django.http import HttpResponse
+from django.conf import settings
+
+def years(request):
+    
+    lang = request.GET.get('lang', request.LANGUAGE_CODE)
+    from_year = request.GET.get('from_year', None)
+    to_year = request.GET.get('to_year', None)
+    count = request.GET.get('count', 20)
+    
+    qs = DbpediaYears.objects.filter(term__dbpedia_fields__language_code=lang).order_by('-term__nb_notice')
+    
+    if to_year:
+        qs = qs.filter(start_year__lt=to_year)
+    if from_year:
+        qs = qs.filter(end_year__gt=to_year)
+    
+    qs = qs[:count]
+    
+    results = [{
+                "start_year": y.start_year,
+                "to_year": y.end_year,
+                "term_id": y.term.id,
+                "label": y.term.dbpedia_fields.get(language_code=lang).label,
+                "nb_notice": y.term.nb_notice,
+                "dbpedia_uri": y.term.dbpedia_uri
+                } for y in qs]
+    
+    return HttpResponse(content=json.dumps(results), mimetype='application/json')
+
+def geo_coords(request):
+    
+    lang = request.GET.get('lang', request.LANGUAGE_CODE)
+    min_lat = request.GET.get('min_lat', None)
+    max_lat = request.GET.get('max_lat', None)
+    min_lng = request.GET.get('min_lng', None)
+    max_lng = request.GET.get('max_lng', None)
+    count = request.GET.get('count', 20)
+    
+    qs = DbpediaGeo.objects.filter(term__dbpedia_fields__language_code=lang).order_by('-term__nb_notice')
+    
+    if min_lat:
+        qs = qs.filter(latitude__gt=min_lat)
+    if max_lat:
+        qs = qs.filter(latitude__lt=min_lat)
+    if min_lng:
+        qs = qs.filter(longitude__gt=min_lng)
+    if max_lng:
+        qs = qs.filter(longitude__lt=min_lng)
+    
+    qs = qs[:count]
+    
+    results = [{
+                "latitude": y.latitude,
+                "longitude": y.longitude,
+                "term_id": y.term.id,
+                "label": y.term.dbpedia_fields.get(language_code=lang).label,
+                "nb_notice": y.term.nb_notice,
+                "dbpedia_uri": y.term.dbpedia_uri
+                } for y in qs]
+    
+    return HttpResponse(content=json.dumps(results), mimetype='application/json')
+
+def contents_by_term(request):
+    
+    lang = request.GET.get('lang', request.LANGUAGE_CODE)
+    count = request.GET.get('count', 20)
+    random = ("random" in request.GET and request.GET["random"])
+    term_id = request.GET.get('term_id', None)
+    
+    if term_id is None:
+        results = []
+    else:
+        qs = Notice.objects.filter(noticeterm__term_id=term_id, image=True)
+        if random:
+            qs = qs.order_by('?')
+        qs = qs[:count]
+        results = [{
+            "title": n.titr if n.titr else n.deno,
+            "notice_id": n.id,
+            "image": settings.JOCONDE_IMG_BASE_URL + n.images.all()[0].url,
+            } for n in qs]
+    
+    return HttpResponse(content=json.dumps(results), mimetype='application/json')
+    
\ No newline at end of file
--- a/src/jocondelab/views/front_office.py	Tue Aug 20 12:27:34 2013 +0200
+++ b/src/jocondelab/views/front_office.py	Tue Aug 20 18:54:03 2013 +0200
@@ -11,7 +11,6 @@
 from django.views.generic import View
 from django.views.generic.base import TemplateResponseMixin
 from django.db.models import Q, Count
-import random
 import re
 import time
 
@@ -86,11 +85,9 @@
         context["notices"] = notices
         context["queryterms"] = querystr
         
-        # The word cloud is very time-consuming !
-        
         wpp = 30
         if show_tagcloud:
-            wqs = DbpediaFields.objects.filter(language_code=lang, term__notices__in=Notice.objects.exclude(image=None)).annotate(notice_count=Count('term__notices')).order_by('-notice_count')[:wpp]
+            wqs = DbpediaFields.objects.filter(language_code=lang, term__notices__in=qs).annotate(notice_count=Count('term__notices')).order_by('-notice_count')[:wpp]
             words = [{
                 "uri": w.dbpedia_uri,
                 "label": w.label,
@@ -107,7 +104,6 @@
                 w["font_size"] = fontmin + scale * w["notice_count"]
          
         context["words"] = words
-        
         context['JOCONDE_IMG_BASE_URL'] = settings.JOCONDE_IMG_BASE_URL
         
         context['duration'] = "%.2f"%(time.time() - starttime)
@@ -125,6 +121,7 @@
         
         notice = Notice.objects.get(id=notice_id)
         
+        context["lang"] = lang
         context["notice"] = notice
         context["title"] = notice.titr if notice.titr else notice.deno
         context["images"] = [i.url for i in notice.images.exclude(relative_url__endswith='v.jpg')]
@@ -152,4 +149,6 @@
         
         context['JOCONDE_IMG_BASE_URL'] = settings.JOCONDE_IMG_BASE_URL
         
-        return self.render_to_response(context)
\ No newline at end of file
+        return self.render_to_response(context)
+
+    
\ No newline at end of file