src/hdalab/views/ajax.py
branchdocumentation
changeset 693 09e00f38d177
parent 620 f45d7494332e
equal deleted inserted replaced
692:b7d19cd87fcf 693:09e00f38d177
    21 
    21 
    22 import logging
    22 import logging
    23 logger = logging.getLogger(__name__)
    23 logger = logging.getLogger(__name__)
    24 
    24 
    25 def tagtranslation(request):
    25 def tagtranslation(request):
       
    26     """
       
    27     Vue donnant des traductions de label de tag pour une langue.
       
    28     la recherche se fait dans les objets :class:`hdalab.models.DbpediaFieldsTranslation`.
       
    29 
       
    30     Paramêtres GET:
       
    31         :var lang: La langue demandée
       
    32         :var labels: Un ou plusieurs labels de tag (séparateur : ",")
       
    33 
       
    34     Réponse (application/json):
       
    35         Un dictionnaire sous la forme ::
       
    36 
       
    37             {
       
    38                 "<label1>": "<translation>",
       
    39                 "<label2>": "<translation>"
       
    40             }
       
    41 
       
    42     """
    26 
    43 
    27     lang = request.GET.get('lang',request.LANGUAGE_CODE)
    44     lang = request.GET.get('lang',request.LANGUAGE_CODE)
    28     labels = request.GET.get('labels',None)
    45     labels = request.GET.get('labels',None)
    29 
    46 
    30     if not labels:
    47     if not labels:
    44 
    61 
    45     translations = dict([(t.master.label, t.label) for t in translationqs])
    62     translations = dict([(t.master.label, t.label) for t in translationqs])
    46 
    63 
    47     return HttpResponse(content=json.dumps(translations), content_type='application/json')
    64     return HttpResponse(content=json.dumps(translations), content_type='application/json')
    48 
    65 
    49 def subcat(category, globtags, level, max_level ):
    66 
       
    67 
       
    68 def subcat(category, globtags, level, max_level):
       
    69     """
       
    70     Méthode récursive utilisée pour reconstruire un arbre de catégories.
       
    71 
       
    72     :param object category: La catégorie racine.
       
    73     :param dict globtags: dictionnaire flobal des tags.
       
    74     :param int level: Niveau de récursion.
       
    75     :param int max_level: Niveau maximum de récursion (level <= max_level)
       
    76 
       
    77     :returns: L'arbre des catégories.
       
    78     """
    50     # recursive function used by cattree
    79     # recursive function used by cattree
    51     catlabel = category.label
    80     catlabel = category.label
    52     tags = Tag.objects.filter(wp_categories__wp_category = category).distinct()
    81     tags = Tag.objects.filter(wp_categories__wp_category = category).distinct()
    53     taglabels = [k for k in dict([(t.label,t.label) for t in tags])]
    82     taglabels = [k for k in dict([(t.label,t.label) for t in tags])]
    54     resobj = {
    83     resobj = {
    68         subcats = WpCategory.objects.filter(parent_categories__parent_category = category)
    97         subcats = WpCategory.objects.filter(parent_categories__parent_category = category)
    69         resobj['themes'] += [subcat(subcats[i], globtags, level + 1, max_level ) for i in range(len(subcats))]
    98         resobj['themes'] += [subcat(subcats[i], globtags, level + 1, max_level ) for i in range(len(subcats))]
    70     return resobj
    99     return resobj
    71 
   100 
    72 def cleantags(category):
   101 def cleantags(category):
       
   102     """
       
   103     Methode annexe qui nettoie recursivement un arbre de catégorie. elle effectue les actions suivantes:
       
   104       - retire les clefs correspondant à des listes vides ('contents' et 'themes')
       
   105       - trie les listes 'themes' par label
       
   106       - trie les listes 'contents' par score
       
   107 
       
   108     :param category: la catégorie racine où commencer le traitement.
       
   109 
       
   110     """
    73     if category.has_key('contents') and len(category['contents']) == 0:
   111     if category.has_key('contents') and len(category['contents']) == 0:
    74         del category['contents']
   112         del category['contents']
    75     if category.has_key('contents'):
   113     if category.has_key('contents'):
    76         category['contents'] = sorted(category['contents'], key=lambda content: -content['score'])
   114         category['contents'] = sorted(category['contents'], key=lambda content: -content['score'])
    77     if category.has_key('themes'):
   115     if category.has_key('themes'):
    84         if len(category['themes']) == 0:
   122         if len(category['themes']) == 0:
    85             del category['themes']
   123             del category['themes']
    86     return category
   124     return category
    87 
   125 
    88 def cattree(request):
   126 def cattree(request):
       
   127     """
       
   128     Contruit l'arbre de catégorie pour un label.
       
   129     Les contenus attachés aux noeud sont des listes de fiches hdalab triées par score.
       
   130     Le score pour une fiche est fonction de ses tags, de leur ordre, de leur présence dnas l'arbre des catégories et de leur hauteur dans l'arbre des catégories.
       
   131 
       
   132     Paramêtres GET :
       
   133         :var label: Le label
       
   134 
       
   135     Réponse (application/json):
       
   136         Un json représentant l'arbre des catégories avec pour chaque noeud une liste ordonnée de fiches liée à la catégorie.
       
   137 
       
   138         exemple ::
       
   139 
       
   140             {
       
   141                 "label": "<label1>",
       
   142                 "themes": [ { "label": "<label1.1>", "themes": [...], "contents": [...]}, ...],
       
   143                 "contents": [
       
   144                     {
       
   145                         "organization": "Ciclic",
       
   146                         "description": "Ciclic propose...",
       
   147                         "score": 7,
       
   148                         "title": "Vocabulaire de l'analyse filmique...",
       
   149                         "url": "http://upopi.ciclic.fr/vocabulaire/definition/sceance-11",
       
   150                         "hda_id": "5879",
       
   151                         "organization_url": "http://www.ciclic.fr/",
       
   152                         "id": 14852
       
   153                     },
       
   154                     ...
       
   155                 ]
       
   156             }
       
   157     """
    89     # Gets the category tree from a label
   158     # Gets the category tree from a label
    90     ROOT_MAX_TAG_ORDER = 8
   159     ROOT_MAX_TAG_ORDER = 8
    91     MAX_TAG_ORDER = 8
   160     MAX_TAG_ORDER = 8
    92     MAX_LEVEL = 3
   161     MAX_LEVEL = 3
    93     LEVEL_COEFF = 5
   162     LEVEL_COEFF = 5
   144         }
   213         }
   145 
   214 
   146 
   215 
   147     return HttpResponse(content=json.dumps(resobj), content_type='application/json')
   216     return HttpResponse(content=json.dumps(resobj), content_type='application/json')
   148 
   217 
       
   218 
   149 def sessioninfo(request):
   219 def sessioninfo(request):
       
   220     """
       
   221     Vue gérant les session Hda permettant de sauvegarder un état d'interface.
       
   222     Note : Cette vue n'est pas mappée dans le module `hdalab.url`.
       
   223     """
   150 
   224 
   151     data = json.loads(request.GET.get('data', "{}"))
   225     data = json.loads(request.GET.get('data', "{}"))
   152     write = False
   226     write = False
   153 
   227 
   154     if 'sessionid' in request.GET:
   228     if 'sessionid' in request.GET:
   186 
   260 
   187     return HttpResponse(content=json.dumps(resobj), content_type='application/json')
   261     return HttpResponse(content=json.dumps(resobj), content_type='application/json')
   188 
   262 
   189 
   263 
   190 def tagsearch(request):
   264 def tagsearch(request):
       
   265     """
       
   266     Vue permettant la recherche dans les tag.
       
   267     La recherche se fait dans les objets :class:`hdabo.models.Tag`, :class:`hdalab.models.DbpediaFields` et :class:`hdalab.models.DbpediaFieldsTranslation`.
       
   268 
       
   269     Paramêtres GET:
       
   270         :var (str) term: Le terme à rechercher.
       
   271         :var (str) lang: La langue dans laquelle il faut faire la recherche.
       
   272         :var (int) count: Le nombre maximum de résultat.
       
   273         :var (bool) count_notices: Ajoute ou pas le nombre de notices par tag.
       
   274 
       
   275     Réponse (application/json):
       
   276         Une liste comprenant les résultats de la recherche.
       
   277 
       
   278         exemple ::
       
   279 
       
   280             [
       
   281                 {
       
   282                     "original_label": "Cathédrale Notre-Dame de Chartres",
       
   283                     "url": "http://fr.wikipedia.org/wiki/Cath%C3%A9drale_Notre-Dame_de_Chartres",
       
   284                     "abstract": "La cathédrale Notre-Dame de Chartres ...",
       
   285                     "value": "Cathédrale Notre-Dame de Chartres",
       
   286                     "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Chartres_Cath+Gare.JPG?width=300",
       
   287                     "nb": 7
       
   288                 },
       
   289                 {
       
   290                     "original_label": "Cathédrale Notre-Dame de Paris",
       
   291                     "url": "http://fr.wikipedia.org/wiki/Cath%C3%A9drale_Notre-Dame_de_Paris",
       
   292                     "abstract": "La cathédrale Notre-Dame de Paris...",
       
   293                     "value": "Cathédrale Notre-Dame de Paris",
       
   294                     "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Notre_Dame_de_Paris_DSC_0846w.jpg?width=300",
       
   295                     "nb": 6
       
   296                 },
       
   297                 ...
       
   298             ]
       
   299     """
   191 
   300 
   192     q = request.GET.get('term',None)
   301     q = request.GET.get('term',None)
   193     maxcount = int(request.GET.get('count','40'))
   302     maxcount = int(request.GET.get('count','40'))
   194     lang = request.GET.get('lang',request.LANGUAGE_CODE)
   303     lang = request.GET.get('lang',request.LANGUAGE_CODE)
   195     count_notices_str = request.REQUEST.get("count_notices")
   304     count_notices_str = request.REQUEST.get("count_notices")
   250             if q is None or resobj['value'].lower().find(lq) != -1:
   359             if q is None or resobj['value'].lower().find(lq) != -1:
   251                 res.append(resobj)
   360                 res.append(resobj)
   252 
   361 
   253     return HttpResponse(content=json.dumps(res), content_type='application/json')
   362     return HttpResponse(content=json.dumps(res), content_type='application/json')
   254 
   363 
       
   364 
       
   365 
   255 def catsearch(request):
   366 def catsearch(request):
       
   367     """
       
   368     Vue permettant la recherche de catégorie. On se restreint aux catégories qui sont aussi des tags.
       
   369 
       
   370     Paramêtres GET:
       
   371         :var (str) term: Le terme à rechercher.
       
   372 
       
   373     Réponse (application/json):
       
   374         Une liste comprenant le résultat de la recherche.
       
   375 
       
   376         exemple ::
       
   377 
       
   378             [
       
   379                 { "value": "1982 au cinéma" },
       
   380                 { "value": "Cinéma italien" },
       
   381                 { "value": "2003 au cinéma" },
       
   382                 ...
       
   383             ]
       
   384 
       
   385     """
       
   386 
   256 
   387 
   257     q = request.GET.get('term',None)
   388     q = request.GET.get('term',None)
   258 
   389 
   259     # On ne récupère que les catégories qui sont également des tags
   390     # On ne récupère que les catégories qui sont également des tags
   260     qrx = '(\\m|\\b)%s'%q
   391     qrx = '(\\m|\\b)%s'%q
   266 
   397 
   267     res = [{'value':t.label} for t in qs]
   398     res = [{'value':t.label} for t in qs]
   268 
   399 
   269     return HttpResponse(content=json.dumps(res), content_type='application/json')
   400     return HttpResponse(content=json.dumps(res), content_type='application/json')
   270 
   401 
       
   402 
       
   403 
   271 def filter(request):
   404 def filter(request):
       
   405     """
       
   406     Vue permettant de filtrer par facette des fiches HDA.
       
   407     Cette méthode est en fait un simple wrapper pour la méthode `filter_generic`.
       
   408 
       
   409     Paramêtres GET:
       
   410         :var lang: la langue de recherche (défaut: fr-fr).
       
   411         :var period: Période dans laquelle doit se faire la recherche.
       
   412         :var label: un mot-clef.
       
   413         :var country: Une liste de pays limitant la recherche.
       
   414         :var contentlist: Liste de fiches limitant la recherche.
       
   415         :var mto: Ordre maximum des tags (défaut: 12).
       
   416         :var contentcount: nombre de fiches maximum (défaut : 8).
       
   417         :var tagcount: nombre maximum de tag (défaut: 30).
       
   418 
       
   419     Réponse (application/json):
       
   420         Un objet comprenant le résultat de la recherche.
       
   421     """
       
   422 
   272 
   423 
   273     lang = request.GET.get('lang',request.LANGUAGE_CODE)
   424     lang = request.GET.get('lang',request.LANGUAGE_CODE)
   274     periode = request.GET.get('period',None)
   425     periode = request.GET.get('period',None)
   275     label = request.GET.get('label', None)
   426     label = request.GET.get('label', None)
   276     country = request.GET.get('country', None)
   427     country = request.GET.get('country', None)
   283 
   434 
   284     return HttpResponse(content=outputstr, content_type='application/json')
   435     return HttpResponse(content=outputstr, content_type='application/json')
   285 
   436 
   286 
   437 
   287 def filter_generic(lang="fr-fr", periode=None, label=None, country=None, contentlist=None, max_tag_order=12, content_count=8, tag_count=30):
   438 def filter_generic(lang="fr-fr", periode=None, label=None, country=None, contentlist=None, max_tag_order=12, content_count=8, tag_count=30):
       
   439     """
       
   440     Méthode de recherche par facette sur les fiches HDA.
       
   441 
       
   442     :param str lang: La langue de recherche (défaut: "fr-fr").
       
   443     :param str period: Période d'année limitant la recherche. Le format est `<année-début>,<année-fin>` (défaut: None).
       
   444     :param str label: Limite la recherche à un label de tag (défaut: None).
       
   445     :param str country: Liste de pays où limiter la recherche. Le format est `<uri dbpedia pays 1>,<uri dbpedia pays 2>...` (défaut: None).
       
   446     :param str contentlist: Liste d'id de fiche HDA (:class:`hdabo.models.Datasheet`) limitant la recherche. Le format est `<id1>,<id2>...` (défaut: None)
       
   447     :param int max_tag_order: Limite le nombre maximum de tag par fiche (défaut: 12).
       
   448     :param int content_count: Limite le nombre de fiches résultat (défaut: 8).
       
   449     :param int tag_count: Limite le nombre de tag dans le résultat (défaut: 30).
       
   450     :rtype: string
       
   451     :returns: Un objet json sérialisé comprenant les résultats de la recherche pour les différentes facettes.
       
   452 
       
   453 
       
   454     Clefs de l'objet:
       
   455         - :count: Nombre total de fiches.
       
   456         - :disciplines: Liste de disciplines artistiques en relation avec les reesultats, triée par score.
       
   457         - :countries: Objet dont les clef sont des uri dbpedia de pays et les valeurs sont le nombre de fiches.
       
   458         - :tags: Liste de tag triés par score.
       
   459         - :sparkline: Liste d'année avec un score, triés par année. Le score est lié au nombre de fiche dont le contenu couvre l'année en question.
       
   460         - :contents: Liste de fiches HDA répondant à la recherche, classée par score. Chaque fiche comporte une liste de tag.
       
   461         - :tagtranslations: Objet donnant les traductions de label de tag rencontrés dans les résultats.
       
   462 
       
   463     exemple::
       
   464 
       
   465         {
       
   466             "count": 936,
       
   467             "disciplines": [
       
   468                 {
       
   469                 "translated_label": "Peinture",
       
   470                 "score": 936,
       
   471                 "label": "Peinture"
       
   472                 },
       
   473                 {
       
   474                 "translated_label": "Sculpture",
       
   475                 "score": 88,
       
   476                 "label": "Sculpture"
       
   477                 },
       
   478                 ...
       
   479             ],
       
   480             "countries": {
       
   481                 "http://fr.dbpedia.org/resource/Iran": 1,
       
   482                 "http://fr.dbpedia.org/resource/Espagne": 16,
       
   483                 ...
       
   484             },
       
   485             "tags": [
       
   486                 {
       
   487                 "url": "http://fr.dbpedia.org/resource/Portrait",
       
   488                 "id": 63452,
       
   489                 "translated_label": "Portrait",
       
   490                 "score": 179,
       
   491                 "wkpd_url": "http://fr.wikipedia.org/wiki/Portrait",
       
   492                 "label": "Portrait",
       
   493                 "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Fayum02.jpg?width=300"
       
   494                 },
       
   495                 ...
       
   496             ],
       
   497             "sparkline": [
       
   498                 {
       
   499                 "score": 2,
       
   500                 "year": -600
       
   501                 },
       
   502                 {
       
   503                 "score": 4,
       
   504                 "year": -500
       
   505                 },
       
   506                 ...
       
   507                 {
       
   508                 "score": 18,
       
   509                 "year": 2001
       
   510                 }
       
   511             ],
       
   512             "contents": [
       
   513                 {
       
   514                 "description": "Le palais Fesch, ...",
       
   515                 "title": "Histoires bibliques",
       
   516                 "url": "http://www.musee-fesch.com/index.php/musee_fesch/content/view/ef_catalogue_sommaire/1513/%28node_id_theme%29/33459",
       
   517                 "tags": [
       
   518                     {
       
   519                     "url": "http://fr.dbpedia.org/resource/Peinture",
       
   520                     "id": 54648,
       
   521                     "translated_label": "Peinture",
       
   522                     "wkpd_url": "http://fr.wikipedia.org/wiki/Peinture",
       
   523                     "label": "Peinture",
       
   524                     "order": 1,
       
   525                     "match": true
       
   526                     },
       
   527                     ...
       
   528                 ],
       
   529                 "score": 23,
       
   530                 "coords": {
       
   531                     "city_name": "Ajaccio",
       
   532                     "latitude": 41.916667,
       
   533                     "longitude": 8.733333
       
   534                 },
       
   535                 "hda_id": "4448",
       
   536                 "id": 13855
       
   537                 },
       
   538                 {
       
   539                 "description": "...",
       
   540                 "title": "Le XIXe siècle",
       
   541                 "url": "http://www.grandpalais.fr/fr/article/le-xixe-siecle",
       
   542                 "tags": [ ... ],
       
   543                 "score": 22,
       
   544                 "hda_id": "5217",
       
   545                 "id": 13582
       
   546                 },
       
   547                 ...
       
   548             ],
       
   549             "tagtranslations": {
       
   550                 "Paul Cézanne": "Paul Cézanne",
       
   551                 "Politique": "Politique",
       
   552                 "Poésie": "Poésie",
       
   553                 "Religion": "Religion",
       
   554                 "Empereur": "Empereur",
       
   555                 "Saint": "Saint",
       
   556                 ...
       
   557             }
       
   558         }
       
   559 
       
   560     """
   288 
   561 
   289     no_translate_langs = [ 'fr' ]
   562     no_translate_langs = [ 'fr' ]
   290 
   563 
   291     key_parts = ("filter",lang,periode,label,country,contentlist,max_tag_order,content_count,tag_count)
   564     key_parts = ("filter",lang,periode,label,country,contentlist,max_tag_order,content_count,tag_count)
   292     key_parts = [unicode(p).encode("ascii", "ignore") for p in key_parts]
   565     key_parts = [unicode(p).encode("ascii", "ignore") for p in key_parts]
   472     return outputstr
   745     return outputstr
   473 
   746 
   474 
   747 
   475 
   748 
   476 def subtree(tree):
   749 def subtree(tree):
       
   750     """
       
   751     Methode récursive permettant de remplir un arbre ce catégories avec les fiches HDA correspondantes.
       
   752 
       
   753     :param tree: L'arbre de catégorie
       
   754 
       
   755     :returns:Un arbre de catégorie rempli de fiches HDA.
       
   756 
       
   757     format du paramêtre `tree` ::
       
   758 
       
   759         {
       
   760             "label": "secteur urbain",
       
   761             "contents": [
       
   762                 { "label": "banlieue",
       
   763                     "contents": [
       
   764                         { "label": "faubourg" }
       
   765                     ] },
       
   766                 { "label": "îlot" },
       
   767                 ...
       
   768             ]
       
   769         }
       
   770 
       
   771     Exemple de retour ::
       
   772 
       
   773 
       
   774         {
       
   775             "label": "secteur urbain",
       
   776             "contents": [
       
   777                 {
       
   778                     "score": 6,
       
   779                     "organization": "Institut national de l'audiovisuel ( INA )",
       
   780                     "description": "Pour faire face à la ...",
       
   781                     "title": "La construction des grands ensembles de banlieue : l'exemple de Sarcelles",
       
   782                     "url": "http://fresques.ina.fr/jalons/fiche-media/InaEdu01075/la-construction-des-grands-ensembles-de-banlieue--l-exemple-de-sarcelles",
       
   783                     "hda_id": "2090",
       
   784                     "organization_url": "http://www.ina.fr",
       
   785                     "id": 12360
       
   786                 },
       
   787                 {
       
   788                     "score": 6,
       
   789                     "organization": "Maison de banlieue et d'architecture",
       
   790                     "description": "La Maison de banlieue et d'architecture...",
       
   791                     "title": "Des ensembles assez grands. Mémoire et projets en Essonne",
       
   792                     "url": "http://maisondebanlieue.fr/wp-content/uploads/2011/05/Cahier11_grands_ensembles.pdf",
       
   793                     "hda_id": "5893",
       
   794                     "organization_url": "http://www.maisondebanlieue.fr/",
       
   795                     "id": 14821
       
   796                 },
       
   797                 ...
       
   798             ]
       
   799             "themes": [
       
   800                 {
       
   801                     "label": "faubourg",
       
   802                     "content":  [...],
       
   803                     "themes": [...]
       
   804                 },
       
   805                 ...
       
   806             ]
       
   807         }
       
   808 
       
   809     """
   477     MAX_TAG_ORDER = 16
   810     MAX_TAG_ORDER = 16
   478     label = tree['label']
   811     label = tree['label']
   479     sub = tree.get('contents',[])
   812     sub = tree.get('contents',[])
   480 
   813 
   481     datasheets = Datasheet.objects.filter(validated = True, taggedsheet__tag__label__iexact = label, taggedsheet__order__lte = MAX_TAG_ORDER).annotate(tagorder=Min('taggedsheet__order')).select_related('organisation').distinct()
   814     datasheets = Datasheet.objects.filter(validated = True, taggedsheet__tag__label__iexact = label, taggedsheet__order__lte = MAX_TAG_ORDER).annotate(tagorder=Min('taggedsheet__order')).select_related('organisation').distinct()
   495         res['themes'] = subcats
   828         res['themes'] = subcats
   496 
   829 
   497     return res
   830     return res
   498 
   831 
   499 def filltree(request):
   832 def filltree(request):
       
   833     """
       
   834     Vue permettant d'ajouter des fiches à un arbre de catégories.
       
   835     Cette méthode est en fait un simple wrapper pour la méthode :meth:`subtree`.
       
   836 
       
   837     Paramêtres GET:
       
   838         :var tree: Serialisation json d'un arbre de catégories à remplir. exemple:
       
   839 
       
   840         ::
       
   841 
       
   842             {
       
   843                 "label": "secteur urbain",
       
   844                 "contents": [
       
   845                     { "label": "banlieue",
       
   846                       "contents": [
       
   847                           { "label": "faubourg" }
       
   848                       ] },
       
   849                     { "label": "îlot" },
       
   850                     ...
       
   851                 ]
       
   852             }
       
   853 
       
   854     Réponse (application/json):
       
   855         L'arbre de catégories remplis de fiches HDA (c.f. retour methode :meth:`subtree`)
       
   856 
       
   857     """
   500 
   858 
   501     tree = request.GET.get('tree','{}')
   859     tree = request.GET.get('tree','{}')
   502 
   860 
   503     treeobj = json.loads(tree)
   861     treeobj = json.loads(tree)
   504 
   862