Add hdabo/hdalab documentations documentation
authorymh <ymh.work@gmail.com>
Wed, 11 Apr 2018 12:19:47 +0200
branchdocumentation
changeset 693 09e00f38d177
parent 692 b7d19cd87fcf
child 694 46da276fbb1b
Add hdabo/hdalab documentations
.hgignore
doc/Makefile
doc/make.bat
doc/source/_static/img/logo_iri.png
doc/source/_static/img/pages/accueil_hdalab.png
doc/source/_static/img/pages/admin_django_hdalab.png
doc/source/_static/img/pages/administrer_renkan.png
doc/source/_static/img/pages/apropos_hdalab.png
doc/source/_static/img/pages/artistic_domains_hdalab.png
doc/source/_static/img/pages/contact_hdalab.png
doc/source/_static/img/pages/credits_hdalab.png
doc/source/_static/img/pages/detail_notice.png
doc/source/_static/img/pages/editorialisation_hdalab.png
doc/source/_static/img/pages/facettes_hdalab.png
doc/source/_static/img/pages/mentions_legales_hdalab.png
doc/source/_static/img/pages/renkan_base_list.png
doc/source/_static/img/pages/renkan_edit.png
doc/source/_static/img/pages/renkan_favorite.png
doc/source/_static/img/pages/renkan_public.png
doc/source/_static/img/pages/renkan_view.png
doc/source/_static/img/pages/renkan_view_full.png
doc/source/_static/img/pages/thematic_folder_hdalab.png
doc/source/_static/img/pages/tree_search_hdalab.png
doc/source/_static/img/pages/user_info_hdalab.png
doc/source/_static/img/pages/user_profile_hdalab.png
doc/source/_static/img/renkan/renkan_bin_plus_ressources.png
doc/source/_static/img/renkan/renkan_bin_resources.png
doc/source/_static/img/renkan/renkan_edition.png
doc/source/_static/img/renkan/renkan_recherche_contenus.png
doc/source/_static/img/renkan/renkan_recherche_resultats.png
doc/source/api.rst
doc/source/api/hdabo.management.commands.rst
doc/source/api/hdabo.management.rst
doc/source/api/hdabo.migrations.rst
doc/source/api/hdabo.rst
doc/source/api/hdabo.search.rst
doc/source/api/hdabo.templatetags.rst
doc/source/api/hdabo.tests.rst
doc/source/api/hdalab.management.commands.rst
doc/source/api/hdalab.management.rst
doc/source/api/hdalab.migrations.rst
doc/source/api/hdalab.models.rst
doc/source/api/hdalab.rst
doc/source/api/hdalab.templatetags.rst
doc/source/api/hdalab.views.rst
doc/source/api/modules.rst
doc/source/commandes.rst
doc/source/conf.py
doc/source/dev.rst
doc/source/index.rst
doc/source/pages.rst
doc/source/renkan.rst
doc/source/taches.rst
src/hdabo/management/commands/clean_tags.py
src/hdabo/management/commands/diff_csv.py
src/hdabo/management/commands/import_csv.py
src/hdabo/management/commands/import_rdf.py
src/hdabo/management/commands/import_tag_popularity.py
src/hdabo/management/commands/order_tags.py
src/hdabo/management/commands/query_wikipedia.py
src/hdabo/models.py
src/hdabo/views.py
src/hdabo/wp_utils.py
src/hdalab/__init__.py
src/hdalab/management/commands/calculate_preview.py
src/hdalab/management/commands/export_tags_csv.py
src/hdalab/management/commands/export_wpcategory_csv.py
src/hdalab/management/commands/fill_tag_years.py
src/hdalab/management/commands/geojson_transform.py
src/hdalab/management/commands/import_hda_insee_csv.py
src/hdalab/management/commands/import_hdabo_db.py
src/hdalab/management/commands/import_insee_csv.py
src/hdalab/management/commands/query_category_inclusion.py
src/hdalab/management/commands/query_dbpedia.py
src/hdalab/management/commands/query_geo_inclusion.py
src/hdalab/management/commands/query_wikipedia_category.py
src/hdalab/management/commands/send_moderation_mail.py
src/hdalab/models/categories.py
src/hdalab/models/dataviz.py
src/hdalab/models/renkan.py
src/hdalab/services.py
src/hdalab/signals.py
src/hdalab/views/__init__.py
src/hdalab/views/ajax.py
src/hdalab/views/pages.py
src/hdalab/views/profile.py
virtualenv/web/res/doc_requirements.txt
--- a/.hgignore	Thu Apr 12 01:27:16 2018 +0200
+++ b/.hgignore	Wed Apr 11 12:19:47 2018 +0200
@@ -26,3 +26,4 @@
 ^src/MANIFEST.in$
 ^dev/hdalab/dist
 ^dev/out
+^doc/build
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SPHINXPROJ    = HDALab
+SOURCEDIR     = source
+BUILDDIR      = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/make.bat	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,36 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+set SPHINXPROJ=HDALab
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
Binary file doc/source/_static/img/logo_iri.png has changed
Binary file doc/source/_static/img/pages/accueil_hdalab.png has changed
Binary file doc/source/_static/img/pages/admin_django_hdalab.png has changed
Binary file doc/source/_static/img/pages/administrer_renkan.png has changed
Binary file doc/source/_static/img/pages/apropos_hdalab.png has changed
Binary file doc/source/_static/img/pages/artistic_domains_hdalab.png has changed
Binary file doc/source/_static/img/pages/contact_hdalab.png has changed
Binary file doc/source/_static/img/pages/credits_hdalab.png has changed
Binary file doc/source/_static/img/pages/detail_notice.png has changed
Binary file doc/source/_static/img/pages/editorialisation_hdalab.png has changed
Binary file doc/source/_static/img/pages/facettes_hdalab.png has changed
Binary file doc/source/_static/img/pages/mentions_legales_hdalab.png has changed
Binary file doc/source/_static/img/pages/renkan_base_list.png has changed
Binary file doc/source/_static/img/pages/renkan_edit.png has changed
Binary file doc/source/_static/img/pages/renkan_favorite.png has changed
Binary file doc/source/_static/img/pages/renkan_public.png has changed
Binary file doc/source/_static/img/pages/renkan_view.png has changed
Binary file doc/source/_static/img/pages/renkan_view_full.png has changed
Binary file doc/source/_static/img/pages/thematic_folder_hdalab.png has changed
Binary file doc/source/_static/img/pages/tree_search_hdalab.png has changed
Binary file doc/source/_static/img/pages/user_info_hdalab.png has changed
Binary file doc/source/_static/img/pages/user_profile_hdalab.png has changed
Binary file doc/source/_static/img/renkan/renkan_bin_plus_ressources.png has changed
Binary file doc/source/_static/img/renkan/renkan_bin_resources.png has changed
Binary file doc/source/_static/img/renkan/renkan_edition.png has changed
Binary file doc/source/_static/img/renkan/renkan_recherche_contenus.png has changed
Binary file doc/source/_static/img/renkan/renkan_recherche_resultats.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,182 @@
+################
+URL d'API HDALAB
+################
+
+Ces URL n'ont pas de sortie HTML. Elle sont utilisée en particulier par les composants javascript HDALab.
+
+Recherche fulltext dans les fiches
+==================================
+
+Ce point d'API est utilisé pour faire des recherches fulltext dans les fiches.
+Il est utilisé aux endroits suivants:
+
+    - :ref:`pages_recherche_facette`
+
++----------+---------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/hdabo/searchajax/ |
++----------+---------------------------------------------------------+
+| view     | :class:`hdabo.views.SearchDatasheet`                    |
++----------+---------------------------------------------------------+
+
+.. autoclass:: hdabo.views.SearchDatasheet
+  :noindex:
+
+
+
+Recherche dans les catégories Wikipedia
+=======================================
+
+Ce point d'API est utilisé pour faire des recherches dans les catégories Wikipedia.
+Il est utilisé aux endroits suivants:
+
+    - :ref:`pages_explorer_domaines_artistiques`
+
++----------+---------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/a/catsearch |
++----------+---------------------------------------------------+
+| view     | :func:`hdalab.views.ajax.catsearch`               |
++----------+---------------------------------------------------+
+
+.. autofunction:: hdalab.views.ajax.catsearch
+  :noindex:
+
+
+.. _api_arbre_categories:
+
+Arbre de catégories
+===================
+
+Ce point d'API est utilisé pour construire un arbre de catégorie Wikipedia à partir d'un label.
+Il est utilisé aux endroits suivants:
+
+    - :ref:`pages_explorer_domaines_artistiques`
+
+
++----------+-------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/a/cattree |
++----------+-------------------------------------------------+
+| view     | :func:`hdalab.views.ajax.cattree`               |
++----------+-------------------------------------------------+
+
+
+.. autofunction:: hdalab.views.ajax.cattree
+  :noindex:
+
+
+Remplissage d'arbre
+===================
+
+Ce point d'API est utilisé pour ajouter des fiches à un arbre de catégorie, comme par exemple produit par l'api :ref:`api_arbre_categories`.
+
+Il est utilisé dans les pages suivantes:
+
+    - :ref:`pages_explorer_domaines_artistiques`
+    - :ref:`pages_recherche_arbre`
+
+
++----------+--------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/a/filltree |
++----------+--------------------------------------------------+
+| view     | :func:`hdalab.views.ajax.filltree`               |
++----------+--------------------------------------------------+
+
+
+.. autofunction:: hdalab.views.ajax.filltree
+  :noindex:
+
+
+Filtrage par facette
+====================
+
+Ce point d'API est utilisé pour réaliser le filtrage par facette des fiches HDA.
+Il est utilisé aux endroits suivants:
+
+    - :ref:`pages_recherche_facette`
+
+
++----------+------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/a/filter |
++----------+------------------------------------------------+
+| view     | :func:`hdalab.views.ajax.filter`               |
++----------+------------------------------------------------+
+
+
+.. autofunction:: hdalab.views.ajax.filter
+  :noindex:
+
+
+Recherche de tag
+================
+
+Ce point d'API est utilisé pour faire des recherche dans les tags.
+Il est utilisé aux endroits suivants:
+
+    - :ref:`pages_recherche_facette`
+    - :ref:`renkan_boite_recherche_contenus`
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/a/tagsearch        |
++----------+----------------------------------------------------------+
+| view     | :func:`hdalab.views.ajax.tagsearch`                      |
++----------+----------------------------------------------------------+
+
+.. autofunction:: hdalab.views.ajax.tagsearch
+  :noindex:
+
+
+login ajax
+==========
+
+Ce point d'API permet la gestion de la connexion à partir d'un éditeur Renkan.
+Il est utilisé aux endroits suivants :
+
+    - :ref:`pages_recherche_facette`
+
+
++----------+---------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/ajaxlogin/  |
++----------+---------------------------------------------------+
+| view     | :func:`hdalab.views.profile.ajax_login`           |
++----------+---------------------------------------------------+
+
+.. autofunction:: hdalab.views.profile.ajax_login
+  :noindex:
+
+Chargement et sauvegarde de renkan
+==================================
+
+Ce point d'API permet le chargement et la sauvegarde des renkan. Il est appelé par le client javascript renkan.
+
+Il est utilisé aux endroits suivants :
+
+    - :ref:`pages_edition_renkan`
+    - :ref:`affichage-d-un-renkan-en-lecture-seule`
+    - :ref:`affichage-d-un-renkan-en-plein-ecran`
+
+
++-----------+------------------------------------------------------+
+| url       | http://hdalab.iri-research.org/hdalab/renkan/getput/ |
++-----------+------------------------------------------------------+
+| view      | :class:`hdalab.views.profile.HdalabRenkanGetPut`     |
++-----------+------------------------------------------------------+
+| view GET  | :meth:`hdalab.views.profile.HdalabRenkanGetPut.get`  |
++-----------+------------------------------------------------------+
+| view POST | :meth:`hdalab.views.profile.HdalabRenkanGetPut.post` |
++-----------+------------------------------------------------------+
+
+A noter que l'appel de l'URL en GET ou POST mème à des vue différentes.
+
+
+Appel en HTTP GET:
+------------------
+
+.. automethod:: hdalab.views.profile.HdalabRenkanGetPut.get
+  :noindex:
+
+Appel en HTTP POST:
+-------------------
+
+.. automethod:: hdalab.views.profile.HdalabRenkanGetPut.post
+  :noindex:
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.management.commands.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,70 @@
+hdabo.management.commands package
+=================================
+
+Submodules
+----------
+
+hdabo.management.commands.clean\_tags module
+--------------------------------------------
+
+.. automodule:: hdabo.management.commands.clean_tags
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.diff\_csv module
+------------------------------------------
+
+.. automodule:: hdabo.management.commands.diff_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.import\_csv module
+--------------------------------------------
+
+.. automodule:: hdabo.management.commands.import_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.import\_rdf module
+--------------------------------------------
+
+.. automodule:: hdabo.management.commands.import_rdf
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.import\_tag\_popularity module
+--------------------------------------------------------
+
+.. automodule:: hdabo.management.commands.import_tag_popularity
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.order\_tags module
+--------------------------------------------
+
+.. automodule:: hdabo.management.commands.order_tags
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.management.commands.query\_wikipedia module
+-------------------------------------------------
+
+.. automodule:: hdabo.management.commands.query_wikipedia
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.management.commands
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.management.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,22 @@
+hdabo.management package
+========================
+
+Submodules
+----------
+
+hdabo.management.utils module
+-----------------------------
+
+.. automodule:: hdabo.management.utils
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.management
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.migrations.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,30 @@
+hdabo.migrations package
+========================
+
+Submodules
+----------
+
+hdabo.migrations.0001\_initial module
+-------------------------------------
+
+.. automodule:: hdabo.migrations.0001_initial
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.migrations.0002\_alter\_user\_fields\_after\_1\_8 module
+--------------------------------------------------------------
+
+.. automodule:: hdabo.migrations.0002_alter_user_fields_after_1_8
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.migrations
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,101 @@
+hdabo package
+=============
+
+Subpackages
+-----------
+
+.. toctree::
+
+    hdabo.tests
+
+Submodules
+----------
+
+hdabo.admin module
+------------------
+
+.. automodule:: hdabo.admin
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.context\_processors module
+--------------------------------
+
+.. automodule:: hdabo.context_processors
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.django\_wsgi module
+-------------------------
+
+.. automodule:: hdabo.django_wsgi
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.forms module
+------------------
+
+.. automodule:: hdabo.forms
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.models module
+-------------------
+
+.. automodule:: hdabo.models
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.search\_indexes module
+----------------------------
+
+.. automodule:: hdabo.search_indexes
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.urls module
+-----------------
+
+.. automodule:: hdabo.urls
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.utils module
+------------------
+
+.. automodule:: hdabo.utils
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.views module
+------------------
+
+.. automodule:: hdabo.views
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdabo.wp\_utils module
+----------------------
+
+.. automodule:: hdabo.wp_utils
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.search.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,22 @@
+hdabo.search package
+====================
+
+Submodules
+----------
+
+hdabo.search.french\_whoosh\_backend module
+-------------------------------------------
+
+.. automodule:: hdabo.search.french_whoosh_backend
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.search
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.templatetags.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,22 @@
+hdabo.templatetags package
+==========================
+
+Submodules
+----------
+
+hdabo.templatetags.hdabo\_tags module
+-------------------------------------
+
+.. automodule:: hdabo.templatetags.hdabo_tags
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.templatetags
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdabo.tests.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,22 @@
+hdabo.tests package
+===================
+
+Submodules
+----------
+
+hdabo.tests.test\_models module
+-------------------------------
+
+.. automodule:: hdabo.tests.test_models
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdabo.tests
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.management.commands.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,118 @@
+hdalab.management.commands package
+==================================
+
+Submodules
+----------
+
+hdalab.management.commands.calculate\_preview module
+----------------------------------------------------
+
+.. automodule:: hdalab.management.commands.calculate_preview
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.export\_tags\_csv module
+---------------------------------------------------
+
+.. automodule:: hdalab.management.commands.export_tags_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.export\_wpcategory\_csv module
+---------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.export_wpcategory_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.fill\_tag\_years module
+--------------------------------------------------
+
+.. automodule:: hdalab.management.commands.fill_tag_years
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.geojson\_transform module
+----------------------------------------------------
+
+.. automodule:: hdalab.management.commands.geojson_transform
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.import\_hda\_insee\_csv module
+---------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.import_hda_insee_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.import\_hdabo\_db module
+---------------------------------------------------
+
+.. automodule:: hdalab.management.commands.import_hdabo_db
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.import\_insee\_csv module
+----------------------------------------------------
+
+.. automodule:: hdalab.management.commands.import_insee_csv
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.query\_category\_inclusion module
+------------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.query_category_inclusion
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.query\_dbpedia module
+------------------------------------------------
+
+.. automodule:: hdalab.management.commands.query_dbpedia
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.query\_geo\_inclusion module
+-------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.query_geo_inclusion
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.query\_wikipedia\_category module
+------------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.query_wikipedia_category
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.management.commands.send\_moderation\_mail module
+--------------------------------------------------------
+
+.. automodule:: hdalab.management.commands.send_moderation_mail
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.management.commands
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.management.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,22 @@
+hdalab.management package
+=========================
+
+Submodules
+----------
+
+hdalab.management.utils module
+------------------------------
+
+.. automodule:: hdalab.management.utils
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.management
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.migrations.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,38 @@
+hdalab.migrations package
+=========================
+
+Submodules
+----------
+
+hdalab.migrations.0001\_initial module
+--------------------------------------
+
+.. automodule:: hdalab.migrations.0001_initial
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.migrations.0002\_alter\_tagyears\_tag\_one2one module
+------------------------------------------------------------
+
+.. automodule:: hdalab.migrations.0002_alter_tagyears_tag_one2one
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.migrations.0003\_default\_site module
+--------------------------------------------
+
+.. automodule:: hdalab.migrations.0003_default_site
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.migrations
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.models.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,38 @@
+hdalab.models package
+=====================
+
+Submodules
+----------
+
+hdalab.models.categories module
+-------------------------------
+
+.. automodule:: hdalab.models.categories
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.models.dataviz module
+----------------------------
+
+.. automodule:: hdalab.models.dataviz
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.models.renkan module
+---------------------------
+
+.. automodule:: hdalab.models.renkan
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.models
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,126 @@
+hdalab package
+==============
+
+Subpackages
+-----------
+
+.. toctree::
+
+    hdalab.models
+    hdalab.views
+
+Submodules
+----------
+
+hdalab.apps module
+------------------
+
+.. automodule:: hdalab.apps
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.celery module
+--------------------
+
+.. automodule:: hdalab.celery
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.config module
+--------------------
+
+.. automodule:: hdalab.config
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.context\_processors module
+---------------------------------
+
+.. automodule:: hdalab.context_processors
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.fields module
+--------------------
+
+.. automodule:: hdalab.fields
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.forms module
+-------------------
+
+.. automodule:: hdalab.forms
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.services module
+----------------------
+
+.. automodule:: hdalab.services
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.settings module
+----------------------
+
+.. automodule:: hdalab.settings
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.signals module
+---------------------
+
+.. automodule:: hdalab.signals
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.tasks module
+-------------------
+
+.. automodule:: hdalab.tasks
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.urls module
+------------------
+
+.. automodule:: hdalab.urls
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.utils module
+-------------------
+
+.. automodule:: hdalab.utils
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.wsgi module
+------------------
+
+.. automodule:: hdalab.wsgi
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.templatetags.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,30 @@
+hdalab.templatetags package
+===========================
+
+Submodules
+----------
+
+hdalab.templatetags.analytics module
+------------------------------------
+
+.. automodule:: hdalab.templatetags.analytics
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.templatetags.hdalab\_tags module
+---------------------------------------
+
+.. automodule:: hdalab.templatetags.hdalab_tags
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.templatetags
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/hdalab.views.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,46 @@
+hdalab.views package
+====================
+
+Submodules
+----------
+
+hdalab.views.ajax module
+------------------------
+
+.. automodule:: hdalab.views.ajax
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.views.editorial module
+-----------------------------
+
+.. automodule:: hdalab.views.editorial
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.views.pages module
+-------------------------
+
+.. automodule:: hdalab.views.pages
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+hdalab.views.profile module
+---------------------------
+
+.. automodule:: hdalab.views.profile
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: hdalab.views
+    :members:
+    :undoc-members:
+    :show-inheritance:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/api/modules.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,8 @@
+src
+===
+
+.. toctree::
+   :maxdepth: 4
+
+   hdabo
+   hdalab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/commandes.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,226 @@
+#######################################
+Commandes d'administration HDABo/HDALab
+#######################################
+
+Le projet HDA fournis un ensemble de commande d'administration permettant de maintenir l'état de l'application.
+Ces commandes utilise le `système d'administration en ligne de commande de Django <https://docs.djangoproject.com/en/1.8/howto/custom-management-commands/>`_.
+L'usage des commande est en général le suivant:
+
+```
+django-admin <subcommand> [options] [arguments...]
+```
+
+Chaque commande implémente ses options et arguments.
+Toutes les commandes du projet accèptent les options suivante:
+
+  - *\-\-version* : montre le numeero de version et quitte.
+  - *\-h, \-\-help* : montre le message d'aide et quitte.
+  - *\-v VERBOSITY, \-\-verbosity=VERBOSITY* : Niveau de verbosité; 0=minimal, 1=normal, 2=verbeux, 3=très verbeux
+  - *\-\-settings=SETTINGS* : Le chemin Python vers un module de `settings`. Si il n'est pas fourni, la variable d'environement DJANGO_SETTINGS_MODULE sera utilisée.
+  - *\-\-pythonpath=PYTHONPATH* : un répertoire à ajouter au chemins Python (`Python path <https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH>`_)
+  - *\-\-traceback* : Lève des exceptions `CommandError`.
+  - *\-\-no-color* : Ne colorise pas la sortie de la commande.
+
+Les options spécifiques sont doumentées pour chaque commande.
+
+
+Voici la liste des commandes hdalab:
+
+    - :ref:`commands-hdalab-calculate-preview`
+    - :ref:`commands-hdalab-export-tags-csv`
+    - :ref:`commands-hdalab-export-wpcategory-csv`
+    - :ref:`commands-hdalab-fill-tag-years`
+    - :ref:`commands-hdalab-geojson-transform`
+    - :ref:`commands-hdalab-import-hda-insee-csv`
+    - :ref:`commands-hdalab-import-hdabo-db`
+    - :ref:`commands-hdalab-import-insee-csv`
+    - :ref:`commands-hdalab-query-category-inclusion`
+    - :ref:`commands-hdalab-query-dbpedia`
+    - :ref:`commands-hdalab-query-geo-inclusion`
+    - :ref:`commands-hdalab-query-wikipedia-category`
+    - :ref:`commands-hdalab-send-moderation-mail`
+
+et la liste des commandes hdabo:
+
+    - :ref:`commands-hdabo-clean-tags`
+    - :ref:`commands-hdabo-diff-csv`
+    - :ref:`commands-hdabo-import-csv`
+    - :ref:`commands-hdabo-import-rdf`
+    - :ref:`commands-hdabo-import-tag-popularity`
+    - :ref:`commands-hdabo-order-tags`
+    - :ref:`commands-hdabo-query-wikipedia`
+
+Il est à noter que ce dans cette dernière liste seule la commande :ref:`commands-hdabo-import-rdf` est utilisée régulièrement pour importer les données HDA dans HDALab.
+
+
+Commandes hdabo
+===============
+
+.. _commands-hdabo-clean-tags:
+
+clean\_tags
+-----------
+
+.. automodule:: hdabo.management.commands.clean_tags
+
+
+.. _commands-hdabo-diff-csv:
+
+diff\_csv
+---------
+
+.. automodule:: hdabo.management.commands.diff_csv
+
+
+
+.. _commands-hdabo-import-csv:
+
+import\_csv
+-----------
+
+.. automodule:: hdabo.management.commands.import_csv
+
+
+.. _commands-hdabo-import-rdf:
+
+import\_rdf
+-----------
+
+.. automodule:: hdabo.management.commands.import_rdf
+
+
+.. _commands-hdabo-import-tag-popularity:
+
+import\_tag\_popularity
+-----------------------
+
+.. automodule:: hdabo.management.commands.import_tag_popularity
+
+
+.. _commands-hdabo-order-tags:
+
+order\_tags
+-----------
+
+.. automodule:: hdabo.management.commands.order_tags
+
+
+
+.. _commands-hdabo-query-wikipedia:
+
+query\_wikipedia
+----------------
+
+.. automodule:: hdabo.management.commands.query_wikipedia
+
+
+
+Commandes hdalab
+================
+
+.. _commands-hdalab-calculate-preview:
+
+calculate\_preview
+------------------
+
+.. automodule:: hdalab.management.commands.calculate_preview
+
+
+.. _commands-hdalab-export-tags-csv:
+
+export\_tags\_csv
+-----------------
+
+.. automodule:: hdalab.management.commands.export_tags_csv
+
+
+.. _commands-hdalab-export-wpcategory-csv:
+
+export\_wpcategory\_csv
+-----------------------
+
+.. automodule:: hdalab.management.commands.export_wpcategory_csv
+
+
+.. _commands-hdalab-fill-tag-years:
+
+fill\_tag\_years
+----------------
+
+.. automodule:: hdalab.management.commands.fill_tag_years
+
+
+.. _commands-hdalab-geojson-transform:
+
+geojson\_transform
+------------------
+
+.. automodule:: hdalab.management.commands.geojson_transform
+
+
+
+.. _commands-hdalab-import-hda-insee-csv:
+
+import\_hda\_insee\_csv
+-----------------------
+
+.. automodule:: hdalab.management.commands.import_hda_insee_csv
+
+
+.. _commands-hdalab-import-hdabo-db:
+
+import\_hdabo\_db
+-----------------
+
+.. automodule:: hdalab.management.commands.import_hdabo_db
+
+
+.. _commands-hdalab-import-insee-csv:
+
+import\_insee\_csv
+------------------
+
+.. automodule:: hdalab.management.commands.import_insee_csv
+
+
+
+.. _commands-hdalab-query-category-inclusion:
+
+query\_category\_inclusion
+--------------------------
+
+.. automodule:: hdalab.management.commands.query_category_inclusion
+
+
+.. _commands-hdalab-query-dbpedia:
+
+query\_dbpedia
+--------------
+
+.. automodule:: hdalab.management.commands.query_dbpedia
+
+
+
+.. _commands-hdalab-query-geo-inclusion:
+
+query\_geo\_inclusion
+---------------------
+
+.. automodule:: hdalab.management.commands.query_geo_inclusion
+
+
+.. _commands-hdalab-query-wikipedia-category:
+
+query\_wikipedia\_category
+--------------------------
+
+.. automodule:: hdalab.management.commands.query_wikipedia_category
+
+
+
+.. _commands-hdalab-send-moderation-mail:
+
+send\_moderation\_mail
+----------------------
+
+.. automodule:: hdalab.management.commands.send_moderation_mail
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/conf.py	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/stable/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+
+import django
+
+sys.path.insert(0, os.path.abspath('../../src'))
+sys.setrecursionlimit(1500)
+
+os.environ['DJANGO_SETTINGS_MODULE'] = 'hdalab.settings'
+django.setup()
+
+# -- Project information -----------------------------------------------------
+
+project = u'HDALab'
+copyright = u'2018, IRI'
+author = u'Yves-Marie Haussonne'
+
+# The short X.Y version
+version = u''
+# The full version, including alpha/beta/rc tags
+release = u'3.2.1'
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.todo',
+    'sphinx.ext.viewcode',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = u'fr'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path .
+exclude_patterns = []
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself.  Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ---------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'HDALabdoc'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'HDALab.tex', u'HDALab Documentation',
+     u'ymh', 'manual'),
+]
+
+
+# -- Options for manual page output ------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'hdalab', u'HDALab Documentation',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output ----------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'HDALab', u'HDALab Documentation',
+     author, 'HDALab', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+
+# -- Extension configuration -------------------------------------------------
+
+# -- Options for todo extension ----------------------------------------------
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+# True to prefix each section label with the name of the document it is in, followed by a colon.
+# For example, index:Introduction for a section called Introduction that appears in document index.rst.
+# Useful for avoiding ambiguity when the same section heading appears in different documents.
+
+autosectionlabel_prefix_document = True
+
+
+autodoc_mock_imports = ["haystack.backends.whoosh_backend.SearchBackend"]
+
+html_theme_options = {
+    'logo': 'img/logo_iri.png',
+}
+
+html_sidebars = {
+    '**': [
+        'about.html',
+        'localtoc.html',
+        'relations.html',
+        # 'sourcelink.html',
+        'searchbox.html'
+    ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/dev.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,216 @@
+####################
+Images Docker HDALab
+####################
+
+
+L'application HDALab a été conteneurisée en 5 services dont 2 nécessite
+la construction d'une image. Les services sont orchestrés avec
+l'application ``docker-compose``. L'ensemble expose les ports suivant
+sur l'ordinateur hôte:
+
+  - port 8080 : l'interface web HDALab
+  - port 8025 : Accès à l'interface de consultation `mailhog <https://github.com/mailhog/MailHog>`__.
+  - port 5432 : port serveur postgresql
+
+Mise place des images conteneurs docker
+---------------------------------------
+
+Deux possibilités existent pour mettre en place les images docker :
+  - construire les images
+  - import des images
+
+Construction des images
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Les commandes suivantes permettent de construire les images. Ces
+commandes sont à lancer dans le même répertoire que le fichier
+``docker-compose.yml``.
+
+::
+
+    $ ./prepare_docker_build.sh
+    $ docker-compose -p hdalab build
+
+Import des images
+~~~~~~~~~~~~~~~~~
+
+Lancer cette commande pour charger les images du projet.
+
+::
+
+    $ docker load -i <chemin/vers/fichier/archives/images>
+
+Comment construire les container HDALab
+---------------------------------------
+
+Toutes les commandes suivantes sont à effectuer dans le répertoire
+contenant le fichier ``docker-compose.yml``.
+
+::
+
+    $ docker-compose -p hdalab up -d
+    $ docker-compose -p hdalab exec hdalab django-admin collectstatic --noinput
+    $ docker-compose -p hdalab exec hdalab django-admin migrate --noinput
+    $ docker-compose -p hdalab exec hdalab supervisorctl restart all
+
+Le site est consultable à l'adresse suivante : http://127.0.0.1:8080 Le
+système est fonctionnel mais avec une bases de donnée vide.
+
+Lancement d'une commande Django
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lancer cette commande pour avoir accès à l'utilitaire de gestion Django
+(c.f.
+`django-admin <https://docs.djangoproject.com/en/1.8/ref/django-admin/>`__)
+
+::
+
+    $ docker-compose -p hdalab exec hdalab django-admin <command> [options]
+
+Pour obtenir la liste des commandes disponibles faire:
+
+::
+
+    $ docker-compose -p hdalab exec hdalab django-admin
+
+Création d'un "superuser"
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cette commande permet la creation d'un utilisateur administeur de
+l'application.
+
+::
+
+    $ docker-compose -p hdalab exec hdalab django-admin createsuperuser
+
+Import des données issues de l'export HDA
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cette commande importe les données RDF exportées à partir de
+l'application HDA. Attention cette commande peut être longue (plusieurs
+heures).
+
+::
+
+    $ docker-compose -p hdalab exec hdalab /usr/local/sbin/import_hda_rdf.sh /etc/hdalab/data /var/lib/hdalab http://data.culture.fr/entrepot/HDA/export.tgz
+
+Import d'un dump de l'application
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Import d'un dump de la base de donnée
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Le fichier de dump de base de données doit être décompressé.
+
+::
+
+    $ docker-compose -p hdalab stop hdalab
+    $ docker exec -i hdalab_pg_1 psql -U iri postgres < </chemin/du/fichier/dump/sql.bckp>
+    $ docker-compose -p hdalab start hdalab
+    $ docker-compose -p hdalab exec hdalab django-admin migrate --noinput
+    $ echo "from django.contrib.sites.models import Site; site=Site.objects.all()[0]; site.domain='127.0.0.1:8080'; site.name='HDALab'; site.save()" | docker exec -i hdalab_hdalab_1 django-admin shell
+    $ docker-compose -p hdalab exec hdalab django-admin changepassword admin
+    $ docker-compose -p hdalab exec hdalab django-admin rebuild_index --noinput
+
+Import des miniatures renkan
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Ces commandes supposent que le service ``hdalab`` est actif. L'archive
+comprenant l'export des miniatures doit être décompressé. Cette archive
+contient le répertoire ``media`` à la racine
+
+::
+
+    $ docker cp ./media/. hdalab_hdalab_1:/var/lib/hdalab/static/media
+
+Commandes utiles
+================
+
+liste des services
+------------------
+
+Les services suivants sont définis dans le fichier
+``docker-compose.yml``: - pg : La base de donnée postgresql - es :
+ElasticSearch - mail : Mailhog, fourni un serveur smtp de test - front :
+Le serveur web (nginx) - hdalab : application hdalab comprenant
+l'application web elle-même et les services associés (envoi de mail et
+calcul des preevisualisations Renkan)
+
+Démarrage des services
+----------------------
+
+Les services se contrôlent avec la commande ``docker-compose``. La ligne
+de commande typique est la suivante:
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab [COMMAND] [ARGS...]
+
+Il faut bien noter l'utilisation systématique de l'option ``-p hdalab``
+qui spécifie le nom du projet. Si la commande est lancée dans le même
+répertoire que celui du fichier ``docker-compose.yml`` l'option ``-f``
+peut être ignorée.
+
+Construction des images des conteneurs
+--------------------------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab build [SERVICE...]
+
+création et lancement des services
+----------------------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab up -d [SERVICE...]
+
+A noter l'option ``-d`` qui mettent les services en tache de fond.
+
+lancement des services
+----------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab run SERVICE [COMMAND] [ARGS...]
+
+Cette commande lance un service.
+
+Execution d'une commande sur un service lancé
+---------------------------------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab exec SERVICE COMMAND [ARGS...]
+
+arrêt des services
+------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab stop [SERVICE...]
+
+consulter la sortie des containers
+----------------------------------
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab logs [-f] [SERVICE...]
+
+effacement et recréation de la base de donnée vide
+--------------------------------------------------
+
+Attention, toutes les données de la base seront définitivement
+supprimées.
+
+::
+
+    $ docker-compose [-f </path/to/docker-compose.yml>] -p hdalab stop hdalab
+    $ echo "drop database hdalab;\ncreate database hdalab owner iri encoding 'utf-8';" | docker exec -i hdalab_pg_1 psql -U iri postgres
+
+Accès à la base de donnée
+-------------------------
+
+Le port postgresql 5432 est ouvert sur l'ordinateur hôte. La base
+utilisée par l'application est ``hdalab``. L'utilisateur et mot de passe
+pour y accéder sont : - utilisateur: ``iri`` - mot de passe: ``iri``
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/index.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,27 @@
+.. HDALab documentation master file.
+
+####################
+Documentation HDALab
+####################
+
+Cette documentation couvre le site HDALab.
+
+Ce site est réalise en python et utilise le framework Django (version 1.8).
+
+Cette documentation n'entrera pas dans le détail des fonctionnalités Django et assume donc une connaissance générale de Django par le lecteur.
+Vous pouvez trouver la documentation de Django (version 1.8) à l'url suivante : https://docs.djangoproject.com/en/1.8/.
+
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contenu de cette documentation:
+
+   pages
+   api
+   renkan
+   commandes
+   taches
+   dev
+   Documentation API <api/modules>
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/pages.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,885 @@
+.. Description des pages
+
+############################
+Description des pages HDALab
+############################
+
+Ces pages constituent la navigation principale du site HDALab.
+
+
+Acceuil
+=======
+
+.. image:: _static/img/pages/accueil_hdalab.png
+
+Page d'acceuil d'HDALab.
+
+
++----------+----------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab  |
++----------+----------------------------------------+
+| view     | django.views.generic.TemplateView      |
++----------+----------------------------------------+
+| template | hdalab/templates/index.html            |
++----------+----------------------------------------+
+
+
+
+A propos
+========
+
+.. image:: _static/img/pages/apropos_hdalab.png
+
+Page décrivant le projet HDALab avec une vidéo de tutoriel Renkan.
+
+
++----------+---------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/hdalab/a_propos/  |
++----------+---------------------------------------------------------+
+| view     | :class:`hdalab.views.pages.HdalabAboutPage`             |
++----------+---------------------------------------------------------+
+| template | hdalab/templates/a_propos.html                          |
++----------+---------------------------------------------------------+
+
+
+
+Crédits
+=======
+
+.. image:: _static/img/pages/credits_hdalab.png
+
+Page de crédits du site.
+
+
++----------+--------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/hdalab/credits/  |
++----------+--------------------------------------------------------+
+| view     | django.views.generic.TemplateView                      |
++----------+--------------------------------------------------------+
+| template | hdalab/templates/credits.html                          |
++----------+--------------------------------------------------------+
+
+
+
+
+Mentions légales
+================
+
+.. image:: _static/img/pages/mentions_legales_hdalab.png
+
+Page des mentions légales.
+
++----------+----------------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/hdalab/mentions_legales/ |
++----------+----------------------------------------------------------------+
+| view     | django.views.generic.TemplateView                              |
++----------+----------------------------------------------------------------+
+| template | hdalab/templates/mentions_legales.html                         |
++----------+----------------------------------------------------------------+
+
+
+
+Contact
+=======
+
+.. image:: _static/img/pages/contact_hdalab.png
+
+Formulaire de contact pour poser une question à l'équipe HDALab.
+Cette partie de l'application s'appuie sur le module `django-envelope <https://github.com/zsiciarz/django-envelope>`_.
+
+
++----------+-------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/hdalab/contact/ |
++----------+-------------------------------------------------------+
+| view     | envelope.views.ContactView                            |
++----------+-------------------------------------------------------+
+| template | - hdalab/templates/envelope/contact.html              |
+|          | - hdalab/templates/envelope/email_body.html           |
+|          | - hdalab/templates/envelope/email_body.txt            |
++----------+-------------------------------------------------------+
+
+
+.. _pages_liste_renkan_publics:
+
+Liste des renkan publics
+========================
+
+.. image:: _static/img/pages/renkan_public.png
+
+Page listant l'ensemble des renkan publiés (et modéré).
+
++----------+------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/renkan/public/ |
++----------+------------------------------------------------------+
+| view     | :class:`hdalab.views.profile.RenkanPublicList`       |
++----------+------------------------------------------------------+
+| template | hdalab/templates/renkan_list.html                    |
++----------+------------------------------------------------------+
+
+Note : Les templates hdalab/templates/renkan_list.html et hdalab/templates/renkan_list_favorite.html sont presque les mêmes.
+
+
+.. _pages_liste_renkan_favoris:
+
+Liste des renkan favoris
+========================
+
+.. image:: _static/img/pages/renkan_favorite.png
+
+Page listant l'ensemble des renkan ayant été marqués comme favoris par l'équipe HDALab.
+
++----------+--------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/renkan/favorite/ |
++----------+--------------------------------------------------------+
+| view     | :class:`hdalab.views.profile.RenkanFavoriteList`       |
++----------+--------------------------------------------------------+
+| template | hdalab/templates/renkan_list_favorite.html             |
++----------+--------------------------------------------------------+
+
+Note : Les templates hdalab/templates/renkan_list.html et hdalab/templates/renkan_list_favorite.html sont presque les mêmes.
+
+
+
+.. _pages_recherche_facette:
+
+Recherche (facette)
+===================
+
+.. image:: _static/img/pages/facettes_hdalab.png
+
+Page de recherche par facette.
+Cette page est relativement complexe.
+Elle contient une application javascript permettant l'édition du filtre par facette et l'affichage des résultats.
+
++----------+-------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/facettes/ |
++----------+-------------------------------------------------+
+| view     | django.views.generic.base.TemplateView          |
++----------+-------------------------------------------------+
+| template | hdalab/templates/facettes.html                  |
++----------+-------------------------------------------------+
+
+Le code javascript se trouve dans le fichier `hdalab/static/hdalab/js/gomina.js`.
+Les données pour la page sont chargées par l'url http://hdalab.iri-research.org/hdalab/a/filter.
+L'auto-completion pour la saisie de mot-clef lance des requêtes à l'URL suivante : http://hdalab.iri-research.org/hdalab/a/tagsearch.
+
+Les liens d'édition des renkan sont http://hdalab.iri-research.org/hdalab/renkan/edit/.
+
+
+Détail d'une fiche
+==================
+
+.. image:: _static/img/pages/detail_notice.png
+
+
+cette page affiche le détail d'une notice.
+Elle est contituée des éléments suivant disposés en trois colonnes :
+
+  - Le détail de la notice
+  - La liste des mots-clef de la notice
+  - La liste des notices liées
+
+Lorsqu'on clique sur un mot-clef, la liste dest notices liées est filtrée et n'affiche plus que les notices concernées par le mot-clef.
+
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/notice/{notice_id} |
++----------+----------------------------------------------------------+
+| view     | :func:`hdalab.views.pages.datasheet`                     |
++----------+----------------------------------------------------------+
+| template | hdalab/templates/notice.html                             |
++----------+----------------------------------------------------------+
+
+
+.. _pages_edition_renkan:
+
+Édition d'un renkan
+===================
+
+.. image:: _static/img/pages/renkan_edit.png
+
+Page d'édition et de création d'un renkan.
+Cette page instancie un éditeur de renkan.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/renkan/edit/ |
++----------+----------------------------------------------------+
+| view     | :class:`hdalab.views.profile.RenkanEdit`           |
++----------+----------------------------------------------------+
+| template | hdalab/templates/renkan_edit.html                  |
++----------+----------------------------------------------------+
+
+
+L'éditeur de renkan fait alors appel à l'url suivante pour charger et sauvegarder un projet renkan :
+http://hdalab.iri-research.org/hdalab/renkan/getput/
+
+
+
+.. _affichage-d-un-renkan-en-lecture-seule:
+
+Affichage d'un renkan en lecture seule
+======================================
+
+.. image:: _static/img/pages/renkan_view.png
+
+Page d'affichage d'un renkan en lecture seule.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/renkan/view/ |
++----------+----------------------------------------------------+
+| view     | django.views.generic.base.TemplateView             |
++----------+----------------------------------------------------+
+| template | hdalab/templates/renkan_view.html                  |
++----------+----------------------------------------------------+
+
+Cette page instancie un composant renkan en lecture seule.
+Le projet renkan est chargé par appel (GET) à l'URL http://hdalab.iri-research.org/hdalab/renkan/getput/.
+
+Les arguments d'affichage (par exemple l'identifiant du renkan) sont passés en javascript grâce à la propriété `window.location.search <https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search>`_ (La partie de l'URL qui suit le symbole « ? », avec ce symbole inclus.)
+
+
+
+.. _affichage-d-un-renkan-en-plein-ecran:
+
+Affichage d'un renkan en plein-écran
+====================================
+
+.. image:: _static/img/pages/renkan_view_full.png
+
+Page d'affichage d'un renkan en lecture seule et en plein écran.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/renkan/full/ |
++----------+----------------------------------------------------+
+| view     | django.views.generic.base.TemplateView             |
++----------+----------------------------------------------------+
+| template | hdalab/templates/renkan_view_full.html             |
++----------+----------------------------------------------------+
+
+cette page permet l'affichage d'un renkan en plein-écran, sans les en-tête, pied de page, barre de navigation,...
+Cette page est utilisée pour la création des miniature de prévisualisation des renkan.
+
+Sur le fonctionnement elle est identique à la page ":ref:`affichage-d-un-renkan-en-lecture-seule`, en particulier sur la façon dont les arguments sont passés.
+
+
+
+.. _pages_explorer_domaines_artistiques:
+
+Explorer les domaines artistiques
+=================================
+
+.. image:: _static/img/pages/artistic_domains_hdalab.png
+
+Cette page permet d'explorer les fiches HDA par le biais des domaines artistiques.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/categories/  |
++----------+----------------------------------------------------+
+| view     | django.views.generic.base.TemplateView             |
++----------+----------------------------------------------------+
+| template | hdalab/templates/categories.html                   |
++----------+----------------------------------------------------+
+
+Cette page contient une application javascript s'occupant du chargement de de l'affichage des données.
+Les données sont chargées à l'url suivante : http://hdalab.iri-research.org/hdalab/a/cattree
+Le code javascript de cette page se trouve dans les fichiers `hdalab/static/hdalab/js/trees.js` et `hdalab/static/hdalab/js/cattree.js`.
+
+
+
+.. _pages_recherche_arbre:
+
+Recherche par arbre
+===================
+
+.. image:: _static/img/pages/tree_search_hdalab.png
+
+Cette page permet de comparer deux extraits de thesaurus utilisés par le MCC.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/thesaurus/   |
++----------+----------------------------------------------------+
+| view     | django.views.generic.base.TemplateView             |
++----------+----------------------------------------------------+
+| template | hdalab/templates/thesaurus.html                    |
++----------+----------------------------------------------------+
+
+Cette page contient une application javascript s'occupant du chargement et de l'afficahge des données.
+Les données sont chargées à l'url suivante : http://hdalab.iri-research.org/hdalab/a/filltree
+Le code javascript de cette page se trouve dans les fichiers `hdalab/static/hdalab/js/trees.js` et `hdalab/static/hdalab/js/thesaurus.js`.
+
+
+.. _pages-d-administration-django-hdalab-hdabo:
+
+Pages d'administration Django hdalab/hdabo
+==========================================
+
+.. image:: _static/img/pages/admin_django_hdalab.png
+
+
+Ce sont toutes les pages dont l'URL commence par http://hdalab.iri-research.org/hdalab/hdabo/admin/ .
+Elles nécessitent toute une authentification.
+L'ensemble de ces pages est fournis par l'application d'administration Django fourni d'origine par le framework.
+Le lien suivant en donne une documentation : https://docs.djangoproject.com/en/1.8/ref/contrib/admin/.
+
+Les objets suivant sont configurés pour être administrables:
+
+  - :class:`hdabo.models.Author`
+  - :class:`hdabo.models.Datasheet`
+  - :class:`hdabo.models.DocumentFormat`
+  - :class:`hdabo.models.Domain`
+  - :class:`hdabo.models.Organisation`
+  - :class:`hdabo.models.Tag`
+  - :class:`hdabo.models.TagCategory`
+  - :class:`hdabo.models.TaggedSheet`
+  - :class:`hdabo.models.TimePeriod`
+  - :class:`hdabo.models.User`
+  - `registration.models.RegistrationProfile`
+  - `django.contrib.sites.models import Site`
+
+
+.. _pages_page_profil_utilisateur:
+
+Page profil utilisateur
+=======================
+
+.. image:: _static/img/pages/user_profile_hdalab.png
+
+
+Page de gestion du profile utilisateur.
+Elle permet l'accès à la gestion de ses renkan et de son profile utilisateur.
+Cette page nécessite d'être authentifié.
+
++----------+----------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/profile/     |
++----------+----------------------------------------------------+
+| view     | :class:`hdalab.views.profile.ProfileHome`          |
++----------+----------------------------------------------------+
+| template | hdalab/templates/profile_home.html                 |
++----------+----------------------------------------------------+
+
+Entre outre des fonction de gestion des renkan, cette page donne accès aux liens suivants:
+
+  - http://hdalab.iri-research.org/hdalab/hdabo/accounts/password/change/ : modification du mot de passe.
+  - http://hdalab.iri-research.org/hdalab/profile/update/ : modification des informations utilisateur (c.f. :ref:`changement-information-utilisateur`)
+
+Si l'utilisateur est identifié comme `staff <https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#django.contrib.auth.models.User.is_staff>`_, il a accès aux line supplémentaires:
+
+  - http://hdalab.iri-research.org/hdalab/edito/manage/
+  - http://hdalab.iri-research.org/hdalab/edito/ :
+  - http://hdalab.iri-research.org/hdalab/hdabo/admin/ : :ref:`pages-d-administration-django-hdalab-hdabo`
+  - http://hdalab.iri-research.org/hdalab/hdabo/ : **obsolète**
+
+
+
+
+.. _changement-information-utilisateur:
+
+Changement information utilisateur
+==================================
+
+.. image:: _static/img/pages/user_info_hdalab.png
+
+Page permettant de modifier les information du profile utilisateur. Dans le cas d'HDALab, cela se limite à la modification de l'email de contact.
+Cette page nécessite d'être authentifié.
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/profile/update     |
++----------+----------------------------------------------------------+
+| view     | :class:`hdalab.views.profile.UserProfileUpdate`          |
++----------+----------------------------------------------------------+
+| template | hdalab/templates/hdabo/user_update_form.html             |
++----------+----------------------------------------------------------+
+
+
+Éditorialisation
+================
+
+.. image:: _static/img/pages/editorialisation_hdalab.png
+
+
+Page donnant accès aux fonction de gestion de l'éditorialisation.
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/edito/             |
++----------+----------------------------------------------------------+
+| view     | django.views.generic.base.TemplateView                   |
++----------+----------------------------------------------------------+
+| template | hdalab/templates/editorial/edito_home.html               |
++----------+----------------------------------------------------------+
+
+
+Cette page propose les 2 liens suivants:
+
+  - http://hdalab.iri-research.org/hdalab/edito/folders/ : :ref:`gestion-des-dossiers-thematiques`
+  - http://hdalab.iri-research.org/hdalab/edito/manage/ : :ref:`gestion-des-renkan-moderation`
+
+
+
+
+.. _gestion-des-dossiers-thematiques:
+
+Gestion des dossiers thématiques
+================================
+
+.. image:: _static/img/pages/thematic_folder_hdalab.png
+
+
+Cette page donne accès au tableau des dossiers thématiques.
+
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/edito/folders/     |
++----------+----------------------------------------------------------+
+| view     | :class:`hdalab.views.editorial.HdalabFolders`            |
++----------+----------------------------------------------------------+
+| template | hdalab/templates/editorial/folders.html                  |
++----------+----------------------------------------------------------+
+
+
+
+.. _gestion-des-renkan-moderation:
+
+Gestion des renkan (modération)
+===============================
+
+
+.. image:: _static/img/pages/administrer_renkan.png
+
+Page de modération des renkans.
+
+
++----------+----------------------------------------------------------+
+| url      | http://hdalab.iri-research.org/hdalab/edito/manage/      |
++----------+----------------------------------------------------------+
+| view     | :class:`hdalab.views.editorial.ManageRenkans`            |
++----------+----------------------------------------------------------+
+| template | hdalab/templates/editorial/manage_renkans.html           |
++----------+----------------------------------------------------------+
+
+
+
+.. _pages_liste_renkan:
+
+Pages de liste des Renkan
+=========================
+
+.. image:: _static/img/pages/renkan_base_list.png
+
+Ce sont les pages dont la vue hérite de :class:`hdalab.views.profile.BaseRenkanList`.
+Ces vues permettent de gérer une liste de Renkan avec un système de filtre et de pagination.
+Les actions suivantes sont disponibles :
+
+  - copie : :ref:`pages_copier_renkan`
+  - affichage : :ref:`affichage-d-un-renkan-en-lecture-seule`
+  - modération (si l'utilisateur est autorisé) : :ref:`pages_moderation_renkan`
+  - édition (si l'utilisateur est autorisé) : :ref:`pages_edition_renkan`
+  - effacement (si l'utilisateur est autorisé) : :ref:`pages_effacer_renkan`
+  - favori (si l'utilisateur est autorisé) :  :ref:`pages_favori_renkan`
+  - création d'un nouveau renkan vide : :ref:`pages_nouveau_renkan`
+
+.. autoclass:: hdalab.views.profile.BaseRenkanList
+  :noindex:
+
+Voici la liste des pages héritant de :class:`hdalab.views.profile.BaseRenkanList` :
+
+  - :ref:`gestion-des-renkan-moderation`
+  - :ref:`pages_liste_renkan_publics`
+  - :ref:`pages_liste_renkan_favoris`
+  - :ref:`pages_page_profil_utilisateur`
+
+
+Pages de commande de Renkan
+===========================
+
+Ces pages sont appelées à partir des pages listant les renkan, en particulier celle dont la vue hérite de :class:`hdalab.views.profile.BaseRenkanList`
+
+
+.. _pages_copier_renkan:
+
+Copier un renkan
+----------------
+
+Copie un renkan dont l'id est donné dans l'url.
+L'utilisateur est redirigé vers la page de liste des Renkan.
+
++-------------+-----------------------------------------------------------+
+| url         | http://hdalab.iri-research.org/hdalab/renkan/copy/<rk_id> |
++-------------+-----------------------------------------------------------+
+| view        | :class:`hdalab.views.profile.HdalabRenkanCopy`            |
++-------------+-----------------------------------------------------------+
+| méthode     | POST                                                      |
++-------------+-----------------------------------------------------------+
+| redirection | Page de liste des renkan.                                 |
++-------------+-----------------------------------------------------------+
+
+
+.. automethod:: hdalab.views.profile.HdalabRenkanCopy.post
+  :noindex:
+
+.. _pages_effacer_renkan:
+
+Effacer un renkan
+-----------------
+
+Effacer un renkan dont l'id est donné dans l'URL.
+
++-------------+-------------------------------------------------------------+
+| url         | http://hdalab.iri-research.org/hdalab/renkan/delete/<rk_id> |
++-------------+-------------------------------------------------------------+
+| view        | :class:`hdalab.views.profile.HdalabRenkanDelete`            |
++-------------+-------------------------------------------------------------+
+| méthode     | POST                                                        |
++-------------+-------------------------------------------------------------+
+| redirection | Page de liste des renkan.                                   |
++-------------+-------------------------------------------------------------+
+
+
+.. automethod:: hdalab.views.profile.HdalabRenkanDelete.post
+  :noindex:
+
+
+.. _pages_favori_renkan:
+
+Marquer un renkan comme favori
+------------------------------
+
+Marque comme favori le renkan dont l'id est donné dans l'URL.
+
++-------------+---------------------------------------------------------------+
+| url         | http://hdalab.iri-research.org/hdalab/renkan/favorite/<rk_id> |
++-------------+---------------------------------------------------------------+
+| view        | :class:`hdalab.views.profile.HdalabRenkanFavorite`            |
++-------------+---------------------------------------------------------------+
+| méthode     | POST                                                          |
++-------------+---------------------------------------------------------------+
+| redirection | Page de liste des renkan.                                     |
++-------------+---------------------------------------------------------------+
+
+
+.. automethod:: hdalab.views.profile.HdalabRenkanFavorite.post
+  :noindex:
+
+
+
+.. _pages_moderation_renkan:
+
+Modération d'un renkan
+----------------------
+
+Cette action change l'état d'un Renkan dont l'id est donné dans l'URL.
+
++-------------+---------------------------------------------------------------+
+| url         | http://hdalab.iri-research.org/hdalab/renkan/moderate/<rk_id> |
++-------------+---------------------------------------------------------------+
+| view        | :class:`hdalab.views.profile.HdalabRenkanModerate`            |
++-------------+---------------------------------------------------------------+
+| méthode     | POST                                                          |
++-------------+---------------------------------------------------------------+
+| redirection | Page de liste des renkan.                                     |
++-------------+---------------------------------------------------------------+
+
+
+.. automethod:: hdalab.views.profile.HdalabRenkanModerate.post
+  :noindex:
+
+.. _pages_nouveau_renkan:
+
+Création d'un nouveau renkan
+----------------------------
+
+Crée un nouveau renkan vide. L'utilisateur est redirigé vers la page d'édition du renkan (:ref:`pages_edition_renkan`)
+
++-------------+--------------------------------------------------+
+| url         | http://hdalab.iri-research.org/hdalab/renkan/new |
++-------------+--------------------------------------------------+
+| view        | :class:`hdalab.views.profile.RenkanNew`          |
++-------------+--------------------------------------------------+
+| méthode     | POST                                             |
++-------------+--------------------------------------------------+
+| redirection | :ref:`pages_edition_renkan`                      |
++-------------+--------------------------------------------------+
+
+
+.. automethod:: hdalab.views.profile.RenkanNew.post
+  :noindex:
+
+
+Pages de gestion des comptes utilisateurs
+=========================================
+
+Ce sont toutes les pages dont l'URL commence par http://hdalab.iri-research.org/hdalab/hdabo/accounts/ .
+Ces URL sont fournies par des librariries externe :
+
+
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| base d'URL                                                      | librairie / lien de documentation                                              |
++=================================================================+================================================================================+
+| http://hdalab.iri-research.org/hdalab/hdabo/accounts/activate/  | `django-registration-redux <https://github.com/macropin/django-registration>`_ |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/hdabo/accounts/register/  | `django-registration-redux <https://github.com/macropin/django-registration>`_ |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/login                     | `django.contrib.auth <https://docs.djangoproject.com/en/1.8/topics/auth/>`_    |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/logout                    | `django.contrib.auth <https://docs.djangoproject.com/en/1.8/topics/auth/>`_    |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/password                  | `django.contrib.auth <https://docs.djangoproject.com/en/1.8/topics/auth/>`_    |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/password_change           | `django.contrib.auth <https://docs.djangoproject.com/en/1.8/topics/auth/>`_    |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+| http://hdalab.iri-research.org/hdalab/password_reset            | `django.contrib.auth <https://docs.djangoproject.com/en/1.8/topics/auth/>`_    |
++-----------------------------------------------------------------+--------------------------------------------------------------------------------+
+
+
+La librairie `django-registration-redux <https://github.com/macropin/django-registration>`_ offre en particulier la fonctionalité d'inscription sur le site et la vérification de l'email.
+
+En outre les 2 URL suivantes sont disponibles afin de faciliter l'authentification à partir de la page d'édition d'un renkan et d'éviter un rechargement de page.
+
+
+  - +----------+----------------------------------------------------------+
+    | url      | http://hdalab.iri-research.org/hdalab/ajaxlogin/         |
+    +----------+----------------------------------------------------------+
+    | view     | :func:`hdalab.views.profile.ajax_login`                  |
+    +----------+----------------------------------------------------------+
+
+  - +----------+----------------------------------------------------------+
+    | url      | http://hdalab.iri-research.org/hdalab/edito/manage/      |
+    +----------+----------------------------------------------------------+
+    | view     | django.views.generic.base.TemplateView                   |
+    +----------+----------------------------------------------------------+
+    | template | hdalab/templates/ajax_identification/ajax_login_ok.html  |
+    +----------+----------------------------------------------------------+
+
+
+
+Pages hdabo
+===========
+
+Ce sont toute les pages dont l'URL commence par `http://hdalab.iri-research.org/hdalab/hdabo/` et qui ne sont pas dans la liste d'excption donnée ci-dessous.
+
+Ces pages sont aujourd'hui obsolètes.
+Elles ont été inclues dans le plan d'url HDALab pour référence, mais ne sont plus utiles.
+
+Elles ont permit le premier traitement sémantique des données HDA pour le projet HDALab.
+Cette fonctionnalité est aujourd'hui directement intégré au portail HDA par l'intermédiaire du module symfony `WikiTagBundle <https://github.com/IRI-Research/WikiTagBundle>`_.
+
+Les données HDA sont régulièrement importées dans HDALab par la commande :class:`hdalab.management.commands.import_hdabo_db`.
+
+Liste d'exception des pages hdabo non obsolètes :
+    - http://hdalab.iri-research.org/hdalab/hdabo/searchajax/
+    - http://hdalab.iri-research.org/hdalab/hdabo/admin/*
+    - http://hdalab.iri-research.org/hdalab/hdabo/account/*
+
+
+
+..
+    /i18n/setlang/	django.views.i18n.set_language	set_language
+    /jsi18n/	django.views.i18n.javascript_catalog	jsi18n.all
+    /jsi18n/<packages>/	django.views.i18n.javascript_catalog	jsi18n
+
+
+    /renkan/copy/<rk_id>	hdalab.views.profile.HdalabRenkanCopy	renkan_copy	login_required
+    /renkan/delete/<rk_id>	hdalab.views.profile.HdalabRenkanDelete	renkan_delete	login_required
+    /renkan/favorite/<rk_id>	hdalab.views.profile.HdalabRenkanFavorite	renkan_favorite	login_required
+    /renkan/moderate/<rk_id>	hdalab.views.profile.HdalabRenkanModerate	renkan_moderate	login_required
+
+    /renkan/new/	hdalab.views.profile.RenkanNew	renkan_new	login_required
+
+
+
+    Fait:
+
+    /renkan/edit/	hdalab.views.profile.RenkanEdit	renkan_edit
+    /renkan/getput/	hdalab.views.profile.HdalabRenkanGetPut	renkan_get_put
+
+    /profile/	hdalab.views.profile.ProfileHome	profile_home	login_required
+    /profile/update/	hdalab.views.profile.UserProfileUpdate	profile_update	login_required
+
+    /notice/<hda_id>	hdalab.views.pages.datasheet	notice
+
+    /a/catsearch	hdalab.views.ajax.catsearch	cat_search
+    /a/cattree	hdalab.views.ajax.cattree	cat_tree
+    /a/filltree	hdalab.views.ajax.filltree	fill_tree
+    /a/filter	hdalab.views.ajax.filter	filter
+    /a/tagsearch	hdalab.views.ajax.tagsearch	tag_search
+
+
+    /edito/deletefolder/<folder_pk>	hdalab.views.editorial.HdalabDeleteFolder	hdalab_delete_folder	login_required
+    /edito/folder/	hdalab.views.editorial.HdalabAddOrUpdateFolder	hdalab_add_or_update_folder	login_required
+    /edito/folder/<folder_pk>	hdalab.views.editorial.HdalabAddOrUpdateFolder	hdalab_add_or_update_folder	login_required
+    /edito/folders/	hdalab.views.editorial.HdalabFolders	hdalab_folders	login_required
+    /edito/manage/	hdalab.views.editorial.ManageRenkans	manage_renkans	login_required
+
+    /facettes/	django.views.generic.base.TemplateView	facettes
+
+
+    /hdalab/a_propos/	hdalab.views.pages.HdalabAboutPage	a_propos
+    /hdalab/contact/	envelope.views.ContactView	envelope-contact
+    /hdalab/credits/	django.views.generic.base.TemplateView	credits
+    /hdalab/mentions_legales/	django.views.generic.base.TemplateView	mentions_legales
+    /thesaurus/	django.views.generic.base.TemplateView	thesaurus
+
+
+    /hdabo/admin/	django.contrib.admin.sites.index	admin:index
+    /hdabo/admin/<app_label>/	django.contrib.admin.sites.app_index	admin:app_list
+    /hdabo/admin/auth/group/	django.contrib.admin.options.changelist_view	admin:auth_group_changelist
+    /hdabo/admin/auth/group/<var>/	django.contrib.admin.options.change_view	admin:auth_group_change
+    /hdabo/admin/auth/group/<var>/delete/	django.contrib.admin.options.delete_view	admin:auth_group_delete
+    /hdabo/admin/auth/group/<var>/history/	django.contrib.admin.options.history_view	admin:auth_group_history
+    /hdabo/admin/auth/group/add/	django.contrib.admin.options.add_view	admin:auth_group_add
+    /hdabo/admin/hdabo/author/	django.contrib.admin.options.changelist_view	admin:hdabo_author_changelist
+    /hdabo/admin/hdabo/author/<var>/	django.contrib.admin.options.change_view	admin:hdabo_author_change
+    /hdabo/admin/hdabo/author/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_author_delete
+    /hdabo/admin/hdabo/author/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_author_history
+    /hdabo/admin/hdabo/author/add/	django.contrib.admin.options.add_view	admin:hdabo_author_add
+    /hdabo/admin/hdabo/datasheet/	django.contrib.admin.options.changelist_view	admin:hdabo_datasheet_changelist
+    /hdabo/admin/hdabo/datasheet/<var>/	django.contrib.admin.options.change_view	admin:hdabo_datasheet_change
+    /hdabo/admin/hdabo/datasheet/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_datasheet_delete
+    /hdabo/admin/hdabo/datasheet/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_datasheet_history
+    /hdabo/admin/hdabo/datasheet/add/	django.contrib.admin.options.add_view	admin:hdabo_datasheet_add
+    /hdabo/admin/hdabo/documentformat/	django.contrib.admin.options.changelist_view	admin:hdabo_documentformat_changelist
+    /hdabo/admin/hdabo/documentformat/<var>/	django.contrib.admin.options.change_view	admin:hdabo_documentformat_change
+    /hdabo/admin/hdabo/documentformat/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_documentformat_delete
+    /hdabo/admin/hdabo/documentformat/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_documentformat_history
+    /hdabo/admin/hdabo/documentformat/add/	django.contrib.admin.options.add_view	admin:hdabo_documentformat_add
+    /hdabo/admin/hdabo/domain/	django.contrib.admin.options.changelist_view	admin:hdabo_domain_changelist
+    /hdabo/admin/hdabo/domain/<var>/	django.contrib.admin.options.change_view	admin:hdabo_domain_change
+    /hdabo/admin/hdabo/domain/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_domain_delete
+    /hdabo/admin/hdabo/domain/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_domain_history
+    /hdabo/admin/hdabo/domain/add/	django.contrib.admin.options.add_view	admin:hdabo_domain_add
+    /hdabo/admin/hdabo/organisation/	django.contrib.admin.options.changelist_view	admin:hdabo_organisation_changelist
+    /hdabo/admin/hdabo/organisation/<var>/	django.contrib.admin.options.change_view	admin:hdabo_organisation_change
+    /hdabo/admin/hdabo/organisation/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_organisation_delete
+    /hdabo/admin/hdabo/organisation/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_organisation_history
+    /hdabo/admin/hdabo/organisation/add/	django.contrib.admin.options.add_view	admin:hdabo_organisation_add
+    /hdabo/admin/hdabo/tag/	django.contrib.admin.options.changelist_view	admin:hdabo_tag_changelist
+    /hdabo/admin/hdabo/tag/<var>/	django.contrib.admin.options.change_view	admin:hdabo_tag_change
+    /hdabo/admin/hdabo/tag/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_tag_delete
+    /hdabo/admin/hdabo/tag/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_tag_history
+    /hdabo/admin/hdabo/tag/add/	django.contrib.admin.options.add_view	admin:hdabo_tag_add
+    /hdabo/admin/hdabo/tagcategory/	django.contrib.admin.options.changelist_view	admin:hdabo_tagcategory_changelist
+    /hdabo/admin/hdabo/tagcategory/<var>/	django.contrib.admin.options.change_view	admin:hdabo_tagcategory_change
+    /hdabo/admin/hdabo/tagcategory/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_tagcategory_delete
+    /hdabo/admin/hdabo/tagcategory/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_tagcategory_history
+    /hdabo/admin/hdabo/tagcategory/add/	django.contrib.admin.options.add_view	admin:hdabo_tagcategory_add
+    /hdabo/admin/hdabo/taggedsheet/	django.contrib.admin.options.changelist_view	admin:hdabo_taggedsheet_changelist
+    /hdabo/admin/hdabo/taggedsheet/<var>/	django.contrib.admin.options.change_view	admin:hdabo_taggedsheet_change
+    /hdabo/admin/hdabo/taggedsheet/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_taggedsheet_delete
+    /hdabo/admin/hdabo/taggedsheet/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_taggedsheet_history
+    /hdabo/admin/hdabo/taggedsheet/add/	django.contrib.admin.options.add_view	admin:hdabo_taggedsheet_add
+    /hdabo/admin/hdabo/timeperiod/	django.contrib.admin.options.changelist_view	admin:hdabo_timeperiod_changelist
+    /hdabo/admin/hdabo/timeperiod/<var>/	django.contrib.admin.options.change_view	admin:hdabo_timeperiod_change
+    /hdabo/admin/hdabo/timeperiod/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_timeperiod_delete
+    /hdabo/admin/hdabo/timeperiod/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_timeperiod_history
+    /hdabo/admin/hdabo/timeperiod/add/	django.contrib.admin.options.add_view	admin:hdabo_timeperiod_add
+    /hdabo/admin/hdabo/user/	django.contrib.admin.options.changelist_view	admin:hdabo_user_changelist
+    /hdabo/admin/hdabo/user/<var>/	django.contrib.admin.options.change_view	admin:hdabo_user_change
+    /hdabo/admin/hdabo/user/<var>/delete/	django.contrib.admin.options.delete_view	admin:hdabo_user_delete
+    /hdabo/admin/hdabo/user/<var>/history/	django.contrib.admin.options.history_view	admin:hdabo_user_history
+    /hdabo/admin/hdabo/user/<var>/password/	django.contrib.auth.admin.user_change_password	admin:auth_user_password_change
+    /hdabo/admin/hdabo/user/add/	django.contrib.auth.admin.add_view	admin:hdabo_user_add
+    /hdabo/admin/jsi18n/	django.contrib.admin.sites.i18n_javascript	admin:jsi18n
+    /hdabo/admin/login/	django.contrib.admin.sites.login	admin:login
+    /hdabo/admin/logout/	django.contrib.admin.sites.logout	admin:logout
+    /hdabo/admin/password_change/	django.contrib.admin.sites.password_change	admin:password_change
+    /hdabo/admin/password_change/done/	django.contrib.admin.sites.password_change_done	admin:password_change_done
+    /hdabo/admin/r/<content_type_id>/<object_id>/	django.contrib.contenttypes.views.shortcut	admin:view_on_site
+    /hdabo/admin/registration/registrationprofile/	django.contrib.admin.options.changelist_view	admin:registration_registrationprofile_changelist
+    /hdabo/admin/registration/registrationprofile/<var>/	django.contrib.admin.options.change_view	admin:registration_registrationprofile_change
+    /hdabo/admin/registration/registrationprofile/<var>/delete/	django.contrib.admin.options.delete_view	admin:registration_registrationprofile_delete
+    /hdabo/admin/registration/registrationprofile/<var>/history/	django.contrib.admin.options.history_view	admin:registration_registrationprofile_history
+    /hdabo/admin/registration/registrationprofile/add/	django.contrib.admin.options.add_view	admin:registration_registrationprofile_add
+    /hdabo/admin/sites/site/	django.contrib.admin.options.changelist_view	admin:sites_site_changelist
+    /hdabo/admin/sites/site/<var>/	django.contrib.admin.options.change_view	admin:sites_site_change
+    /hdabo/admin/sites/site/<var>/delete/	django.contrib.admin.options.delete_view	admin:sites_site_delete
+    /hdabo/admin/sites/site/<var>/history/	django.contrib.admin.options.history_view	admin:sites_site_history
+    /hdabo/admin/sites/site/add/	django.contrib.admin.options.add_view	admin:sites_site_add
+
+    /hdabo/accounts/activate/<activation_key>/	registration.backends.default.views.ActivationView	registration_activate
+    /hdabo/accounts/activate/complete/	django.views.generic.base.TemplateView	registration_activation_complete
+    /hdabo/accounts/login/	django.contrib.auth.views.login	auth_login
+    /hdabo/accounts/login/	django.contrib.auth.views.login	login
+    /hdabo/accounts/logout/	django.contrib.auth.views.logout	auth_logout	login_required
+    /hdabo/accounts/logout/	django.contrib.auth.views.logout	logout	login_required
+    /hdabo/accounts/password/change/	django.contrib.auth.views.password_change	auth_password_change
+    /hdabo/accounts/password/change/done/	django.contrib.auth.views.password_change_done	auth_password_change_done	login_required
+    /hdabo/accounts/password/reset/	django.contrib.auth.views.password_reset	auth_password_reset
+    /hdabo/accounts/password/reset/complete/	django.contrib.auth.views.password_reset_complete	auth_password_reset_complete	login_required
+    /hdabo/accounts/password/reset/confirm/<uidb64>/<token>/	django.contrib.auth.views.password_reset_confirm	auth_password_reset_confirm
+    /hdabo/accounts/password/reset/confirm/<uidb64>/<token>/	django.contrib.auth.views.password_reset_confirm	auth_password_reset_confirm
+    /hdabo/accounts/password/reset/done/	django.contrib.auth.views.password_reset_done	auth_password_reset_done	login_required
+    /hdabo/accounts/password_change/	django.contrib.auth.views.password_change	password_change
+    /hdabo/accounts/password_change/done/	django.contrib.auth.views.password_change_done	password_change_done	login_required
+    /hdabo/accounts/password_reset/	django.contrib.auth.views.password_reset	password_reset
+    /hdabo/accounts/password_reset/done/	django.contrib.auth.views.password_reset_done	password_reset_done	login_required
+    /hdabo/accounts/register/	registration.backends.default.views.RegistrationView	registration_register
+    /hdabo/accounts/register/closed/	django.views.generic.base.TemplateView	registration_disallowed
+    /hdabo/accounts/register/complete/	django.views.generic.base.TemplateView	registration_complete
+    /hdabo/accounts/reset/<uidb64>/<token>/	django.contrib.auth.views.password_reset_confirm	password_reset_confirm
+    /hdabo/accounts/reset/done/	django.contrib.auth.views.password_reset_complete	password_reset_complete	login_required
+
+    /ajaxlogin/	hdalab.views.profile.ajax_login	ajax_login
+    /ajaxloginok/	django.views.generic.base.TemplateView	ajax_login_ok
+
+    /categories/	django.views.generic.base.TemplateView	categories
+
+
+    /static/media/<path>	django.views.static.serve
+
+
+    /renkan/favorite/	hdalab.views.profile.RenkanFavoriteList	renkan_favorite_list
+    /renkan/public/	hdalab.views.profile.RenkanPublicList	renkan_public_list
+    /renkan/view/	django.views.generic.base.TemplateView	renkan_view
+    /renkan/full/	django.views.generic.base.TemplateView	renkan_full
+
+
+    /edito/	django.views.generic.base.TemplateView	edito_home	login_required
+
+
+    /hdabo/	hdabo.views.home	hdabo_home	login_required
+
+    /hdabo/addtag	hdabo.views.add_tag		login_required
+
+    /hdabo/alltags/	hdabo.views.all_tags		login_required
+    /hdabo/alltags/<num_page>/	hdabo.views.all_tags		login_required
+    /hdabo/alltags/<num_page>/<nb_by_page>/	hdabo.views.all_tags		login_required
+    /hdabo/alltags/<num_page>/<nb_by_page>/<sort>/	hdabo.views.all_tags		login_required
+    /hdabo/alltags/<num_page>/<nb_by_page>/<sort>/<searched>/	hdabo.views.all_tags		login_required
+
+    /hdabo/data	hdabo.views.display_datasheet	display_datasheet	login_required
+    /hdabo/data/<ds_id>	hdabo.views.display_datasheet	display_datasheet	login_required
+
+    /hdabo/deletefolder/<folder_pk>	hdabo.views.DeleteFolder	delete_folder	login_required
+
+    /hdabo/folder/	hdabo.views.AddOrUpdateFolder	add_or_update_folder	login_required
+    /hdabo/folder/<folder_pk>	hdabo.views.AddOrUpdateFolder	add_or_update_folder	login_required
+    /hdabo/folders/	hdabo.views.Folders	folders	login_required
+
+    /hdabo/list/	hdabo.views.orga_list	orga_list	login_required
+    /hdabo/list/<orga_id>	hdabo.views.list_for_orga	list_for_orga	login_required
+    /hdabo/list/<orga_id>/<valid>/	hdabo.views.list_for_orga	list_for_orga	login_required
+    /hdabo/list/<orga_id>/<valid>/<start_index>/	hdabo.views.list_for_orga	list_for_orga	login_required
+    /hdabo/list/<orga_id>/<valid>/<start_index>/<length>/	hdabo.views.list_for_orga	list_for_orga	login_required
+
+    /hdabo/logout/	django.contrib.auth.views.logout_then_login		login_required
+
+    /hdabo/modifytag	hdabo.views.modify_tag		login_required
+    /hdabo/modifytagds	hdabo.views.modify_tag_datasheet		login_required
+
+    /hdabo/ordertagsdatasheet	hdabo.views.reorder_tag_datasheet		login_required
+
+    /hdabo/removetagfromlist	hdabo.views.remove_tag_from_list		login_required
+    /hdabo/removewplink	hdabo.views.remove_wp_link		login_required
+    /hdabo/resetwpinfo	hdabo.views.reset_wikipedia_info		login_required
+
+    /hdabo/search/	haystack.views.SearchView()	haystack_search
+    /hdabo/searchajax/	hdabo.views.SearchDatasheet()	searchajax
+
+    /hdabo/tagupdown	hdabo.views.tag_up_down		login_required
+
+    /hdabo/updatetagalias	hdabo.views.update_tag_alias		login_required
+    /hdabo/updatetagcategory	hdabo.views.update_tag_category		login_required
+
+    /hdabo/validatedatasheet	hdabo.views.validate_datasheet		login_required
+    /hdabo/validatedatasheet/<ds_id>	hdabo.views.validate_datasheet		login_required
+    /hdabo/validatedatasheet/<ds_id>/<valid>/	hdabo.views.validate_datasheet		login_required
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/renkan.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,199 @@
+.. description des renkan
+
+##############################
+Description de l'outils renkan
+##############################
+
+Introduction
+============
+
+Renkan est un outil d'édition et d'affichage de carte mentale.
+
+Il a été conçu de façon modulaire et avec une claire separation entre la partie cliente en javascript et la partie serveur.
+
+En particulier la partie du client en charge des communications avec le serveur (chargement des projets, gestion de la persistance) est totalement modulaire et configurable.
+Cela permet d'adapter facilement le client à l'api de sauvegarde du serveur.
+
+
+Modèle de donnée serveur (HDALab)
+=================================
+
+Le modèle de donnée du coté serveur est simple.
+En effet le serveur ne cherche pas à interpréter le contenu d'un renkan.
+Il se content de sauvegarder le contenu qui lui est transmis par le client et dans l'autre sens de transmettre directement au client le contenu sauvegardé en base.
+Toute l'interprétation du modèle se fait dans le client.
+
+Classe renkanmanager.models.Renkan
+----------------------------------
+
+*class* ``renkanmanager.models.``\ **Renkan** :
+
+    Classe de base d'un renkan.
+
+    Champs de l'objet:
+
+      - **owner** (`object`) : Le propriétaire (créateur) du renkan.
+      - **rk_id** (`str`) : id du renkan.
+      - **content** (`str`) : contenu du renkan (la chaine JSON brute).
+      - **title** (`str`) : titre du renkan.
+      - **image** (`str`) : chemin vers l'image miniature du renkan.
+      - **creation_date** (`datetime`) : date de création.
+      - **modification_date** (`datetime`) : date de modification.
+
+
+Classe hdalab.models.renkan.HdalabRenkan
+----------------------------------------
+
+.. autoclass:: hdalab.models.renkan.HdalabRenkan
+  :noindex:
+
+
+Format renkan
+=============
+
+Un renkan a le format suivant:
+
+  exemple ::
+
+    {
+        "id": "f4d002b7-d4fd-486c-8898-6c6ceebc3354",
+        "schema_version": 2, #version of schema, latest is 2.
+        "title": "Example of Renkan with movies",
+        "description": "A long description",
+        "created": "2013-03-18T11:32:40.253+01:00",
+        "updated": "2014-02-04T15:12:56.619+01:00",
+        "nodes": [
+            {
+                "id": "node-2013-05-08-72c911bafdf9932c-0001",
+                "title": "Une femme mène l'enquête",
+                "description": "La caméra suit la femme qui marche\nJeu avec la caméra qui se substitue au spectateur",
+                "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/lyceehulst_3extraits/c8a61ee4-b33c-11e2-802c-00145ea4a2be#id=s_DCA8D184-EFC2-314B-0F6B-84043E8F9984",
+                "style": { #optional
+                    "color": "#ff7f00", #line color, optional (null)
+                    "thickness": 1, #thickness of the line, optional (1)
+                    "dash": false, #dashed line, optional (false)
+                },
+                "position": {
+                    "x": -547.0499881440252,
+                    "y": -221.5401229374163
+                },
+                "image": "http://ldt.iri.centrepompidou.fr/static/site/ldt/css/imgs/video_sequence.png",
+                "size": 0,
+                "project_id": "f4d002b7-d4fd-486c-8898-6c6ceebc3354",
+                "created_by": "de68xf75y6hs5rgjhgghxbm217xk",
+                "type": "...",
+                "hidden": false,
+                "shape": "circle",
+            },
+            ...
+        ],
+        "edges": [
+            {
+                "id": "edge-2013-05-08-72c911bafdf9932c-0002",
+                "title": "",
+                "description": "",
+                "uri": "",
+                "style": { #optional
+                    "color": "#ff7f00", #line color, optional (null)
+                    "thickness": 1, #thickness of the line, optional (1)
+                    "dash": false, #dashed line, optional (false)
+                    "arrow": true,  #draw the arrow, optional (true)
+                },
+                "from": "node-2013-04-30-a81adec6694db5f4-0032",
+                "to": "node-2013-05-08-72c911bafdf9932c-0001",
+                "project_id": "f4d002b7-d4fd-486c-8898-6c6ceebc3354",
+                "created_by": "de68xf75y6hs5rgjhgghxbm217xk"
+            },
+            ...
+        ],
+        "users": [ #optional
+            {
+                "userId": "user-2015-05-05-72c911bafdf9932c-0001",
+                "color": "#cc9866",
+                "username": "user1",
+                "anonymous": true
+            },
+        ...
+        ],
+        "space_id": "17f968e4-2640-4319-aa61-b5b8b527ebb4", #Optional
+        "views": [ #Optional
+            {
+                "zoom_level": 0.8275032552816195,
+                "offset_x": 832.0104075533723,
+                "offset_y": 402.8917139487223
+            }
+        ]
+    }
+
+Système de chutier
+==================
+
+Renkan propose un système de "chutier". C'est un système de liste d'élément ouvert à gauche d'un renkan en édition.
+
+On le voit à gauche sur l'image suivante :
+
+.. image:: _static/img/renkan/renkan_edition.png
+
+Ce système permet d'ajouter rapidement des resources fiches ou tag par "glisser/déposer".
+Techniquement, ces fonctionalités de chutiers propres à HDALab sont définies dans le fichier `hdalab/static/hdalab/js/hdalab-renkan-bins.js`.
+
+
+.. _renkan_boite_recherche_contenus:
+
+Boite de recherche de contenus
+------------------------------
+
+.. image:: _static/img/renkan/renkan_recherche_contenus.png
+
+
+Cette boite de recherche permet de lancer une requête sur 3 types de ressources:
+  - recherche de tag
+  - recherche de fiches
+  - recherche d'article wikipedia
+
+  +--------------------+----------------------------------------------------------+--------------------------------------+
+  | type               | url de requête                                           | Vue                                  |
+  +====================+==========================================================+======================================+
+  | tags               | http://hdalab.iri-research.org/hdalab/a/tagsearch?       | :func:`hdalab.views.ajax.tagsearch`  |
+  +--------------------+----------------------------------------------------------+--------------------------------------+
+  | fiches             | http://hdalab.iri-research.org/hdalab/hdabo/searchajax/? | :class:`hdabo.views.SearchDatasheet` |
+  +--------------------+----------------------------------------------------------+--------------------------------------+
+  | articles wikipedia | https://fr.wikipedia.org/w/api.php?action=query...       |                                      |
+  +--------------------+----------------------------------------------------------+--------------------------------------+
+
+Le resultat de la recherche est affiché dans un nouvel onglet listant les ressources.
+
+
+Boite de recherche sur les résultats
+------------------------------------
+
+.. image:: _static/img/renkan/renkan_recherche_resultats.png
+
+Cette boite de recherche permet de rechercher et de filtrer des résultats déjà présent dans les onglets. La recherche est uniquement locale et ne lance fait pas de requête http.
+
+
+Liste de ressource
+------------------
+
+.. image:: _static/img/renkan/renkan_bin_resources.png
+
+Cet onglet liste des ressources statiques qui peuvent être utiles à l'édition du renkan.
+
+
+Liste de ressource supplémentaire
+---------------------------------
+
+.. image:: _static/img/renkan/renkan_bin_plus_ressources.png
+
+Cet onglet liste des ressources "supplémentaires".
+Un renkan est souvent créé à partir du résultat d'une recherche sur la page de `recherche par facette <pages_recherche_facette>`.
+Pour éviter d'avoir trop de noeuds ressources, les 8 premiers résultats de la recherche sont utilisés dans le renkan et les 10 suivants sont utilisés dans ce chutier.
+(ce comportement est défini dans la méthode :func:`hdalab.views.profile.HdalabRenkanGetPut.get`).
+
+
+Sauvegarde des renkan
+=====================
+
+la sauvegarde des renkan est définie dans le fichier `hdalab/static/hdalab/js/renkan-manual-save.js`.
+La sauvegarde est déclenchée par une action de l'utilisateur.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/taches.rst	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,34 @@
+####################
+Taches Celery HDALab
+####################
+
+Ces tâches longues sont lancées de façon asynchrone par `Celery <http://www.celeryproject.org/>`_.
+
+Liste des tâches asynchrones:
+
+  - :ref:`taches-hdalab-tasks-capture_preview`
+  - :ref:`taches-djcelery_email_send_multiple`
+
+
+.. _taches-hdalab-tasks-capture_preview:
+
+hdalab.tasks.capture_preview
+----------------------------
+
+Crée un snapshot d'un renkan.
+La tache est un simple wrapper qui appelle :func:`hdalab.services.renkan_capture_preview`.
+
+.. autofunction:: hdalab.services.renkan_capture_preview
+  :noindex:
+
+.. _taches-djcelery_email_send_multiple:
+
+djcelery_email_send_multiple
+----------------------------
+
+Envoi asynchrone d'email.
+Cette tâche est fournie par la librairie `django-celery-email <https://github.com/pmclanahan/django-celery-email>`_.
+C'est un backend Django qui utilise une queue `Celery`_ pour envoyer les messages de façon asynchrone, libérant ainsi le thread de traitement de requête.
+
+
+
--- a/src/hdabo/management/commands/clean_tags.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/clean_tags.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,9 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jun 20, 2012
+Retire les tags orphelins et fusionne les tags dupliqués (la clef étant l'URI DBPedia).
 
-@author: ymh
+**Usage**: ``django-admin clean_tags [options]``
+
 '''
 from django.core.management.base import NoArgsCommand
 from django.core.management.color import no_style
@@ -17,7 +18,7 @@
 
 class Command(NoArgsCommand):
     '''
-    remove orphan tags and merge duplicates (the key is the dbpedia uri) 
+    remove orphan tags and merge duplicates (the key is the dbpedia uri)
     '''
 
 
@@ -29,7 +30,7 @@
         # merge duplicate tags
         cursor = connection.cursor()
         cursor.execute("select label, dbpedia_uri from hdabo_tag group by label,dbpedia_uri having count(label) > 1")
-        
+
         for label,_ in cursor:
             qs = Tag.objects.filter(label=label).annotate(num_ds=Count('datasheet')).order_by('-num_ds')
             ref_tag = None
@@ -43,14 +44,13 @@
                         print("changing tag %d to %d" %(ts.tag.id, ref_tag.id) )
                         ts.tag = ref_tag
                         ts.save()
-        
+
         # remove ophans tags
-        
+
         orphans_tags = Tag.objects.annotate(num_ds=Count('datasheet')).filter(num_ds=0)
-        
+
         print("nb Orphans : %d" % orphans_tags.count())
-                
+
         #delete
         orphans_tags.delete()
 
-        
\ No newline at end of file
--- a/src/hdabo/management/commands/diff_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/diff_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,17 @@
 # -*- coding: utf-8 -*-
 '''
-Created on May 25, 2011
+Permet d'afficher (et optionellement d'effacer) les fiches se trouvant dans la base de données et pas dans le fichiers CSV.
+
+**Usage**: ``django-admin diff_csv [options] <path_to_csv_file path_to_csv_file ...>``
+
+**Options spécifiques:**
 
-@author: ymh
+    - *\-\-encoding=ENCODING* : encodage des fichiers CSV (défaut ``latin-1``)
+    - *\-\-delimiter=DELIMITER* : Séparateur des fichiers CSV
+    - *\-\-dialect=DIALECT* : Dialecte fichier CSV (c.f. `Dialectes Python CSV <https://docs.python.org/2/library/csv.html#csv-fmt-params>`_)
+    - *\-\-fieldnames=FIELDNAMES* : liste des noms de champ à traiter (séparateur : ``,``)
+    - *\-\-do\-delete* : efface les fiches se trouvant dans la base mais pas dans le fichier CSV.
+
 '''
 #Auteur,Chemin,Comment,Controle,Datcre,Datmaj,Desc,Domaine,Format,ID,Insee,Org,Org_Home,OrgID,Periode1,Periode2,Periode3,Satut,Sousdom,Tag,Theme2,Theme3,Titre,Url,Vignette,Ville
 #"Auteur","Chemin","Comment","Controle","Datcre","Datmaj","Desc","Domaine","Format","ID","Insee","Org","Org_Home","OrgID","Periode1","Periode2","Periode3","Satut","Sousdom","Tag","Theme2","Theme3","Titre","Url","Vignette","Ville",
@@ -17,11 +26,11 @@
 
 class Command(BaseCommand):
     '''
-    Command to diff datasheets content from csv content 
+    Command to diff datasheets content from csv content
     '''
     args = '<path_to_csv_file path_to_csv_file ...>'
     options = '[--do-delete] [--encoding] [--delimiter] [--dialect]'
-    help = """Import of a csv file for hdabo
+    help = """Command to diff datasheets content from csv content
 Options:
     --do-delete : ignore existing datasheets
     --encoding : files encoding. default to latin-1
@@ -29,7 +38,7 @@
     --dialect : csv dialect
     --fieldnames : csv columns
     """
-    
+
     option_list = BaseCommand.option_list + (
         make_option('--encoding',
             action='store',
@@ -60,30 +69,30 @@
             dest='do_delete',
             default=False,
             help='delete datasheets'),
-        
+
         )
-    
+
     def show_progress(self, current_line, total_line, width):
 
         percent = (float(current_line) / float(total_line)) * 100.0
 
         marks = math.floor(width * (percent / 100.0))
         spaces = math.floor(width - marks)
-    
+
         loader = '[' + ('=' * int(marks)) + (' ' * int(spaces)) + ']'
-    
+
         sys.stdout.write("%s %d%% %d/%d\r" % (loader, percent, current_line - 1, total_line - 1)) #takes the header into account
         if percent >= 100:
             sys.stdout.write("\n")
         sys.stdout.flush()
 
-            
+
 
     def handle(self, *args, **options):
-        
+
         if len(args) == 0:
             raise CommandError("Gives at lat one csv file to import")
-        
+
         self.encoding = options.get('encoding', "latin-1")
         self.do_delete = options.get('do_delete', False)
         fieldnames = options.get('fieldnames', None)
@@ -91,30 +100,30 @@
         for csv_path in args:
             print "Processing %s " % (csv_path)
             with open(csv_path, 'rU') as csv_file:
-                
+
                 # get the number of lines if necessary
                 for i, l in enumerate(csv_file): #@UnusedVariable
-                    pass                        
+                    pass
                 total_line = i + 1
                 if fieldnames:
                     total_line = total_line + 1
                 csv_file.seek(0)
-                
+
                 delimiter = options.get('delimiter', ";")
                 if delimiter == "TAB" or delimiter == "\\t":
                     delimiter = '\t'
-    
+
                 dr_kwargs = {'delimiter':delimiter}
                 if  fieldnames is not None:
                     dr_kwargs['fieldnames'] = [f.strip() for f in fieldnames.split(",")]
                 dialect = options.get('dialect', "excel")
                 if dialect is not None:
                     dr_kwargs['dialect'] = dialect
-                   
+
                 reader = csv.DictReader(csv_file, **dr_kwargs)
-                
+
                 ids = []
-    
+
                 for row in reader:
                     line_num = reader.line_num if fieldnames is None else reader.line_num + 1
                     self.show_progress(line_num, total_line, 60)
@@ -123,24 +132,24 @@
                             return val.decode(encoding)
                         else:
                             return val
-                                                
+
                     row = dict([(safe_decode(key, self.encoding), safe_decode(value, self.encoding)) for key, value in row.items()])
-                    
+
                     ids.append(row['ID'])
-                
+
                 qs = Datasheet.objects.exclude(hda_id__in = ids).order_by("hda_id")
-                
+
                 qs_count = qs.count()
-                
+
                 if qs_count == 0:
                     print("No datasheet to delete : exit")
                     return
-                    
+
                 print("The following datasheets are in the database and not in the csv file")
                 for i,ds in enumerate(qs):
                     print("%*d- %4s : %s" % (len(str(qs_count+1)), i+1, ds.hda_id, ds.title.strip() if ds.title is not None else ""))
-                    
-                
+
+
                 if self.do_delete:
                     print("deleting datasheets")
                     qs.delete()
--- a/src/hdabo/management/commands/import_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/import_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,19 @@
 # -*- coding: utf-8 -*-
 '''
-Created on May 25, 2011
+Importe un (ou pusieurs) fichiers CSV issus d'un export de la base HDA.
+Cette commande se contente d'importer les données contenues dans les fichiers CSV.
+
+**Usage**: ``django-admin import_csv [options] <path_to_csv_file path_to_csv_file ...>``
+
+**Options spécifiques:**
 
-@author: ymh
+    - *\-\-encoding=ENCODING* : encodage des fichiers CSV (défaut ``latin-1``)
+    - *\-\-delimiter=DELIMITER* : Séparateur des fichiers CSV
+    - *\-\-dialect=DIALECT* : Dialecte fichier CSV (c.f. `Dialectes Python CSV <https://docs.python.org/2/library/csv.html#csv-fmt-params>`_)
+    - *\-\-fieldnames=FIELDNAMES* : liste des noms de champ à traiter (séparateur : ``,``)
+    - *\-\-lines=LINES* : Nombre de ligne de ficheirs CSV à lire ( 0 : toutes, défaut 0)
+    - *\-\-ignore-existing* : écrase les fiches qui existent déjà dans la base
+
 '''
 #Auteur,Chemin,Comment,Controle,Datcre,Datmaj,Desc,Domaine,Format,ID,Insee,Org,Org_Home,OrgID,Periode1,Periode2,Periode3,Satut,Sousdom,Tag,Theme2,Theme3,Titre,Url,Vignette,Ville
 #"Auteur","Chemin","Comment","Controle","Datcre","Datmaj","Desc","Domaine","Format","ID","Insee","Org","Org_Home","OrgID","Periode1","Periode2","Periode3","Satut","Sousdom","Tag","Theme2","Theme3","Titre","Url","Vignette","Ville",
@@ -29,7 +40,7 @@
     --ignore-existing : ignore existing datasheets
     --lines : max number of lines to load (for each file). 0 means all.
     --encoding : files encoding. default to latin-1"""
-    
+
     option_list = BaseCommand.option_list + (
         make_option('--encoding',
             action='store',
@@ -66,24 +77,24 @@
             dest='ignore_existing',
             default=False,
             help='force insertion'),
-        
+
         )
-    
+
     def show_progress(self, current_line, total_line, width):
 
         percent = (float(current_line) / float(total_line)) * 100.0
 
         marks = math.floor(width * (percent / 100.0))
         spaces = math.floor(width - marks)
-    
+
         loader = '[' + ('=' * int(marks)) + (' ' * int(spaces)) + ']'
-    
+
         sys.stdout.write("%s %d%% %d/%d\r" % (loader, percent, current_line - 1, total_line - 1)) #takes the header into account
         if percent >= 100:
             sys.stdout.write("\n")
         sys.stdout.flush()
 
-    
+
     def create_domain_period(self, row_value, klass, school_period):
         res_list = []
         if not row_value:
@@ -93,12 +104,12 @@
                 res_obj, created = klass.objects.get_or_create(label=label_str, school_period=school_period, defaults={"label":label_str, "school_period":school_period}) #@UnusedVariable
                 res_list.append(res_obj)
         return res_list
-    
+
     def create_datasheet(self, row):
-        
+
         if self.ignore_existing and Datasheet.objects.filter(hda_id=row[u"ID"]).count() > 0:
             return
-        
+
         author_str = row[u'Auteur']
         if author_str:
             author_array = author_str.split(" ")
@@ -111,12 +122,12 @@
             elif len(author_array) == 2:
                 firstname = author_array[0]
                 lastname = author_array[1]
-                
+
             author, created = Author.objects.get_or_create(hda_id=author_str, defaults={"firstname":firstname, "lastname":lastname}) #@UnusedVariable
         else:
             author = None
-        
-        org_str = row[u"Org"]    
+
+        org_str = row[u"Org"]
         if org_str:
             url_str = row[u'Org_Home']
             if url_str is not None:
@@ -124,36 +135,36 @@
             org, created = Organisation.objects.get_or_create(hda_id=org_str, defaults={"name":org_str, "website" : url_str}) #@UnusedVariable
         else:
             org = None
-            
+
         town_str = row[u"Ville"]
         if town_str:
             insee_str = row[u'Insee'].strip() if row[u'Insee'] else row[u'Insee']
             if len(insee_str) > 5:
-                insee_str = "" 
+                insee_str = ""
             loc, created = Location.objects.get_or_create(insee=insee_str, defaults={"name": town_str, "insee": insee_str}) #@UnusedVariable
         else:
             loc = None
-            
+
         format_str = row[u"Format"]
         if format_str:
             format, created = DocumentFormat.objects.get_or_create(label=format_str, defaults={"label": format_str}) #@UnusedVariable
         else:
             format = None
-        
+
         domains = self.create_domain_period(row[u"Domaine"], Domain, Domain.DOMAIN_PERIOD_DICT[u'Global'])
-                                        
+
         primary_periods = self.create_domain_period(row[u"Periode1"], TimePeriod, TimePeriod.TIME_PERIOD_DICT[u'Primaire'])
         college_periods = self.create_domain_period(row[u"Periode2"], TimePeriod, TimePeriod.TIME_PERIOD_DICT[u'Collège'])
         highschool_periods = self.create_domain_period(row[u"Periode3"], TimePeriod, TimePeriod.TIME_PERIOD_DICT[u'Lycée'])
-                    
+
         primary_themes = self.create_domain_period(row[u"Sousdom"], Domain, Domain.DOMAIN_PERIOD_DICT[u'Primaire'])
         college_themes = self.create_domain_period(row[u"Theme2"], Domain, Domain.DOMAIN_PERIOD_DICT[u'Collège'])
         highschool_themes = self.create_domain_period(row[u"Theme3"], Domain, Domain.DOMAIN_PERIOD_DICT[u'Lycée'])
-        
+
         url = row[u"Url"]
         if url is not None:
             url = url.strip()
-        
+
         datasheet = Datasheet.objects.create(
             hda_id=row[u"ID"],
             author=author,
@@ -165,11 +176,11 @@
             format=format,
             original_creation_date=datetime.datetime.strptime(row[u"Datcre"], "%d/%m/%Y").date(),
             original_modification_date=datetime.datetime.strptime(row[u"Datmaj"], "%d/%m/%Y").date(),
-            validated=False                                          
+            validated=False
         )
-        
+
         datasheet.save()
-        
+
         datasheet.set_domains(domains)
         datasheet.set_primary_periods(primary_periods)
         datasheet.set_college_periods(college_periods)
@@ -178,7 +189,7 @@
         datasheet.set_college_themes(college_themes)
         datasheet.set_highschool_themes(highschool_themes)
 
-        
+
         if row[u'Tag']:
             for i, tag in enumerate([t.strip() for t in row[u'Tag'].split(u";")]):
                 if len(tag) == 0:
@@ -190,20 +201,20 @@
                         tag_obj = t
                         if tag_obj.url_status != Tag.TAG_URL_STATUS_DICT['null_result']:
                             break
- 
+
                 if tag_obj is None:
                     tag_obj = Tag(label=tag_label, original_label=tag)
                     tag_obj.save()
 
                 tagged_ds = TaggedSheet(datasheet=datasheet, tag=tag_obj, original_order=i + 1, order=i + 1)
                 tagged_ds.save()
-        
+
 
     def handle(self, *args, **options):
-        
+
         if len(args) == 0:
             raise CommandError("Gives at lat one csv file to import")
-        
+
         self.encoding = options.get('encoding', "latin-1")
         lines = options.get('lines', 0)
         self.ignore_existing = options.get('ignore_existing', False)
@@ -218,18 +229,18 @@
                 try:
                     print "Processing %s " % (csv_path)
                     with open(csv_path, 'rU') as csv_file:
-                        
+
                         # get the number of lines if necessary
                         if not lines:
                             for i, l in enumerate(csv_file): #@UnusedVariable
-                                pass                        
+                                pass
                             total_line = i + 1
                             if fieldnames:
                                 total_line = total_line + 1
                             csv_file.seek(0)
                         else:
                             total_line = lines + 1
-                        
+
                         delimiter = options.get('delimiter', ";")
                         if delimiter == "TAB" or delimiter == "\\t":
                             delimiter = '\t'
@@ -240,9 +251,9 @@
                         dialect = options.get('dialect', "excel")
                         if dialect is not None:
                             dr_kwargs['dialect'] = dialect
-                           
+
                         reader = csv.DictReader(csv_file, **dr_kwargs)
-        
+
                         for j, row in enumerate(reader):
                             if lines and j >= lines:
                                 break
@@ -253,14 +264,14 @@
                                     return val.decode(encoding)
                                 else:
                                     return val
-                                                        
+
                             row = dict([(safe_decode(key, self.encoding), safe_decode(value, self.encoding)) for key, value in row.items()])
                             self.create_datasheet(row)
-                            
+
                             transaction.commit()
                 except Exception:
                     transaction.rollback()
-                    raise 
+                    raise
                 finally:
                     print('')
         finally:
--- a/src/hdabo/management/commands/import_rdf.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/import_rdf.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,10 +1,29 @@
 # -*- coding: utf-8 -*-
 '''
-Created on May 25, 2011
+Importe un fichiers RDF issus d'un export de la base HDA.
+Cette commande remplace le contenu de la base existante.
 
-- after `import_rdf` call commands `import_hdabo_db -c` then `rebuild_index`
+La liste des types d'objets importés est la suivante :
+    - `Categorie`,
+    - `Tag`,
+    - `Site`,
+    - `Ville`,
+    - `Institution`,
+    - `Theme`,
+    - `Domaine`,
+    - `SousDomaine`,
+    - `Periode`,
+    - `Notice`
 
-@author: ymh
+A noter que cette commande est actuellement utilisée pour transférer le contenu de la base de donnée du site HDA vers HDALab. les commandes suivantes sont ensuite lancée:
+    #. :class:`import_hdabo_db -c <hdalab.management.commands.import_hdabo_db>`
+    #. `rebuild_index <http://django-haystack.readthedocs.io/en/master/management_commands.html#rebuild-index>`_
+
+**Usage**: ``django-admin import_rdf [options] <path_to_rdf_file>``
+
+**Options spécifiques:**
+
+    - *\-t, \-\-type=TYPE* : type d'objet à importer. Cette option peut être ajoutée plusieurs fois.
 '''
 
 import base64
@@ -33,8 +52,8 @@
 logger = logging.getLogger(__name__)
 
 RDF_EXT_MAP = {
-    '.xml': 'rdfxm',
-    '.rdf': 'rdfxm',
+    '.xml': 'rdfxml',
+    '.rdf': 'rdfxml',
     '.ttl': 'turtle',
     '.nt': 'ntriples'
 }
@@ -804,7 +823,7 @@
 
 class Command(BaseCommand):
     '''
-    Command to import csvfile
+    Command to import rdf file
     '''
     args = '<path_to_rdf_file>'
     options = '[--type TYPE]'
@@ -835,7 +854,7 @@
         self.types_list = options.get('types', TYPES_LIST) or TYPES_LIST
 
         if any([t not in TYPES_LIST for t in self.types_list]):
-            raise CommandError("Types is %r : all types mus be in %r" % (self.types_list, TYPES_LIST))
+            raise CommandError("Types is %r : all types must be in %r" % (self.types_list, TYPES_LIST))
 
         with transaction.atomic():
             connection = connections[DEFAULT_DB_ALIAS]
--- a/src/hdabo/management/commands/import_tag_popularity.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/import_tag_popularity.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,10 +1,18 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jun 17, 2011
+Importe les informations de popularité des tags. (c.f. champ `popularity` de l'objet :class:`hdabo.models.Tag`.).
+
+**Usage**: ``django-admin import_tag_popularity [options] <path_to_csv_file path_to_csv_file ...>``
+
+**Options spécifiques:**
 
-@author: ymh
-
-command to import tag popularity
+    - *\-\-all* : Capture les miniatures pours tous les renkan publié. Remplace les miniatures existantes.
+    - *\-\-encoding=ENCODING* : encodage des fichiers CSV (défaut ``latin-1``)
+    - *\-\-delimiter=DELIMITER* : Séparateur des fichiers CSV
+    - *\-\-dialect=DIALECT* : Dialecte fichier CSV (c.f. `Dialectes Python CSV <https://docs.python.org/2/library/csv.html#csv-fmt-params>`_)
+    - *\-\-fieldnames=FIELDNAMES* : liste des noms de champ à traiter (séparateur : ``,``)
+    - *\-\-lines=LINES* : Nombre de ligne de ficheirs CSV à lire ( 0 : toutes, défaut 0)
+    - *\-\-preserve* : Ne met pas à jour les informations de popularité existante.
 
 '''
 
@@ -19,7 +27,7 @@
 
 class Command(BaseCommand):
     '''
-    Command to import csvfile
+    Command to import tag popularity.
     '''
     args = '<path_to_csv_file path_to_csv_file ...>'
     options = '[--ignore-existing] [--lines] [--encoding]'
@@ -28,7 +36,7 @@
     --ignore-existing : ignore existing datasheets
     --lines : max number of lines to load (for each file). 0 means all.
     --encoding : files encoding. default to latin-1"""
-    
+
     option_list = BaseCommand.option_list + (
         make_option('--encoding',
             action='store',
@@ -65,44 +73,44 @@
             dest='preserve',
             default=False,
             help='preserve'),
-                                             
-        
+
+
         )
-    
+
     def show_progress(self, current_line, total_line, width):
 
         percent = (float(current_line) / float(total_line)) * 100.0
 
         marks = math.floor(width * (percent / 100.0))
         spaces = math.floor(width - marks)
-    
+
         loader = '[' + ('=' * int(marks)) + (' ' * int(spaces)) + ']'
-    
+
         sys.stdout.write("%s %d%% %d/%d\r" % (loader, percent, current_line - 1, total_line - 1)) #takes the header into account
         if percent >= 100:
             sys.stdout.write("\n")
         sys.stdout.flush()
 
     def handle(self, *args, **options):
-        
+
         if len(args) == 0:
             raise CommandError("Give one csv file to import")
         elif len(args) > 1:
             raise CommandError("Only one file can be imported")
-        
+
         self.encoding = options.get('encoding', "latin-1")
         lines = options.get('lines', 0)
         fieldnames = options.get('fieldnames', "label,popularity")
 
         csv_path = args[0]
-        
+
         print("Processing %s " % (csv_path))
-        
+
         with open(csv_path, 'rU') as csv_file:
             # get the number of lines if necessary
             if not lines:
                 for i, l in enumerate(csv_file): #@UnusedVariable
-                    pass                        
+                    pass
                 total_line = i + 1
                 if fieldnames:
                     total_line = total_line + 1
@@ -119,10 +127,10 @@
             dialect = options.get('dialect', "excel")
             if dialect is not None:
                 dr_kwargs['dialect'] = dialect
-               
+
             if not options.get('preserve',False):
                 Tag.objects.update(popularity=0)
-                
+
             reader = csv.DictReader(csv_file, **dr_kwargs)
 
             for j, row in enumerate(reader):
@@ -135,16 +143,16 @@
                         return val.decode(encoding)
                     else:
                         return val
-                                            
+
                 row = dict([(safe_decode(key, self.encoding), safe_decode(value, self.encoding)) for key, value in row.items()])
-                
+
                 label = normalize(row['label'].strip())
                 popularity_str = row['popularity']
-                
+
                 if not label or not popularity_str:
                     continue
-                
-                
+
+
                 for tag in Tag.objects.filter(normalized_label=label):
                     tag.popularity = tag.popularity + int(row['popularity'])
                     tag.save()
--- a/src/hdabo/management/commands/order_tags.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/order_tags.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,7 +1,14 @@
+# -*- coding: utf-8 -*-
 '''
-Created on Jun 7, 2011
+Calcule l'ordre des tags d'une fiche en fonction des scores de la recherche indexée du tag sur le titre et la description de la fiche.
+
+**Usage**: ``django-admin order_tags [options]``
 
-@author: ymh
+**Options spécifiques:**
+
+    - *\-f* : refait le calcul sur l'ensemble des fiches, même celles qui ont été validées ou bien réordonnées manuellement.
+    - *\-\-noinput* : ne pose aucune question.
+
 '''
 
 from django.core.management.base import NoArgsCommand
@@ -24,7 +31,7 @@
     args = ''
     options = '-f : force '
     help = "calculate the order of tags based on indexation recalculate all tags. Will ask for confirmation"
-    
+
     option_list = NoArgsCommand.option_list + (
         make_option('-f', '--force',
             action='store_true',
@@ -40,19 +47,19 @@
 
 
     def handle_noargs(self, **options):
-        
+
         self.style = no_style()
-        
+
         interactive = options.get('interactive', True) and not options.get('no_input', False)
         force = options.get('force', True)
-        
+
         if interactive:
             confirm = raw_input("""You have requested to recalculate the index order of all the tags.
 This will process all the tags in %s datasheets. Are you sure you want to do this ?
     Type 'yes' to continue, or 'no' to cancel: """ % ("all" if force else "not validated"))
         else:
             confirm = 'yes'
-            
+
         if confirm != "yes":
             print "Tag reordering cancelled"
             return
@@ -62,7 +69,7 @@
         else:
             queryset = Datasheet.objects.filter(validated=False, manual_order=False)
         total = queryset.count()
-        
+
         transaction.commit_unless_managed()
         transaction.enter_transaction_management()
         transaction.managed(True)
@@ -77,5 +84,5 @@
             raise
         finally:
             transaction.leave_transaction_management()
-            
-        
+
+
--- a/src/hdabo/management/commands/query_wikipedia.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/management/commands/query_wikipedia.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,17 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jun 7, 2011
+Lance des requêtes wikipedia pour associer un tag à un article wikipedia (i.e. sémantisé le tag).
+On utilise pour cela directement `l'api de requête wikipedia <https://www.mediawiki.org/wiki/API:Query>`_ en recherchant par le nom des pages (``titles=Foo|Bar|Main_Page``).
+
+**Usage**: ``django-admin import_csv [options] <path_to_csv_file path_to_csv_file ...>``
 
-@author: ymh
+**Options spécifiques:**
+
+    - *\-\-force* : force la mise à jour de tous les tags, pas seulement ceux pas encore traités.
+    - *\-\-random* : force un ordre aléatoire sur la requête des tags.
+    - *\-\-site=SITE_URL* : url du site wikipedia.
+    - *\-\-limit=LIMIT* : nombre de tags à traiter.
+    - *\-\-start=START* : nombre de tag à ignorer.
 '''
 
 from django.conf import settings
@@ -23,7 +32,7 @@
     '''
     options = ''
     help = """query and update wikipedia for tag title."""
-    
+
     option_list = NoArgsCommand.option_list + (
         make_option('--force',
             action='store_true',
@@ -54,44 +63,44 @@
             default=0,
             help='number of tag to ignore'),
         )
-    
+
     def __is_homonymie(self, page_dict):
         for cat in page_dict.get(u"categories", []):
             if u'Catégorie:Homonymie' in cat.get(u"title", u"") or u'Category:Disambiguation pages' in cat.get(u"title", u""):
                 return True
         return False
-        
+
     def show_progress(self, current_line, total_line, label, width):
 
         percent = (float(current_line) / float(total_line)) * 100.0
 
         marks = math.floor(width * (percent / 100.0))
         spaces = math.floor(width - marks)
-    
+
         loader = u'[' + (u'=' * int(marks)) + (u' ' * int(spaces)) + u']'
-        
+
         sys.stdout.write(u"%s %d%% %d/%d - %r\r" % (loader, percent, current_line - 1, total_line - 1, label[:50].rjust(50))) #takes the header into account
         if percent >= 100:
             sys.stdout.write("\n")
         sys.stdout.flush()
-        
+
     def handle_noargs(self, **options):
-        
+
         self.style = no_style()
-        
+
         interactive = options.get('interactive', True)
-        
+
         verbosity = int(options.get('verbosity', '1'))
-        
+
         force = options.get('force', False)
-        
+
         limit = options.get("limit", -1)
         start = options.get("start", 0)
-        
+
         site_url = options.get('site_url', settings.WIKIPEDIA_API_URL)
-        
+
         random = options.get('random', False)
-        
+
         if verbosity > 2:
             print "option passed : " + repr(options)
 
@@ -101,7 +110,7 @@
     Type 'yes' to continue, or 'no' to cancel: """)
         else:
             confirm = 'yes'
-            
+
         if confirm != "yes":
             print "wikipedia query cancelled"
             return
@@ -109,38 +118,38 @@
         if force:
             queryset = Tag.objects.all()
         else:
-            queryset = Tag.objects.filter(url_status=None)                    
-        
+            queryset = Tag.objects.filter(url_status=None)
+
         if random:
             queryset = queryset.order_by("?")
         else:
             queryset = queryset.order_by("label")
-        
+
         if limit >= 0:
             queryset = queryset[start:limit]
         else:
             queryset = queryset[start:]
-            
-        
+
+
         if verbosity > 2 :
             print "Tag Query is %s" % (queryset.query)
-        
+
         site = wiki.Wiki(site_url) #@UndefinedVariable
-        
-        
+
+
         count = queryset.count()
         if verbosity > 1:
             print "Processing %d tags" % (count)
-        
-        
-        
+
+
+
         for i, tag in enumerate(queryset):
-            
+
             if verbosity > 1:
                 print "processing tag %s (%d/%d)" % (tag.label, i + 1, count)
             else:
-                self.show_progress(i + 1, count, tag.label, 60)                            
-            
+                self.show_progress(i + 1, count, tag.label, 60)
+
             process_tag(site, tag, verbosity)
-            
-            
+
+
--- a/src/hdabo/models.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/models.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,4 +1,7 @@
 # -*- coding: utf-8 -*-
+"""
+Ce module contient les classes de base utilisées dans le back-office HDA ainsi que dans l'application hdalab.
+"""
 
 import datetime
 
@@ -12,6 +15,9 @@
 
 # User Class, due to migration to django 1.6.5
 class User(AbstractUser):
+    """
+    Un utiliateur HDALab.
+    """
     class Meta:
         db_table = 'auth_user'
 
@@ -26,17 +32,30 @@
 
 
 class Organisation(models.Model):
+    """
+    Représente une entité émettrice de documents.
+    """
     hda_id = models.CharField(max_length=512, unique=True, blank=False, null=False)
     name = models.CharField(max_length=512, unique=False, blank=False, null=False)
     location = models.CharField(max_length=512, unique=False, blank=True, null=True)
     website = models.CharField(max_length=2048, unique=False, blank=True, null=True)
-    
+
 class Author(models.Model):
+    """
+    Personne ayant importer une fiche.
+    """
+
     hda_id = models.CharField(max_length=512, unique=True, blank=False, null=False)
     lastname = models.CharField(max_length=512, unique=False, blank=True, null=True)
     firstname = models.CharField(max_length=512, unique=False, blank=True, null=True)
 
 class TimePeriod(models.Model):
+    """
+    Période de scolarité:
+        - Primaire
+        - Collège
+        - Lycée
+    """
     TIME_PERIOD_CHOICES = (
         (1, u'Primaire'),
         (2, u'Collège'),
@@ -52,7 +71,7 @@
     natural_key = models.CharField(max_length=512, unique=True, blank=False, null=False)
 
     objects = SortedModelManager()
-    
+
     class Meta:
         unique_together = ("label", "school_period")
 
@@ -60,6 +79,13 @@
         return unicode(self.label)
 
 class Domain(models.Model):
+    """
+    Période de la scolarité ciblé par une fiche:
+        - Global (toute les période scolaires)
+        - Primaire
+        - Collège
+        - Lycée
+    """
     DOMAIN_PERIOD_CHOICES = (
         (0, u'Global'),
         (1, u'Primaire'),
@@ -86,22 +112,44 @@
 
 
 class DocumentFormat(models.Model):
+    """
+    Format de la fiche (pdf, word, html,...)
+    """
     label = models.CharField(max_length=512, unique=True, blank=False, null=False)
 
     def __unicode__(self):
         return unicode(self.label)
-    
+
 class TagCategory(models.Model):
+    """
+    Catégorie du tag. Explique pourqoui le tag a été posé sur une fiche.
+    Exemples :
+    - Localisation : le tage représente un lieu en relation avec la fiche.
+    - Créateur : Le tag représente l'auteur de(s) oeuvre(s) décrite(s) dans la fiche.
+    - Datation : Le tag ajoute une information de date sur l'oeuvre sujet de la fiche.
+    - Ecole/Mouvement : Le tag décrit à quelle école ou mouvement artistique appartient l'oeuvre sujet de la fiche.
+    - Discipline artistique : Le tag décrit à quelle discipline artistique appartient l'oeuvre sujet de la fiche.
+    """
     label = models.CharField(max_length=512, unique=True, blank=False, null=False)
     natural_key = models.CharField(max_length=512, unique=False, blank=False, null=False, db_index=True)
-    
+
     def __unicode__(self):
         return unicode(self.label)
-    
+
     class Meta:
         verbose_name_plural = "TagCategories"
 
 class Tag(models.Model):
+    """
+    Un tag. Soit c'est un simple mot, soit il est "sémantisé" et dans ce cas, il fait référence à une page Wikipedia.
+    Attributs remarquables:
+    - wikipedia_url : l'url wikipedia
+    - wikipedia_pageid : l'identifiant de page wikipedia.
+    - alternative_wikipedia_url : autre page wikipedia pour le même tag (par exemple "Molière" pour "Jean-Baptiste Poquelin")
+    - url_status : état de liage du tag (pas de liage proposé, redirection, homonymie, correspondance, non sémantisé)
+    - dbpedia_uri : URI DBPedia
+    - popularity : Popularité du tag sur le portail HDA. Cela permet de mettre une priorité pour sémantisé le tag.
+    """
     TAG_URL_STATUS_CHOICES = (
         (0, "null_result"),
         (1, "redirection"),
@@ -109,7 +157,7 @@
         (3, "match"),
         (4, "unsematized"),
     )
-    
+
     TAG_URL_STATUS_DICT = {
         "null_result":0,
         "redirection":1,
@@ -117,7 +165,7 @@
         "match":3,
         "unsemantized":4,
     }
-    
+
     label = models.CharField(max_length=1024, unique=False, blank=False, null=False, db_index=True)
     alternative_label = models.CharField(max_length=1024, unique=False, blank=True, null=True)
     normalized_label = models.CharField(max_length=1024, unique=False, blank=False, null=False, db_index=True, editable=False)
@@ -135,7 +183,7 @@
     #natural_key = models.CharField(max_length=7168, blank=True, null=True, db_index=True)
     #TODO: find a proper key. natural key is not really a key.
     natural_key = models.CharField(max_length=7168, blank=False, null=False, db_index=True)
-    
+
 
     def __init__(self, *args, **kwargs):
         models.Model.__init__(self, *args, **kwargs)
@@ -145,7 +193,7 @@
     def url_status_text(): #@NoSelf
         def fget(self):
             return self.TAG_URL_STATUS_CHOICES[self.url_status][1]
-        
+
         return locals()
 
     def calculate_natural_key(self):
@@ -157,18 +205,21 @@
         ]
         return ('_'.join(parts))[:7168]
 
-    
+
     def save(self, *args, **kwargs):
         if self.label and not self.normalized_label:
             self._normalized_label = normalize(self.label)
         if not self.force_natural_key:
             self.natural_key = self.calculate_natural_key()
-        super(Tag, self).save(*args, **kwargs) 
-            
+        super(Tag, self).save(*args, **kwargs)
+
     class Meta:
         unique_together = (('label', 'original_label', 'url_status'),)
-        
+
 class Location(models.Model):
+    """
+    Information de lieu pour une fiche, avec en particulier son numéro insee.
+    """
     name = models.CharField(max_length=512, unique=False, blank=False, null=False)
     insee = models.CharField(max_length=5, unique=True, blank=False, null=False)
 
@@ -177,12 +228,12 @@
 
 
 def generate_m2m_setter(m2m_field_name):
-    
+
     def set_m2m_field(self, lst):
-        
+
         m2m_manager = getattr(self, m2m_field_name)
         m2m_manager.clear()
-        
+
         through_klass = set_m2m_field.cache.get('through_klass', None)
         if through_klass is None:
             field = getattr(self.__class__, m2m_field_name)
@@ -203,11 +254,14 @@
             new_rel = through_klass(**kwargs)
             new_rel.save()
     set_m2m_field.cache = {}
-            
+
     return set_m2m_field
 
 
 class Datasheet(models.Model):
+    """
+    Une fiche de ressource du portail Histoire des Arts.
+    """
     hda_id = models.CharField(max_length=512, unique=True, blank=False, null=False)
     author = models.ForeignKey(Author, null=True, blank=True, serialize=False)
     organisation = models.ForeignKey(Organisation, serialize=False, null=True)
@@ -231,38 +285,38 @@
     validator = models.ForeignKey(User, null=True, blank=True, serialize=False)
     manual_order = models.BooleanField(default=False, db_index=True, serialize=False)
     tags = models.ManyToManyField(Tag, through='TaggedSheet', serialize=False)
-    
+
     def natural_key(self):
         return self.hda_id
-        
+
     def validate(self, user):
         self.validation_date = datetime.datetime.now()
         self.validated = True
         self.validator = user
         self.save()
-    
+
     def unvalidate(self):
         self.validation_date = datetime.datetime.min
         self.validated = False
         self.validator = None
         self.save()
-        
-        
+
+
     set_domains = generate_m2m_setter("domains")
-    
+
     @Property
     def domains_list(): #@NoSelf
         def fget(self):
             return [d.label for d in self.domains.all()]
-        
-        return locals() 
+
+        return locals()
 
     @Property
     def domains_text(): #@NoSelf
         def fget(self):
             return "; ".join(self.domains_list)
-        
-        return locals() 
+
+        return locals()
 
 
     set_primary_periods = generate_m2m_setter("primary_periods")
@@ -270,96 +324,96 @@
     @Property
     def primary_periods_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.primary_periods.all()] 
+            return [d.label for d in self.primary_periods.all()]
 
-        return locals() 
+        return locals()
 
-    
+
     @Property
     def primary_periods_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.primary_periods_list) 
+            return "; ".join(self.primary_periods_list)
 
-        return locals() 
+        return locals()
 
     set_college_periods = generate_m2m_setter("college_periods")
 
     @Property
     def college_periods_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.college_periods.all()] 
+            return [d.label for d in self.college_periods.all()]
 
-        return locals() 
+        return locals()
 
     @Property
     def college_periods_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.college_periods_list) 
+            return "; ".join(self.college_periods_list)
 
-        return locals() 
+        return locals()
 
     set_highschool_periods = generate_m2m_setter("highschool_periods")
 
     @Property
     def highschool_periods_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.highschool_periods.all()] 
+            return [d.label for d in self.highschool_periods.all()]
 
-        return locals() 
+        return locals()
 
     @Property
     def highschool_periods_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.highschool_periods_list) 
+            return "; ".join(self.highschool_periods_list)
 
-        return locals() 
+        return locals()
 
     set_primary_themes = generate_m2m_setter("primary_themes")
 
     @Property
     def primary_themes_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.primary_themes.all()] 
+            return [d.label for d in self.primary_themes.all()]
 
-        return locals() 
+        return locals()
 
 
     @Property
     def primary_themes_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.primary_themes_list) 
+            return "; ".join(self.primary_themes_list)
 
-        return locals() 
+        return locals()
 
     set_college_themes = generate_m2m_setter("college_themes")
 
     @Property
     def college_themes_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.college_themes.all()] 
+            return [d.label for d in self.college_themes.all()]
 
-        return locals() 
-    
+        return locals()
+
     @Property
     def college_themes_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.college_themes_list) 
+            return "; ".join(self.college_themes_list)
 
-        return locals() 
+        return locals()
 
     set_highschool_themes = generate_m2m_setter("highschool_themes")
 
     @Property
     def highschool_themes_list(): #@NoSelf
         def fget(self):
-            return [d.label for d in self.highschool_themes.all()] 
+            return [d.label for d in self.highschool_themes.all()]
 
         return locals()
 
     @Property
     def highschool_themes_text(): #@NoSelf
         def fget(self):
-            return "; ".join(self.highschool_themes_list) 
+            return "; ".join(self.highschool_themes_list)
 
         return locals()
 
@@ -367,14 +421,14 @@
     def town_text(): #@NoSelf
         def fget(self):
             return self.town.name if self.town else ""
-        
+
         return locals()
 
     @Property
     def tags_text(): #@NoSelf
         def fget(self):
             return "; ".join([t.label for t in self.tags.all()])
-        
+
         return locals()
 
     @models.permalink
@@ -385,6 +439,13 @@
 
 
 class TaggedSheet(models.Model):
+    """
+    Objet liant un tag à une fiche.
+    Attributs important:
+    - order : ordre du tag dans la liste de tag de la fiche. Plus un tag est en tête de fiche, plus il est important pour la fiche.
+    - index_note : coéficient d'importance du tag calculé automatiquement lors de l'import et permettant de déterminer un ordre initial pour les tags.
+    - wikipedia_revision_id : Numéro de révision de la page wikipedia au moment de la pose du tag sur la fiche.
+    """
     datasheet = models.ForeignKey(Datasheet)
     tag = models.ForeignKey(Tag)
     created_at = models.DateTimeField(auto_now_add=True)
@@ -392,23 +453,23 @@
     order = models.IntegerField(null=False, blank=False, default=0, db_index=True)
     index_note = models.FloatField(null=False, blank=False, default=0.0, db_index=True)
     wikipedia_revision_id = models.BigIntegerField(unique=False, blank=True, null=True)
-    
+
     @Property
     def wikipedia_verion_permalink(): #@NoSelf
         def fget(self):
             return settings.WIKIPEDIA_VERSION_PERMALINK_TEMPLATE % (unicode(self.wikipedia_revision_id))
-        
+
         return locals()
 
 
-class SortedDatasheetLink(models.Model):    
+class SortedDatasheetLink(models.Model):
     datasheet = models.ForeignKey(Datasheet, db_index=True, null=False, blank=False)
     sort_value = models.IntegerField(null=False, blank=False)
 
     class Meta:
         abstract = True
         ordering = ['sort_value']
-        
+
 
 class Datasheet_domains(SortedDatasheetLink):
     domain = models.ForeignKey(Domain, db_index=True, null=False, blank=False)
@@ -434,6 +495,9 @@
 
 # Evolution pour Hda 2 : folders of datasheets
 class Folder(models.Model):
+    """
+    Décrit un dossier thématique comportant une liste de fiches.
+    """
     url = models.URLField(max_length=2048, unique=True, blank=False, null=False)
     title = models.CharField(max_length=2048, blank=True, null=True)
     description = models.TextField(blank=True, null=True)
--- a/src/hdabo/views.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/views.py	Wed Apr 11 12:19:47 2018 +0200
@@ -629,6 +629,46 @@
 
 
 class SearchDatasheet(SearchView):
+    """
+    Vue permettant la recherche dans les fiches HDALab.
+    La recherche se fait dans les objets :class:`hdabo.models.Datasheet`.
+    C'est une vue qui étend `haystack.views.SearchView <https://django-haystack.readthedocs.io/en/v2.3.2/views_and_forms.html#searchview-template-none-load-all-true-form-class-none-searchqueryset-none-context-class-requestcontext-results-per-page-none>`_.
+
+    Paramêtres GET:
+
+    :var (str) q: La requête à effectuer.
+    :var (str) format: format de la réponse. Si `json` le contenu retourné est un contenu json.
+    :var (int) limit: Le nombre maximum de résultat par page.
+    :var (int) page: le numéro de page de résultat.
+
+
+    Réponse (application/json):
+
+    Une liste comprenant les résultats de la recherche.
+    Si le paramêtre `format` est ``json``, cette vue retourne un document json décrit plus bas.
+    Sinon, la vue retourne une page html.
+
+    exemple de retour json ::
+
+      {
+        "results": [
+            {
+                "url": " http://www.lesartsdecoratifs.fr/francais/arts-decoratifs/collections-26/parcours-27/chronologique/xixe-siecle/les-salles-302/couleurs-vives-et-bois-clairs/",
+                "hda_id": "1279",
+                "description": "A partir des ...",
+                "title": "Couleurs vives et bois clairs"
+            },
+            {
+                "url": "http://www.louvre.fr/oeuvre-notices/autoportrait",
+                "hda_id": "826",
+                "description": "Conservé au Louvre...",
+                "title": "Autoportrait, Jean Fouquet (1452-1455)"
+            },
+            ...
+        ]
+      }
+
+    """
 
     template = "partial/search_datasheet_for_folders.html"
 
--- a/src/hdabo/wp_utils.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdabo/wp_utils.py	Wed Apr 11 12:19:47 2018 +0200
@@ -28,29 +28,29 @@
 
 
 def query_wikipedia_title(site, label=None, pageid=None):
-    
+
     params = {'action':'query', 'prop':'info|categories|langlinks', 'inprop':'url', 'lllimit':'500', 'cllimit':'500', 'rvprop':'ids'}
-        
+
     if label:
         params['titles'] = label
     else:
         params['pageids'] = pageid
     wpquery = api.APIRequest(site, params) #@UndefinedVariable
-    
+
     response = wpquery.query()
     original_response = response
     def return_null_result():
         return { 'new_label': None, 'alternative_label': None, 'status': Tag.TAG_URL_STATUS_DICT["null_result"], 'wikipedia_url': None, 'pageid': None, 'alternative_wikipedia_url': None, 'alternative_pageid': None, 'dbpedia_uri': None, 'revision_id': None, 'response': response }
-    
+
 
     query_dict = response['query']
     # get page if multiple pages or none -> return Tag.null_result
     pages = query_dict.get("pages", {})
     if len(pages) > 1 or len(pages) == 0:
         return return_null_result()
-    
+
     page = pages.values()[0]
-    
+
     if u"invalid" in page or u"missing" in page:
         return return_null_result()
 
@@ -60,57 +60,57 @@
     alternative_label = None
     alternative_url = None
     alternative_pageid = None
-    
+
     if __is_homonymie(page):
         status = Tag.TAG_URL_STATUS_DICT["homonyme"]
     elif u"redirect" in page:
         status = Tag.TAG_URL_STATUS_DICT["redirection"]
     else:
         status = Tag.TAG_URL_STATUS_DICT["match"]
-    
+
     if status == Tag.TAG_URL_STATUS_DICT["redirection"]:
         params['redirects'] = True
-        wpquery = api.APIRequest(site, params) #@UndefinedVariable    
+        wpquery = api.APIRequest(site, params) #@UndefinedVariable
         response = wpquery.query()
         query_dict = response['query']
         pages = query_dict.get("pages", {})
-        #we know that we have at least one answer        
+        #we know that we have at least one answer
         if len(pages) > 1 or len(pages) == 0:
             return return_null_result()
         page = pages.values()[0]
         alternative_label = page.get('title', None)
         alternative_url = page.get('fullurl', None)
         alternative_pageid = page.get('pageid',None)
-    
+
     revision_id = page.get('lastrevid', None)
-    
+
     # to be perfect we should sparql request DBPEDIA_URI_TEMPLATE, but we simply build the url
     dbpedia_uri = settings.DBPEDIA_URI_TEMPLATE % ("resource", urlize_for_wikipedia(new_label))
-            
+
 
     return { 'new_label': new_label, 'alternative_label': alternative_label, 'status': status, 'wikipedia_url': url, 'pageid': pageid, 'alternative_wikipedia_url': alternative_url, 'alternative_pageid': alternative_pageid, 'dbpedia_uri': dbpedia_uri, 'revision_id': revision_id, 'response': original_response }
 
 
 
 def get_or_create_tag(tag_label):
-    
+
     tag_label_normalized = normalize_tag(tag_label)
     # We get the wikipedia references for the tag_label
     # We get or create the tag object
-    
+
     tag = None
     for t in Tag.objects.filter(label__iexact=tag_label_normalized):
         if tag is None or t.url_status != Tag.TAG_URL_STATUS_DICT['null_result']:
             tag = t
             if tag.url_status != Tag.TAG_URL_STATUS_DICT['null_result']:
                 break
- 
+
     if tag is None:
         tag = Tag(label=tag_label_normalized, original_label=tag_label)
         created = True
     else:
         created = False
-    
+
     site = wiki.Wiki(settings.WIKIPEDIA_API_URL) #@UndefinedVariable
 
     if created:
@@ -125,7 +125,7 @@
         dbpedia_uri = wp_res["dbpedia_uri"]
         wikipedia_revision_id = wp_res['revision_id']
 
-    
+
         # We save the datas
         if new_label is not None:
             tag.label = new_label
@@ -134,23 +134,23 @@
         tag.alternative_label = alternative_label
         tag.alternative_wikipedia_url = alternative_url
         tag.alternative_wikipedia_pageid = alternative_pageid
-        tag.wikipedia_url = url            
+        tag.wikipedia_url = url
         tag.wikipedia_pageid = pageid
-        tag.dbpedia_uri = dbpedia_uri 
+        tag.dbpedia_uri = dbpedia_uri
 
         tag.save()
-        
+
     elif tag.wikipedia_pageid:
         wp_res = query_wikipedia_title(site, pageid=tag.wikipedia_pageid)
         wikipedia_revision_id = wp_res['revision_id']
     else:
         wikipedia_revision_id = None
-        
-        
+
+
     return tag, wikipedia_revision_id, created
 
 def process_tag(site, tag, verbosity=0):
-    
+
     wp_res = query_wikipedia_title(site, label=tag.label)
     new_label = wp_res['new_label']
     alternative_label= wp_res['alternative_label']
@@ -162,13 +162,13 @@
     response = wp_res['response']
     dbpedia_uri =  wp_res["dbpedia_uri"]
     revision_id = wp_res["revision_id"]
-    
+
     if verbosity >= 2 :
         print "response from query to %s with parameters %s :" % (site.apibase, repr(new_label))
         print repr(response)
-    
+
     prev_wikipedia_pageid = tag.wikipedia_pageid
-    
+
     if new_label is not None:
         tag.label = new_label
     if status is not None:
@@ -179,14 +179,17 @@
     tag.alternative_label = alternative_label
     tag.alternative_wikipedia_url = alternative_url
     tag.alternative_wikipedia_pageid = alternative_pageid
-        
+
     tag.save()
-    
+
     if prev_wikipedia_pageid != pageid:
         TaggedSheet.objects.filter(tag=tag).update(wikipedia_revision_id=revision_id)
 
 
 def reorder_datasheet_tags(ds):
+    """
+    Reorder a Datasheet tags (object Tag) according to the score they obtain on a search on the title and description of the Datasheet.
+    """
     ts_list = []
     for ts in ds.taggedsheet_set.all():
         ts.index_note = 0
@@ -206,4 +209,4 @@
         ds.manual_order = False
         ds.save()
 
-    
+
--- a/src/hdalab/__init__.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/__init__.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,4 +1,7 @@
 # -*- coding: utf-8 -*-
+"""
+Module contenant l'applicatiion Django HDALab.
+"""
 from __future__ import absolute_import
 
 VERSION = (3, 2, 1, "final", 0)
--- a/src/hdalab/management/commands/calculate_preview.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/calculate_preview.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,16 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jan 30, 2012
+Commande permettant la création des miniatures renkan.
+
+Par défaut, seul les renkan pour lesquel c'est nécessaire sont traités (ceux qui sont publié)
+Les miniatures sont calculées immédiatement de façons synchrone.
 
-@author: ymh
+**Usage**: ``django-admin calculate_preview [options]``
+
+**Options spécifiques:**
+
+    - *\-\-all*: Capture les miniatures pours tous les renkan publié. Remplace les miniatures existantes.
+
 '''
 
 import logging
@@ -25,7 +33,7 @@
     '''
     options = ''
     help = """calculate renkan preview."""
-    
+
     option_list = NoArgsCommand.option_list + (
         make_option('--all',
             action='store_true',
@@ -33,16 +41,16 @@
             default=False,
             help='force all tags to be updated, not only those not yet processed'),
     )
-    
+
 
     def handle_noargs(self, **options):
-                
+
         self.style = no_style()
-        
+
         self.all = options.get('all', False)
 
         queryset = HdalabRenkan.objects.filter(state=HdalabRenkan.PUBLISHED)
-        
+
         if not self.all:
             queryset = queryset.filter(renkan__image = settings.DEFAULT_RENKAN_ICON)
 
--- a/src/hdalab/management/commands/export_tags_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/export_tags_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,21 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jan 25, 2012
+Exporte les catégories wikipedia des tags dans 3 fichiers csv:
+  - \*_visible.txt : les catégories visibles.
+  - \*_hidden.txt : les catégories cachés.
+  - \*_infobox.txt : les paramêtres des infobox.
+
+Seul les tags sémantisés sont pris en compte.
 
-@author: ymh
+**Usage**: ``django-admin export_tags_csv [options] <chemin_vers_le_nom_de_base_des_fichiers_csv>``
+
+**Options spécifiques:**
+
+    - *\-c,\-\-category*: filtre par nom de catégories.
+    - *\-\-lines* : nombre maximal de ligne à exporter. 0 signifie toute.
+    - *\-\-encoding* : encodage des fichier, le défaut est `latin-1`.
+    - *\-f* : force l'écrasement des fichiers csv de sortie.
+
 '''
 
 from django.core.management.base import BaseCommand, CommandError
@@ -23,7 +36,7 @@
     -c, --category : filter by category
     --lines : max number of lines to load (for each file). 0 means all.
     --encoding : files encoding. default to latin-1"""
-    
+
     option_list = BaseCommand.option_list + (
         make_option("-c","--category",
             action='append',
@@ -43,9 +56,9 @@
             default=False,
             help='force file overwrite'),
         )
-        
+
     def handle(self, *args, **options):
-        
+
         if len(args) == 0 or not args[0]:
             raise CommandError("Gives at last one csv file to export")
 
@@ -54,13 +67,13 @@
         self.force = options.get("force", False)
         self.base_path = args[0].strip()
         self.interactive = options.get("interactive",True)
-        
+
         files_path = {
             "visible" : { 'path':self.base_path + "_visible.txt",},
             "hidden" : { 'path':self.base_path + "_hidden.txt",},
             "infobox" : { 'path':self.base_path + "_infobox.txt",},
         }
-        
+
         try:
             for filedef in files_path.values():
                 try:
@@ -81,9 +94,9 @@
                     filedef['file'] = open(filedef['path'],'w')
                 except IOError:
                     filedef['file'] = open(filedef['path'],'w')
-                
+
                 filedef['csv'] = UnicodeWriter(filedef['file'], doublequote=False, escapechar="\\", encoding=self.encoding)
-                
+
             queryset = Tag.objects.exclude(wikipedia_pageid= None)
             cat_filter = None
             for cat in self.categories:
@@ -93,32 +106,31 @@
                     cat_filter = cat_filter | Q(category__label = cat)
             if cat_filter is not None:
                 queryset = queryset.filter(cat_filter)
-            
+
             tcount = queryset.count()
-            
+
             print "Exporting %d tags" % (tcount)
             writer = None
-                
+
             for i,t in enumerate(queryset.order_by("label")):
-                
+
                 writer = utils.show_progress(i+1, tcount, t.label, 50, writer)
                 #normal category
                 row = [t.label,] + [cat.wp_category.label for cat in t.wp_categories.filter(hidden=False)]
                 files_path['visible']['csv'].writerow(row)
-                
+
                 #hidden category
                 row = [t.label,] + [cat.wp_category.label for cat in t.wp_categories.filter(hidden=True)]
                 files_path['hidden']['csv'].writerow(row)
-                
+
                 #infobox
                 for i in t.infoboxes.all():
                     vec = [[p.param_name,p.param_value.replace('\n',"\\n")] for p in i.infoboxparameter_set.all()]
                     ib_params = [num for elem in vec for num in elem]
                     row = [t.label, i.name.strip()] + ib_params
                     files_path['infobox']['csv'].writerow(row)
-            
+
         finally:
             for filedef in files_path.itervalues():
                 if filedef.get('file',None):
                     filedef['file'].close()
-        
\ No newline at end of file
--- a/src/hdalab/management/commands/export_wpcategory_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/export_wpcategory_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,14 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Feb 2, 2012
+Exporte en csv les catégories wikipédia utilisées dans HDALab.
+
+**Usage**: ``django-admin export_wpcategory_csv [options] <chemin_vers_le_fichier_csv>``
 
-@author: ymh
+**Options spécifiques:**
+
+    - *\-\-encoding* : encodage des fichier, le défaut est `latin-1`.
+    - *\-f* : force l'écrasement du fichier csv de sortie.
+
 '''
 from django.core.management.base import BaseCommand, CommandError
 from optparse import make_option
@@ -23,7 +29,7 @@
     -e, --encoding : files encoding. default to latin-1
     -f, --force : force file overwrite
     """
-    
+
     option_list = BaseCommand.option_list + (
         make_option("-e","--encoding",
             action='store',
@@ -37,9 +43,9 @@
             default=False,
             help='force file overwrite'),
         )
-        
+
     def handle(self, *args, **options):
-        
+
         if len(args) == 0 or not args[0]:
             raise CommandError("Gives at last one csv file to export")
 
@@ -48,7 +54,7 @@
         self.path = args[0].strip()
         self.interactive = options.get("interactive",True)
 
-        file = None        
+        file = None
         try:
             try:
                 file = open(self.path,'r')
@@ -63,27 +69,27 @@
                 elif not self.interactive and not self.force:
                     print "Export file %s already exists. Exit." % (self.path)
                     return "error"
-    
+
                 file.close()
                 file = open(self.path,'w')
             except IOError:
                 file = open(self.path,'w')
-        
+
             csv = UnicodeWriter(file, doublequote=False, escapechar="\\", encoding=self.encoding)
             writer = None
-            
+
             qs = WpCategory.objects.filter(tagwpcategory__hidden=False).distinct()
-            
+
             total = qs.count()
-            
+
             for i,wpcat in enumerate(qs):
                 writer = show_progress(i+1, total, wpcat.label, 50, writer)
                 nb_ds = 0
                 for tag in wpcat.tagwpcategory_set.all():
                     nb_ds += tag.tag.datasheet_set.count()
-                    
-                csv.writerow([wpcat.label, u"http://fr.wikipedia.org/wiki/Catégorie:%s" % urlquote(normalize_tag(wpcat.label)), nb_ds]) 
+
+                csv.writerow([wpcat.label, u"http://fr.wikipedia.org/wiki/Catégorie:%s" % urlquote(normalize_tag(wpcat.label)), nb_ds])
 
         finally:
             if file is not None:
-                file.close()
\ No newline at end of file
+                file.close()
--- a/src/hdalab/management/commands/fill_tag_years.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/fill_tag_years.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,13 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jan 29, 2012
+Calcule les périodes de date pour les tag (:class:`hdabo.models.Tag`) catégorisés comme `Datation`.
+(c.f. :class:`hdalab.models.dataviz.TagYears`)
 
-@author: ymh
+Fait une analyse heuristique du label du tag, ou (si disponible) de l'URI DBPedia.
+Efface et remplace les objets deejà existants.
+
+**Usage**: ``django-admin fill_tag_years [options]``
+
 '''
 from django.conf import settings
 from django.core.management.base import NoArgsCommand
@@ -15,16 +20,16 @@
 class Command(NoArgsCommand):
     def handle_noargs(self, **options):
         self.style = no_style()
-        
+
         TagYears.objects.all().delete()
 
         qs = Tag.objects.filter(category__label="Datation")
         total = qs.count()
         dbptstart = len(settings.DBPEDIA_URI_TEMPLATE % ("resource",""))
         #dbptstart = len("http://dbpedia.org/resource/")
-        
+
         writer = None
-        
+
         for i,tag in enumerate(qs):
             writer = show_progress(i+1, total, tag.label, 50, writer)
             start = None
@@ -51,11 +56,11 @@
                         else:
                             start = 1 + 100*(val-1)
                         end = start + 100
-            
+
             if start != None and end != None:
                 ty = TagYears.objects.create(tag=tag, start_year=start, end_year=end)
                 ty.save()
-    
+
     def rom_to_int(self, string):
         # from http://codereview.stackexchange.com/questions/902/conversion-from-to-roman-numbers
         table=[['M',1000],['CM',900],['D',500],['CD',400],['C',100],['XC',90],['L',50],['XL',40],['X',10],['IX',9],['V',5],['IV',4],['I',1]]
@@ -64,4 +69,4 @@
             while string.startswith(letter):
                 result += value
                 string = string[len(letter):]
-        return result
\ No newline at end of file
+        return result
--- a/src/hdalab/management/commands/geojson_transform.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/geojson_transform.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,112 +1,118 @@
-# -*- coding: utf-8 -*-
-'''
-@author: raphv
-'''
-from django.conf import settings
-from django.core.management.base import BaseCommand, CommandError
-from django.utils.http import urlquote
-import json
-from SPARQLWrapper import SPARQLWrapper, JSON
-
-#import pydevd #@UnresolvedImport
-#pydevd.settrace(suspend=False)
-
-
-class Command(BaseCommand):
-    '''
-    Command to export tags
-    '''
-    args = '<path_to_geojson_file>'
-    options = ''
-    help = """Adds semantic data to countries.geo.json files"""
-        
-    def handle(self, *args, **options):
-
-        if len(args) == 0 or not args[0]:
-            raise CommandError("Give a Geo Json File to process")
-        
-        geojsonfile = args[0]
-        
-        f = open(geojsonfile,"r")
-        geojson = json.loads(f.read())
-        f.close()
-        
-        labels = [feature['properties']['label_fr'] for feature in geojson['features']]
-        #uris = dict([(label, 'http://dbpedia.org/resource/' + urlquote(label.replace(' ','_'))) for label in labels])
-        uris = dict([(label, settings.DBPEDIA_URI_TEMPLATE % ( 'resource', urlquote(label.replace(' ','_')) )) for label in labels])
-        
-        uri_list = [uris[label] for label in uris]
-        base_uris = dict([(uris[label],uris[label]) for label in uris])
-        
-        grp = 10
-        #endpoint = SPARQLWrapper("http://dbpedia.org/sparql")
-        endpoint = SPARQLWrapper(settings.DBPEDIA_URI_TEMPLATE % ( 'sparql', '' ))
-        endpoint.setReturnFormat(JSON)
-            
-        start = 0
-        while start < len(uri_list):
-            sparql = """
-                PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
-                SELECT ?source ?target
-                WHERE {
-                    ?source dbpedia-owl:wikiPageRedirects ?target .
-                    Filter (?source in (<%s>)) .
-                }
-            """ % '>, <'.join(uri_list[start:start + grp])
-            endpoint.setQuery(sparql)
-            results = endpoint.query().convert()
-            
-            for r in results["results"]["bindings"]:
-                source = r["source"]["value"]
-                target = r["target"]["value"]
-                base_uris[source] = target
-                #print "%s redirects to %s"%(source, target)
-            start += grp
-        
-        base_uri_list = [base_uris[uri] for uri in base_uris]
-        
-        french_labels = {}
-        labels = {}
-        
-        start = 0
-        while start < len(base_uri_list):
-            
-            sparql = """
-                PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-                SELECT ?country ?label WHERE {
-                  ?country rdfs:label ?label .
-                  FILTER (?country in (<%s>))
-                }
-            """ % '>, <'.join(base_uri_list[start:start + grp])
-            
-            endpoint.setQuery(sparql)
-            results = endpoint.query().convert()
-            
-            #print repr(results)
-            
-            for r in results["results"]["bindings"]:
-                country = r["country"]["value"]
-                label = r["label"]["value"]
-                if country not in labels:
-                    labels[country] = {}
-                labels[country][r["label"]["xml:lang"]] = label 
-                if r["label"]["xml:lang"] == 'fr':
-                    french_labels[country] = label
-                print "%s label: %s"%(country, label)
-            
-            start += grp
-        
-        for feature in geojson['features']:
-            base_uri = base_uris[uris[feature['properties']['label_fr']]]
-            feature['properties']['dbpedia_uri'] = base_uri
-                        
-            if labels.has_key(base_uri):
-                feature['properties']['labels'] = labels[base_uri]
-            if french_labels.has_key(base_uri):
-                feature['properties']['label_fr'] = french_labels[base_uri]
-            else:
-                print "No label for %s"%base_uri
-        
-        f = open(geojsonfile,"w")
-        f.write(json.dumps(geojson, indent=2))
-        f.close()
\ No newline at end of file
+# -*- coding: utf-8 -*-
+'''
+Ajoute des données sémantiques issues de DBPedia a des fichiers de pays geojson.
+En particulier ajoute les labels français et dans les autres langues disponibles.
+
+**Usage**: ``django-admin geojson_transform [options] [args [args ...]]``
+
+**Arguments**: <chemin_vers_fichier_geojson>
+
+'''
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.utils.http import urlquote
+import json
+from SPARQLWrapper import SPARQLWrapper, JSON
+
+#import pydevd #@UnresolvedImport
+#pydevd.settrace(suspend=False)
+
+
+class Command(BaseCommand):
+    '''
+    Command to export tags
+    '''
+    args = '<path_to_geojson_file>'
+    options = ''
+    help = """Adds semantic data to countries.geo.json files"""
+
+    def handle(self, *args, **options):
+
+        if len(args) == 0 or not args[0]:
+            raise CommandError("Give a Geo Json File to process")
+
+        geojsonfile = args[0]
+
+        f = open(geojsonfile,"r")
+        geojson = json.loads(f.read())
+        f.close()
+
+        labels = [feature['properties']['label_fr'] for feature in geojson['features']]
+        #uris = dict([(label, 'http://dbpedia.org/resource/' + urlquote(label.replace(' ','_'))) for label in labels])
+        uris = dict([(label, settings.DBPEDIA_URI_TEMPLATE % ( 'resource', urlquote(label.replace(' ','_')) )) for label in labels])
+
+        uri_list = [uris[label] for label in uris]
+        base_uris = dict([(uris[label],uris[label]) for label in uris])
+
+        grp = 10
+        #endpoint = SPARQLWrapper("http://dbpedia.org/sparql")
+        endpoint = SPARQLWrapper(settings.DBPEDIA_URI_TEMPLATE % ( 'sparql', '' ))
+        endpoint.setReturnFormat(JSON)
+
+        start = 0
+        while start < len(uri_list):
+            sparql = """
+                PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
+                SELECT ?source ?target
+                WHERE {
+                    ?source dbpedia-owl:wikiPageRedirects ?target .
+                    Filter (?source in (<%s>)) .
+                }
+            """ % '>, <'.join(uri_list[start:start + grp])
+            endpoint.setQuery(sparql)
+            results = endpoint.query().convert()
+
+            for r in results["results"]["bindings"]:
+                source = r["source"]["value"]
+                target = r["target"]["value"]
+                base_uris[source] = target
+                #print "%s redirects to %s"%(source, target)
+            start += grp
+
+        base_uri_list = [base_uris[uri] for uri in base_uris]
+
+        french_labels = {}
+        labels = {}
+
+        start = 0
+        while start < len(base_uri_list):
+
+            sparql = """
+                PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+                SELECT ?country ?label WHERE {
+                  ?country rdfs:label ?label .
+                  FILTER (?country in (<%s>))
+                }
+            """ % '>, <'.join(base_uri_list[start:start + grp])
+
+            endpoint.setQuery(sparql)
+            results = endpoint.query().convert()
+
+            #print repr(results)
+
+            for r in results["results"]["bindings"]:
+                country = r["country"]["value"]
+                label = r["label"]["value"]
+                if country not in labels:
+                    labels[country] = {}
+                labels[country][r["label"]["xml:lang"]] = label
+                if r["label"]["xml:lang"] == 'fr':
+                    french_labels[country] = label
+                print "%s label: %s"%(country, label)
+
+            start += grp
+
+        for feature in geojson['features']:
+            base_uri = base_uris[uris[feature['properties']['label_fr']]]
+            feature['properties']['dbpedia_uri'] = base_uri
+
+            if labels.has_key(base_uri):
+                feature['properties']['labels'] = labels[base_uri]
+            if french_labels.has_key(base_uri):
+                feature['properties']['label_fr'] = french_labels[base_uri]
+            else:
+                print "No label for %s"%base_uri
+
+        f = open(geojsonfile,"w")
+        f.write(json.dumps(geojson, indent=2))
+        f.close()
--- a/src/hdalab/management/commands/import_hda_insee_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/import_hda_insee_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,6 +1,11 @@
 # -*- coding: utf-8 -*-
 '''
-@author: raphv
+Importe les code INSEE dans les fiches HDA (objets :class:`hdabo.models.datasheet`).
+
+**Usage**: ``django-admin import_hda_insee_csv [options] [args [args ...]]``
+
+**Arguments**: <chemin_vers_csv_insee>
+
 '''
 import csv
 import re
@@ -18,21 +23,21 @@
     args = '<path_to_csv_file>'
     options = ''
     help = """Imports HDA Lab INSEE codes from a csv file"""
-        
+
     def handle(self, *args, **options):
 
         if len(args) == 0 or not args[0]:
             raise CommandError("Give a CSV File to import")
-        
+
         filename = args[0]
-        
+
         csvfile = open(filename, "rb")
         dialect = csv.Sniffer().sniff(csvfile.read(1024))
         csvfile.seek(0)
         reader = csv.reader(csvfile, dialect)
         fieldstoget = [ 'id', 'insee' ]
-        
-        
+
+
         for i,line in enumerate(reader):
             if i == 0:
                 fields = {}
@@ -47,9 +52,9 @@
                     rawdata = dict([(k,line[v].strip()) for k,v in fields.iteritems()])
                     # Traitement special pour la Corse
                     insee = int(re.sub('^2(A|B)','20',rawdata['insee']))
-                        
+
                     hda_id = int(rawdata['id'])
-                    
+
                     try:
                         datasheet = Datasheet.objects.get(hda_id=hda_id)
                     except Datasheet.DoesNotExist:
@@ -60,11 +65,11 @@
                     except InseeCoords.DoesNotExist:
                         print "INSEE entry for Insee Code %d does not exist" % insee
                         inseecoord = None
-                    
+
                     if datasheet is not None and inseecoord is not None:
                         dsextra, created = DatasheetExtras.objects.get_or_create(datasheet=datasheet, defaults={'insee':inseecoord})
                         if not created:
                             dsextra.insee = inseecoord
                             dsextra.save()
-        
-        csvfile.close()
\ No newline at end of file
+
+        csvfile.close()
--- a/src/hdalab/management/commands/import_hdabo_db.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/import_hdabo_db.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,27 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Feb 28, 2012
+Cette commande transforme une base de donnée hdabo en base de donnée hdalab.
+En particulier cette command est utilisée dans l'import de l'extraction rdf des données HDA.
+
+Cette commande enchaine en fait les commandes Django suivantes:
 
-@author: ymh
+    - `migrate <https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-migrate>`_
+    - :mod:`query_wikipedia_category \-f \-\-all <hdalab.management.commands.query_wikipedia_category>` (si l'option est passée)
+    - :mod:`query_dbpedia \-f \-\-all <hdalab.management.commands.query_dbpedia>`
+    - :mod:`fill_tag_years <hdalab.management.commands.fill_tag_years>`
+    - :mod:`geojson_transform \<chemin répertoire data\>/countries.geo.json <hdalab.management.commands.geojson_transform>`
+    - :mod:`query_geo_inclusion <hdalab.management.commands.query_geo_inclusion>`
+    - :mod:`import_insee_csv \<chemin répertoire data\>/villes.csv <hdalab.management.commands.import_insee_csv>`
+    - :mod:`import_insee_csv \<chemin répertoire data\>/additional_cities.csv <hdalab.management.commands.import_insee_csv>`
+    - :mod:`import_hda_insee_csv \<chemin répertoire data\>/HDA_Insee.csv <hdalab.management.commands.import_hda_insee_csv>`
+    - :mod:`query_category_inclusion \-f \-\-all <hdalab.management.commands.query_category_inclusion>`
+
+**Usage**: ``django-admin import_hdabo_db [options] [<chemin répertoire data>]``
+
+**Options spécifiques:**
+
+    - *\-c,\-\-categories*: ajoute la commande :mod:`query_wikipedia_category \-f \-\-all <hdalab.management.commands.query_wikipedia_category>` à la chaîne de traitements.
+
 '''
 from django.core.management.base import BaseCommand
 from django.core.management import call_command
--- a/src/hdalab/management/commands/import_insee_csv.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/import_insee_csv.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,59 +1,65 @@
-# -*- coding: utf-8 -*-
-'''
-@author: raphv
-'''
-from django.core.management.base import BaseCommand, CommandError
-from SPARQLWrapper import SPARQLWrapper, JSON
-from hdalab.models import InseeCoords
-import json
-import csv
-import re
-import sys
-
-class Command(BaseCommand):
-    '''
-    Command to export tags
-    '''
-    args = '<path_to_csv_file>'
-    options = ''
-    help = """Imports Insee codes and geographic coordinates from a csv file"""
-        
-    def handle(self, *args, **options):
-
-        if len(args) == 0 or not args[0]:
-            raise CommandError("Give a CSV File to import")
-        
-        filename = args[0]
-        
-        csvfile = open(filename, "rb")
-        dialect = csv.Sniffer().sniff(csvfile.read(1024))
-        csvfile.seek(0)
-        reader = csv.reader(csvfile, dialect)
-        fieldstoget = [ 'ville', 'insee', 'latitude', 'longitude' ]
-        
-        for i,line in enumerate(reader):
-            if i == 0:
-                fields = {}
-                minlength = 0
-                for j,field in enumerate(line):
-                    for fieldname in fieldstoget:
-                        if re.search('(?i)%s' % fieldname, field):
-                            fields[fieldname] = j
-                            minlength = max(j,minlength)
-            else:
-                if len(line) > minlength:
-                    rawdata = dict([(k,line[v].strip()) for k,v in fields.iteritems()])
-                    #print "Processing line %d" % i
-                    #print rawdata
-                    try:
-                        latitude = float(rawdata['latitude'].replace(',','.'))
-                        longitude = float(rawdata['longitude'].replace(',','.')) if rawdata['longitude'] != '-' else 0
-                        insee = int(rawdata['insee'])
-                        ville = unicode(rawdata['ville'], 'iso-8859-1')
-                        
-                        InseeCoords.objects.get_or_create(insee=insee, city_name=ville, latitude=latitude, longitude=longitude)
-                        
-                    except:
-                        print line, "Error :", sys.exc_info()[1]
-        
-        csvfile.close()
\ No newline at end of file
+# -*- coding: utf-8 -*-
+'''
+Importe des codes INSEE et les coordonnées géographiques d'un fichier CSV.
+Crée des objects :class:`hdalab.models.dataviz.InseeCoords`.
+
+Attention cette commande de remplace pas ni n'efface de données existante dans la base (la clef étant le numéro INSEE).
+
+**Usage**: ``django-admin import_insee_csv <chemin_vers_fichier_csv>``
+
+'''
+from django.core.management.base import BaseCommand, CommandError
+from SPARQLWrapper import SPARQLWrapper, JSON
+from hdalab.models import InseeCoords
+import json
+import csv
+import re
+import sys
+
+class Command(BaseCommand):
+    '''
+    Command to export tags
+    '''
+    args = '<path_to_csv_file>'
+    options = ''
+    help = """Imports Insee codes and geographic coordinates from a csv file"""
+
+    def handle(self, *args, **options):
+
+        if len(args) == 0 or not args[0]:
+            raise CommandError("Give a CSV File to import")
+
+        filename = args[0]
+
+        csvfile = open(filename, "rb")
+        dialect = csv.Sniffer().sniff(csvfile.read(1024))
+        csvfile.seek(0)
+        reader = csv.reader(csvfile, dialect)
+        fieldstoget = [ 'ville', 'insee', 'latitude', 'longitude' ]
+
+        for i,line in enumerate(reader):
+            if i == 0:
+                fields = {}
+                minlength = 0
+                for j,field in enumerate(line):
+                    for fieldname in fieldstoget:
+                        if re.search('(?i)%s' % fieldname, field):
+                            fields[fieldname] = j
+                            minlength = max(j,minlength)
+            else:
+                if len(line) > minlength:
+                    rawdata = dict([(k,line[v].strip()) for k,v in fields.iteritems()])
+                    #print "Processing line %d" % i
+                    #print rawdata
+                    try:
+                        latitude = float(rawdata['latitude'].replace(',','.'))
+                        longitude = float(rawdata['longitude'].replace(',','.')) if rawdata['longitude'] != '-' else 0
+                        insee = int(rawdata['insee'])
+                        ville = unicode(rawdata['ville'], 'iso-8859-1')
+
+                        InseeCoords.objects.get_or_create(insee=insee, city_name=ville, latitude=latitude, longitude=longitude)
+
+                    except:
+                        print line, "Error :", sys.exc_info()[1]
+
+        csvfile.close()
--- a/src/hdalab/management/commands/query_category_inclusion.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/query_category_inclusion.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,20 @@
 # -*- coding: utf-8 -*-
 '''
-Created on July 2, 2012
+Requête wikipedia pour reconstituer l'arbre des catégories.
+
+Cette commande utilise directement `l'api wikipedia <https://www.mediawiki.org/wiki/API:Main_page>`_ pour faire ses requêtes.
+
+**Usage**: ``django-admin query_category_inclusion [options]``
+
+**Options spécifiques:**
 
-@author: raphv
+    - *\-\-all* :               force à traiter toutes les catégories
+    - *\-\-force* :             ne pose aucune question
+    - *\-\-site=SITE_URL* :     url du site wikipedia (défaut: https://fr.wikipedia.org/w/api.php)
+    - *\-\-limit=LIMIT* :       Nombre de catégories à traiter
+    - *\-\-start=START* :       Nombre de catégories à ignorer
+    - *\-\-category=CATEGORY* : Limite le traitement à cette catégorie
+
 '''
 
 from django.conf import settings
@@ -26,7 +38,7 @@
     '''
     options = ''
     help = """query and update wikipedia for tag title."""
-    
+
     option_list = NoArgsCommand.option_list + (
         make_option('--all',
             action='store_true',
@@ -67,101 +79,101 @@
 
 
     def query_all_categories(self, category_title, site):
-        
+
         params = {'action':'query', 'cmtitle':category_title, 'list':'categorymembers', 'cmlimit': 'max'}
-        
+
         res = []
-        
+
         wpquery = api.APIRequest(site, params) #@UndefinedVariable
         response = wpquery.query()
-        
+
         if self.verbosity > 1:
             print "Query category : " + repr(wpquery.request.get_full_url()+"?"+wpquery.request.get_data())
             print repr(response)
-        
+
         members = response.get('query', {}).get('categorymembers', [])
-                    
+
         for member in members:
             title = member.get('title',"")
             if re.match(CATEGORY_PREFIX, title):
                 res.append(re.sub(CATEGORY_PREFIX, "", title))
-            
+
         if self.verbosity > 1:
             print "Query categories result: "
             print repr(res)
-            
+
         return res
-    
+
     def process_categories(self, cat_list, parent_cat):
         for cat in cat_list:
             child_cat,created = WpCategory.objects.get_or_create(label=cat) #@UnusedVariable
             WpCategoryInclusion.objects.get_or_create(parent_category=parent_cat, child_category=child_cat)
-        
+
     def handle_noargs(self, **options):
-        
+
         self.style = no_style()
-        
+
         interactive = options.get('interactive', True)
-        
+
         self.verbosity = int(options.get('verbosity', '1'))
-        
+
         force = options.get('force', False)
-        
+
         limit = options.get("limit", -1)
         start = options.get("start", 0)
-        
+
         site_url = options.get('site_url', settings.WIKIPEDIA_API_URL)
-        
+
         types_mask = 0
-        
+
         if self.verbosity > 2:
             print "option passed : " + repr(options)
 
         queryset = WpCategory.objects.filter(tags__hidden = False).distinct()
-        
+
         cat_list = options.get("category", []);
-        
+
         if cat_list:
             queryset = queryset.filter(label__in=cat_list)
-        elif options.get('all',False):            
-            queryset = queryset.annotate(wpc=Count('child_categories')).filter(wpc = 0)                    
-        
+        elif options.get('all',False):
+            queryset = queryset.annotate(wpc=Count('child_categories')).filter(wpc = 0)
+
         queryset = queryset.order_by("label")
-        
+
         if limit >= 0:
             queryset = queryset[start:limit]
         elif start > 0:
-            queryset = queryset[start:]            
-        
+            queryset = queryset[start:]
+
         if self.verbosity > 2 :
             print "Category Query is %s" % (queryset.query)
-        
+
         site = wiki.Wiki(site_url) #@UndefinedVariable
-        
-        
+
+
         count = queryset.count()
         if self.verbosity > 1:
             print "Processing %d categories" % (count)
-        
+
         if not force and interactive:
             confirm = raw_input("You have requested to query and replace the wikipedia information for %d categories.\n Are you sure you want to do this? \nType 'yes' to continue, or 'no' to cancel: " % (count))
         else:
             confirm = 'yes'
-            
+
         if confirm != "yes":
             print "wikipedia query cancelled"
             return
-        
+
         for i, category in enumerate(queryset):
-            
+
             if self.verbosity > 1:
                 print "processing category %s (%d/%d)" % (category.label, i + 1, count)
             else:
-                utils.show_progress(i + 1, count, category.label, 60)                            
-                
+                utils.show_progress(i + 1, count, category.label, 60)
+
             title = CATEGORY_PREFIX + category.label
             # query categories
 
             with transaction.atomic():
                 res = self.query_all_categories(title, site)
-                self.process_categories(res, category)
\ No newline at end of file
+                self.process_categories(res, category)
--- a/src/hdalab/management/commands/query_dbpedia.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/query_dbpedia.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,26 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jan 30, 2012
+Requête DBPedia pour renseigner les objets :class:`hdabo.models.Tag`.
+Seuls les tags sémantisés sont traités.
+
+Les données suivantes sont moissonnées:
+
+  - label dans toutes les langues disponibles
+  - résumé dans toutes les langues disponibles
+  - thumbnail
+  - lien entre les tags
 
-@author: ymh
+**Usage**: ``django-admin query_dbpedia [options]``
+
+**Options spécifiques:**
+
+    - *\-\-all* :               force à traiter tous les tags
+    - *\-\-random* :            faire le traitement des tags dans un ordre aléatoire
+    - *\-\-force* :             ne pose aucune question
+    - *\-\-limit=LIMIT* :       Nombre de tags à traiter
+    - *\-\-start=START* :       Nombre de tags à ignorer
+    - *\-\-tag=TAG* :           Limite le traitement à ce tag
+
 '''
 
 from hdabo.models import Tag
@@ -32,7 +50,7 @@
     '''
     options = ''
     help = """query and update wikipedia for tag title."""
-    
+
     option_list = NoArgsCommand.option_list + (
         make_option('--all',
             action='store_true',
@@ -68,7 +86,7 @@
             default=[],
             help='the tag to query'),
     )
-    
+
     def query_dbpedia(self, query, fmt='n3'):
         url = settings.DBPEDIA_URI_TEMPLATE % ( 'sparql', '' )
         params = {
@@ -81,58 +99,58 @@
 
 
     def handle_noargs(self, **options):
-                
+
         self.style = no_style()
-        
+
         self.interactive = options.get('interactive', True)
-        
+
         self.verbosity = int(options.get('verbosity', '1'))
-        
+
         self.force = options.get('force', False)
-        
+
         self.limit = options.get("limit", -1)
         self.start = options.get("start", 0)
-        
+
         self.random = options.get('random', False)
-                        
+
         if self.verbosity > 2:
             print "option passed : " + repr(options)
 
         self.tag_list = options.get("tags", []);
 
         queryset = Tag.objects.exclude(dbpedia_uri= None)
-        
-                
+
+
         if self.tag_list:
             queryset = queryset.filter(label__in=self.tag_list)
-        elif not options.get('all',False):            
+        elif not options.get('all',False):
             queryset = queryset.annotate(dbfc=Count('dbpedia_fields')).filter(dbfc = 0)
 
         if self.random:
             queryset = queryset.order_by("?")
         else:
             queryset = queryset.order_by("label")
-        
+
         if self.limit >= 0:
             queryset = queryset[self.start:self.limit]
         elif self.start > 0:
             queryset = queryset[self.start:]
-        
+
         if self.verbosity > 2 :
             print "Tag Query is %s" % (queryset.query)
 
         count = queryset.count()
-        
+
         if count == 0:
             print "No tag to query : exit."
             return
-            
-            
+
+
         if not self.force and self.interactive:
             confirm = raw_input("You have requested to query and replace the dbpedia information for %d tags.\n Are you sure you want to do this? \nType 'yes' to continue, or 'no' to cancel: " % (count))
         else:
             confirm = 'yes'
-            
+
         if confirm != "yes":
             print "dbpedia query cancelled"
             return
@@ -141,12 +159,12 @@
         for i,tag in enumerate(queryset):
             writer = show_progress(i+1, count, tag.label, 50, writer)
             db.reset_queries()
-            
+
             #abstract query
             #"select ?y
             # where {<%s>  <http://dbpedia.org/ontology/abstract> ?y}" % (tag.dbpedia_uri)
-            
-            #rdf_uri = re.sub('\/resource\/', "/data/", tag.dbpedia_uri) + ".n3"            
+
+            #rdf_uri = re.sub('\/resource\/', "/data/", tag.dbpedia_uri) + ".n3"
             #g = Graph()
             try :
                 abstracts = {}
@@ -157,12 +175,12 @@
                     for _,_,o in res_abstracts.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
                         abstracts[o.language] = (unicode(o), True)
                     logger.debug("Abstracts: %r" % abstracts)
-                    
+
                     res_labels = self.query_dbpedia("select distinct ?y where {<%s>  <http://www.w3.org/2000/01/rdf-schema#label> ?y}" % (tag.dbpedia_uri), 'n3')
                     for _,_,o in res_labels.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
                         labels[o.language] = (unicode(o), True)
                     logger.debug("Labels: %r" % labels)
-                    
+
                     res_thumbnails = self.query_dbpedia("select distinct ?y where {<%s>  <http://dbpedia.org/ontology/thumbnail> ?y} limit 1" % (tag.dbpedia_uri), 'n3')
                     for _,_,o in res_thumbnails.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
                         thumbnail = unicode(o)
@@ -172,7 +190,7 @@
                         tagqs = Tag.objects.filter(dbpedia_uri=unicode(o))
                         if tagqs:
                             TagLinks.objects.get_or_create(subject=tag, object=tagqs[0])
-                    
+
                     ref_label_lang, (ref_label, _) = ('fr',labels['fr']) if 'fr' in labels else ('en',labels['en']) if 'en' in labels else labels.items()[0] if len(labels) > 0 else ('fr',(tag.label, True))
                     ref_abstract_lang, (ref_abstract, _) = ('fr',abstracts['fr']) if 'fr' in abstracts else ('en',abstracts['en']) if 'en' in abstracts else abstracts.items()[0] if len(abstracts) > 0 else ('fr',(None, 'True'))
 
@@ -182,7 +200,7 @@
                         if lang[0] not in abstracts:
                             abstracts[lang[0]] = (ref_abstract, False)
 
-                    dbfield , created = DbpediaFields.objects.get_or_create(tag=tag, defaults={'dbpedia_uri':tag.dbpedia_uri, 'abstract':ref_abstract, 'thumbnail':thumbnail, 'label':ref_label}) #@UndefinedVariable                    
+                    dbfield , created = DbpediaFields.objects.get_or_create(tag=tag, defaults={'dbpedia_uri':tag.dbpedia_uri, 'abstract':ref_abstract, 'thumbnail':thumbnail, 'label':ref_label}) #@UndefinedVariable
                     if not created:
                         dbfield.dbpedia_uri = tag.dbpedia_uri
                         dbfield.abstract = ref_abstract
@@ -198,22 +216,22 @@
                         if lang in consolidated_trans:
                             consolidated_trans[lang][1] = abstract
                         else:
-                            consolidated_trans[lang] = [(ref_label, lang==ref_label_lang), abstract] 
-                         
+                            consolidated_trans[lang] = [(ref_label, lang==ref_label_lang), abstract]
+
                     for lang, trans in consolidated_trans.iteritems():
                         label, abstract = tuple(trans)
                         DbpediaFieldsTranslation.objects.create(master=dbfield, language_code=lang, label=label[0], is_label_translated=label[1], abstract=abstract[0], is_abstract_translated=abstract[1])
-                    
-                    
+
+
             except Exception as e:
                 if tag.dbpedia_uri:
                     print "\nError processing resource %s : %s" %(tag.dbpedia_uri,unicode(e))
                 else:
                     print "\nError processing resource %s" % unicode(e)
                 traceback.print_exception(type(e), e, sys.exc_info()[2])
-                
+
 
 
-            
-            
+
 
+
--- a/src/hdalab/management/commands/query_geo_inclusion.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/query_geo_inclusion.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,9 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Feb 22, 2012
+Requête DBPedia afin de déterminer dans quel pays sont les tag de localisation.
 
-@author: raphv
+**Usage**: ``django-admin query_geo_inclusion [options]``
+
 '''
 from django.conf import settings
 from django.core.management.base import NoArgsCommand
@@ -22,7 +23,7 @@
 
         qs = Tag.objects.filter(category__label="Localisation").exclude(dbpedia_uri = None)
         total = qs.count()
-        
+
         #endpoint = SPARQLWrapper("http://dbpedia.org/sparql")
         endpoint = SPARQLWrapper(settings.DBPEDIA_URI_TEMPLATE % ( 'sparql', '' ))
         endpoint.setReturnFormat(JSON)
@@ -36,31 +37,31 @@
         #resourceprefix = "http://dbpedia.org/resource/"
         resourceprefix = settings.DBPEDIA_URI_TEMPLATE % ( 'resource', '' )
         identityuri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
-        
+
         writer = None
-        
+
         for i,tag in enumerate(qs):
             endpoint.setQuery(sparqltext % (tag.dbpedia_uri, tag.dbpedia_uri))
-    
+
             results = endpoint.query().convert()['results']['bindings']
-            
+
             if len(results) == 1: # We don't want places located in multiple countries
-                
+
                 resourceuri = results[0]['resource']['value']
-                
+
                 if re.match(resourceprefix, resourceuri):
                     countrytxt = re.findall('([^/]+$)', resourceuri)[0]
-                    
+
                     country, _ = Country.objects.get_or_create(dbpedia_uri=resourceuri)
                     GeoInclusion.objects.get_or_create(tag=tag, country=country)
-                    
+
                 if resourceuri == identityuri:
                     countrytxt = '<is a country>'
-                    
+
                     country, _ = Country.objects.get_or_create(dbpedia_uri=tag.dbpedia_uri)
                     GeoInclusion.objects.get_or_create(tag=tag, country=country)
-                
+
             else:
                 countrytxt = '<unknown>'
-            
-            writer = show_progress(i+1, total, '%s => %s'%(tag.label, countrytxt), 50, writer)
\ No newline at end of file
+
+            writer = show_progress(i+1, total, '%s => %s'%(tag.label, countrytxt), 50, writer)
--- a/src/hdalab/management/commands/query_wikipedia_category.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/query_wikipedia_category.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,32 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Jun 7, 2011
+Requête Wikipedia qui renseigne les différentes catégories wikipedia pour les tag sémantisés.
+
+Les données suivantes sont moissonée pour chaque tag sémantisé (i.e. article Wikipedia)
+    - catégories visibles (`visible`)
+    - catégories cachées (`hidden`)
+    - paramêtres d'infobox (`infobox`)
+
+Les objets créé sont les suivants:
+
+    - catégories : :class:`hdalab.models.WpCategory` et :class:`hdalab.models.TagWpCategory`
+    - paramêtre d'infobox : :class:`hdalab.models.InfoboxParameter` et :class:`hdalab.models.TagInfobox`
+
+Cette commande utilise directement `l'api wikipedia <https://www.mediawiki.org/wiki/API:Main_page>`_ pour faire ses requêtes.
 
-@author: ymh
+**Usage**: ``django-admin query_wikipedia_category [options]``
+
+**Options spécifiques:**
+
+    - *\-\-all* :               force à traiter tous les tags
+    - *\-\-random* :            faire le traitement des tags dans un ordre aléatoire
+    - *\-\-force* :             ne pose aucune question
+    - *\-\-limit=LIMIT* :       Nombre de tags à traiter
+    - *\-\-start=START* :       Nombre de tags à ignorer
+    - *\-\-type=TYPES* :        Quel type de requête faire : `visible` : catégories visibles, `hidden` : catégories cachées, `infobox`: infoboxes, `all`: toutes (défaut). cette option peut être passée plusieurs fois.
+    - *\-\-use\-label* :        Utilise le label du tag au lieu du pageid pour faire la requête wikipedia
+    - *\-\-tag=TAG* :           Limite le traitement à ce tag
+
 '''
 
 from django.conf import settings
--- a/src/hdalab/management/commands/send_moderation_mail.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/management/commands/send_moderation_mail.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,8 +1,14 @@
 # -*- coding: utf-8 -*-
 '''
-Created on Mar 5, 2015
+Envoie un mail récapitulatif des renkan à modérer.
+Aucun mail n'est envoyé si aucune modération n'est demandée.
+
+L'envoi est fait aux utilisateurs marqués comme `staff <https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#django.contrib.auth.models.User.is_staff>`_.
 
-@author: ymh
+cette commande est typiquement prévue pour être lancée à partir d'une tâche ``cron`` périodique (1 fois par jour par exemple).
+
+**Usage**: ``django-admin send_moderation_mail [options]``
+
 '''
 
 import logging
@@ -26,30 +32,30 @@
 
 TEMPLATE_NAME = "mails/moderation_notice"
 class Command(NoArgsCommand):
-    
+
     def handle_noargs(self, **options):
         # query renkan to moderate
         set_script_prefix(settings.SCRIPT_PREFIX)
-        
+
         renkan_query = HdalabRenkan.objects.filter(state=HdalabRenkan.MODERATED)
-        
+
         renkan_count = renkan_query.count()
-        
+
         if renkan_count == 0:
             logger.info("Send moderation email : no renkan to moderate. exiting")
             return
 
         logger.debug("Send moderation email : %d renkan(s) to moderate", renkan_count)
-        
+
         renkan_list = list(renkan_query.select_related()[:20])
-        
+
         connection = mail.get_connection()
         try:
             connection.open()
             for email_recipient in User.objects.filter(is_staff=True):
                 if not email_recipient.email:
                     continue
-    
+
                 msg_html = ""
                 msg_txt = ""
                 try:
@@ -67,7 +73,7 @@
                 except Exception as e:
                     logger.error("Error rendering template %s : %r", TEMPLATE_NAME, e)
                     raise e
-        
+
                 if not msg_html and not msg_txt:
                     logger.info("Send moderation email: nothing to email exiting")
                     continue
@@ -76,4 +82,3 @@
                 emsg.send(fail_silently=True)
         finally:
             connection.close()
-    
\ No newline at end of file
--- a/src/hdalab/models/categories.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/models/categories.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 '''
 Created on Jan 26, 2012
 
@@ -8,35 +9,66 @@
 
 
 class WpCategory(models.Model):
+    """
+    Une catégorie Wikipedia.
+
+    :cvar str label: Le label de la catégorie.
+    """
     label = models.CharField(max_length=2048, unique=True, blank=False, null=False)
-    
+
     def __unicode__(self):
         return unicode(self.label)
-    
+
     class Meta:
         app_label = 'hdalab'
         verbose_name_plural = "WpCategories"
 
 class TagWpCategory(models.Model):
+    """
+    Relie une catégorie Wikipedia à un tag.
+
+    :cvar object tag: Le tag.
+    :cvar object wp_category: La categorie wikipedia.
+    :cvar bool hidden: Indique si la catégorie est cachée ou pas.
+    """
     tag = models.ForeignKey(Tag, related_name="wp_categories")
     wp_category = models.ForeignKey(WpCategory, related_name="tags")
     hidden = models.BooleanField(blank=False, null=False, default=False)
-    
+
     class Meta:
         app_label = 'hdalab'
         unique_together = ('tag', 'wp_category', 'hidden')
 
+
 class TagInfobox(models.Model):
+    """
+    Contenu de l'infobox wikipedia pour un tag.
+
+    :cvar object tag: Le tag
+    :cvar str name: Le nom (type) de l'infobox.
+    :cvar str source: Le code source de l'infobox.
+    :cvar int revision_id: Numéro de révision de l'infobox.
+    """
+
     tag = models.ForeignKey(Tag, related_name="infoboxes")
     name = models.CharField(max_length=2048, unique=False, blank=False, null=False)
     source = models.TextField(unique=False, blank=True, null=True)
     revision_id = models.BigIntegerField(unique=False, blank=True, null=True)
-    
+
     class Meta:
         app_label = 'hdalab'
         unique_together = ('tag','name','revision_id')
-    
+
+
 class InfoboxParameter(models.Model):
+    """
+    Valeurs de paramêtre d'une infobox Wikipedia.
+
+    :cvar object tag_infobox: L'objet :class:TagInfobox.
+    :cvar str param_name: Nom du paramêtre.
+    :cvar str param_value: Valeur du paramêtre.
+    """
+
     tag_infobox = models.ForeignKey(TagInfobox)
     param_name = models.CharField(max_length=2048, unique=False, blank=False, null=False)
     param_value = models.TextField(unique=False, blank=True, null=True)
@@ -48,9 +80,16 @@
 # Added on 02/07/2012
 
 class WpCategoryInclusion(models.Model):
+    """
+    Classe permettant de modéliser l'arbre de catégorie Wikipedia.
+
+    :cvar object parent_category: La catégorie parente.
+    :cvar object child_category: La catégorie enfant.
+    """
+
     parent_category = models.ForeignKey(WpCategory, related_name="child_categories")
     child_category = models.ForeignKey(WpCategory, related_name="parent_categories")
-    
+
     class Meta:
         app_label = 'hdalab'
-        unique_together = ('parent_category','child_category')
\ No newline at end of file
+        unique_together = ('parent_category','child_category')
--- a/src/hdalab/models/dataviz.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/models/dataviz.py	Wed Apr 11 12:19:47 2018 +0200
@@ -11,44 +11,80 @@
 
 
 class TagYears(models.Model):
-    
+    """
+    Représente une période (début - fin) associée à un Tag.
+
+    :cvar object tag: Le tag
+    :cvar int start_year: L'année de début de la période.
+    :cvar int end_year: L'année de fin de période.
+    """
     tag = models.OneToOneField(Tag, related_name="years", blank=False, null=False, db_index=True)
     start_year = models.IntegerField(blank=False, null=False, db_index=True)
     end_year = models.IntegerField(blank=False, null=False, db_index=True)
-    
+
     class Meta:
         app_label = 'hdalab'
-        
+
 
 class TagLinks(models.Model):
-    
+    """
+    Représente un lien entre tag.
+
+    :cvar object subject: Le tag sujet (source) du lien.
+    :cvar object object: Le tag object (cible) du lien.
+    """
+
     subject = models.ForeignKey(Tag, blank=False, null=False, db_index=True, related_name="taglinks_subjects")
     object = models.ForeignKey(Tag, blank=False, null=False, db_index=True, related_name="taglinks_objects")
-    
+
     class Meta:
         app_label = 'hdalab'
 
 class Country(models.Model):
-    
+    """
+    Représente un pays.
+
+    :cvar str dbpedia_uri: L'URI DBPedia de ce pays.
+    """
+
     dbpedia_uri = models.URLField(max_length=255, blank=False, null=False, db_index=True, unique=True)
-    
+
     class Meta:
         app_label = 'hdalab'
 
 class GeoInclusion(models.Model):
-    
+    """
+    Représente une relation entre un tag et un pays. (par exemple, le tage "Paris" est inclus dans le pays "France")
+    Un tag ne peut être relié qu'a un seul pays.
+
+    :cvar object tag: le tag.
+    :cvar object country: Le pays.
+
+    """
+
     tag = models.OneToOneField(Tag, related_name="locatedin", db_index=True)
     country = models.ForeignKey(Country, blank=False, null=False, related_name="includes", db_index=True)
-    
+
     class Meta:
         app_label = 'hdalab'
 
 class DbpediaFields(models.Model):
+    """
+    Informations DBPedia pour un tag.
+    Un tag ne peut être lié qu'à une seule instance de cette classe.
+
+    :cvar str dbpedia_uri: L'URI DBPedia.
+    :cvar object tag: Le tag.
+    :cvar str abstract: Texte résumé du tag issu de DBPedia.
+    :cvar str thumbnail: URL d'un thumbnail pour le tag.
+    :cvar str label: Label DBPedia pour le tag.
+
+    """
 
     dbpedia_uri = models.URLField(max_length=2048, blank=False, null=False, db_index=True, unique=False)
     tag = fields.OneToOneField(Tag, db_index=True, related_name="dbpedia_fields", related_default=lambda instance: None)
     abstract = models.TextField(blank=True, null=True)
-    thumbnail = models.URLField(max_length=2048, blank=True, null=True, db_index=False)    
+    thumbnail = models.URLField(max_length=2048, blank=True, null=True, db_index=False)
     label = models.CharField(max_length=2048, unique=False, blank=True, null=True)
 
     class Meta:
@@ -56,6 +92,16 @@
 
 
 class DbpediaFieldsTranslation(models.Model):
+    """
+    Les traductions pour un :class:DbpediaField.
+
+    :cvar object master: Le DBPediafield
+    :cvar str language_code: Le code de la langue de la traduction.
+    :cvar str label: Le label traduit. Attention si une traduction du label n'a pas été trouvée, on trouvera là le même label que dans "master".
+    :cvar str abstract: Le résumé traduit. Attention si une traduction du résumé n'a pas été trouvée, on trouvera là le même label que dans "master".
+    :cvar bool is_label_translated: Indique si le label est effectivement traduit.
+    :cvar bool is_abstract_translated: Indicque si le résumé est effectivement traduit.
+    """
 
     master = models.ForeignKey(DbpediaFields, blank=False, null=False, db_index=True, related_name="translations")
     language_code = models.CharField(max_length=15, blank=False, null=False, db_index=True)
@@ -69,27 +115,45 @@
 
 
 class HdaSession(models.Model):
-    
+    """
+    Classe destinée à sauvagarder des session d'exploration sur HDALab (état de l'interface de recherche par facette).
+    Cet objet n'est pas utilisé.
+    """
+
     sessionid = models.CharField(max_length=36, unique=True, blank=False, null=False, db_index=True)
     data = models.TextField(blank=True, null=True)
-    
+
     class Meta:
         app_label = 'hdalab'
 
 class InseeCoords(models.Model):
-    
+    """
+    Coordonnées géographiques et nom de l'entité pour un code INSEE.
+
+    :cvar integer insee: code insee.
+    :cvar str city_name: Nom de la commune.
+    :cvar float latitude: Latitude.
+    :cvar float longitude: Longitude.
+    """
+
     insee = models.IntegerField(primary_key=True)
     city_name = models.CharField(max_length=255, blank=False, null=False)
     latitude = models.FloatField(blank=False, null=False)
     longitude = models.FloatField(blank=False, null=False)
-    
+
     class Meta:
         app_label = 'hdalab'
 
 class DatasheetExtras(models.Model):
-    
+    """
+    Information supplémentaire pour und fiche hda.
+
+    :cvar object datasheet: La fiche HDA.
+    :cvar object insee: Les information insee (:class:InseeCoords) pour la fiche.
+    """
+
     datasheet = models.OneToOneField(Datasheet, related_name="extras", db_index=True)
     insee = models.ForeignKey(InseeCoords, blank=True, null=True, db_index=True)
-    
+
     class Meta:
-        app_label = 'hdalab'
\ No newline at end of file
+        app_label = 'hdalab'
--- a/src/hdalab/models/renkan.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/models/renkan.py	Wed Apr 11 12:19:47 2018 +0200
@@ -15,35 +15,54 @@
 logger = logging.getLogger(__name__)
 
 class HdalabRenkan(models.Model):
-    
+    """
+    Classe representant un Renkan HDALab.
+    Est utilisée pour ajouter au projet renkan des informations sur l'état d'édition ou bien si il est marqué comme favori.
+
+    :cvar object renkan: Le renkan lui même.
+    :cvar int state: État du renkan (1: en édition, 2: en modération, 3: publié, 4: rejeté).
+    :cvar bool favorite: Le renkan est marqué comme favori ou pas.
+    """
+
     EDITION = 1
     MODERATED = 2
     PUBLISHED = 3
     REJECTED = 4
-      
+
     STATE_CHOICES = (
     (EDITION, 'edition'),
     (MODERATED, 'moderated'),
     (PUBLISHED, 'published'),
     (REJECTED, 'rejected'),
     )
-    
+
     STATE_CHOICES_DICT = {
         EDITION: _('edition_state'),
         MODERATED: _('moderated_state'),
         PUBLISHED: _('published_state'),
         REJECTED: _('rejected_state')
     }
-    
+
     renkan = models.ForeignKey(Renkan, blank=False, null=False)
     state = models.IntegerField(choices=STATE_CHOICES, default=1)
     favorite = models.BooleanField(null=False, blank=False, default=False)
-    
+
     class Meta:
         app_label = 'hdalab'
 
 
 class HdalabRenkanStateTransition(models.Model):
+    """
+    Modélise un changement de statut du renkan.
+    Permet de garder l'historique des changements de statut.
+
+    :cvar object renkan: Le renkan.
+    :cvar int from_state: le statut initial.
+    :cvar int to_state: le statut final.
+    :cvar datetime ts: date/heure du changement.
+    :cvar str message: Message (optionel) associé au changement de statut.
+    :cvar object author: Utilisateur ayant initié le changement de statut.
+    """
 
     renkan = models.ForeignKey(HdalabRenkan, blank=False, null=False, related_name='states')
     from_state = models.IntegerField(choices=HdalabRenkan.STATE_CHOICES, default=1, blank=False, null=False)
@@ -51,7 +70,7 @@
     ts = models.DateTimeField(auto_now_add=True, blank=False, null=False)
     message = models.TextField(blank=True, null=True)
     author = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, null=False)
-    
+
     class Meta:
         app_label = 'hdalab'
         ordering = ["-ts"]
--- a/src/hdalab/services.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/services.py	Wed Apr 11 12:19:47 2018 +0200
@@ -23,6 +23,14 @@
 
 @transaction.atomic
 def change_renkan_state(hda_renkan, state, message=None, author=None):
+    """
+    Change l'état d'un renkan et crée un objet :class:`hdalab.models.HdalabRenkanStateTransition` dans une transaction unique.
+
+    :param:hda_renkan: L'objet :class:`hdalab.models.HdaRenkan`.
+    :param:state: L'état cible.
+    :param:message: Le message de changement d'état.
+    :param:author: L'utilisateur (:class:`hdabo.models.User`).
+    """
 
     if state != hda_renkan.state:
 
@@ -32,6 +40,13 @@
 
 
 def renkan_capture_preview(hdalab_renkan):
+    """
+    Lance la création d'une miniature pour un renkan.
+    Ceci est fait en ouvrant l'url `renkan_full` (:ref:`affichage-d-un-renkan-en-plein-ecran`) avec PhantomJS, et en déclenchant une capture "d'écran".
+
+    :param:hdalab_renkan: Une instance de :class:`hdalab.models.renkan.HdalabRenkan`.
+
+    """
     #get last state date or last modification date
     #states are ordered by ts
     folder_date = hdalab_renkan.renkan.modification_date
--- a/src/hdalab/signals.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/signals.py	Wed Apr 11 12:19:47 2018 +0200
@@ -21,8 +21,8 @@
 logger = logging.getLogger(__name__)
 
 MAIL_TEMPLATES = {
-    (HdalabRenkan.MODERATED,HdalabRenkan.PUBLISHED): ("mails/published_renkan", "Renkan publié"),
-    (HdalabRenkan.MODERATED,HdalabRenkan.REJECTED): ("mails/rejected_renkan", "Renkan rejeté"),
+    (HdalabRenkan.MODERATED, HdalabRenkan.PUBLISHED): ("mails/published_renkan", "Renkan publié"),
+    (HdalabRenkan.MODERATED, HdalabRenkan.REJECTED): ("mails/rejected_renkan", "Renkan rejeté"),
     (HdalabRenkan.PUBLISHED, HdalabRenkan.EDITION): ("mails/unpublished_renkan", "Renkan dépublié"),
     (HdalabRenkan.PUBLISHED, HdalabRenkan.REJECTED): ("mails/rejected_renkan", "Renkan rejeté"),
 }
@@ -30,6 +30,15 @@
 
 #TODO put into queue
 def send_renkan_moderation_messages(sender, **kwargs):
+    """
+    Envoie un email suite au changement de status d'un renkan.
+    Le template à utiliser pour l'email est donné par la constante `MAIL_TEMPLATES` et est fonction du statut de dépard et du status d'arrivé.
+    Si aucun template est trouvé, aucun mail n'est envoyé.
+
+    :param:instance: l'objet :class:`hdalab.models.renkan.HdalabRenkanStateTransition` venant d'être créé.
+
+    """
+
     renkan_state = kwargs.get('instance', None)
     if not renkan_state or (renkan_state.from_state,renkan_state.to_state) not in MAIL_TEMPLATES:
         return
@@ -51,7 +60,7 @@
 #        logger.error("Error rendering template %s for state %s : %r", MAIL_TEMPLATES[template_key], HdalabRenkan.STATE_CHOICES_DICT[renkan_state.to_state], e)
 #        return
 #        raise e
-    
+
     if msg_txt and msg_html and renkan_state.renkan and renkan_state.renkan.renkan and renkan_state.renkan.renkan.owner and renkan_state.renkan.renkan.owner.email:
         logger.debug("Sending following mail to %s : %s", renkan_state.renkan.renkan.owner.email, msg_txt)
         emsg = EmailMultiAlternatives(subject, msg_txt, settings.DEFAULT_FROM_EMAIL, [renkan_state.renkan.renkan.owner.email])
@@ -60,10 +69,17 @@
 
 
 def queue_renkan_rendering(sender, **kwargs):
+    """
+    Gère le calcul et l'effacement de la miniature d'un renkan en fonction de sont statut.
+      - Si un renkan était publié et change d'état, la miniature est effacée.
+      - Si un renkan devient publié, une demande de calcul de miniature est mise en file d'attente (c.f. :func:`hdalab.tasks.capture_preview`).
+
+    :param:instance: l'objet :class:`hdalab.models.renkan.HdalabRenkanStateTransition` venant d'être créé.
+    """
     renkan_state = kwargs.get('instance', None)
     if not renkan_state:
         return
-    
+
     if renkan_state.from_state == HdalabRenkan.PUBLISHED and renkan_state.renkan.renkan.image != settings.DEFAULT_RENKAN_ICON:
         if renkan_state.renkan.renkan.image:
             renkan_state.renkan.renkan.image.delete(False)
@@ -75,13 +91,19 @@
         capture_preview.delay(renkan_state.renkan.renkan.rk_id)  # @UndefinedVariable
 
 def renkan_delete_image(sender, **kwargs):
+    """
+    Efface la miniature d'un renkan si celui-ci est effacé.
+
+    :param:instance: l'objet :class:`renkanmanager.models.Renkan` qui va être effacé.
+
+    """
     renkan = kwargs.get('instance', None)
     if not renkan or not renkan.image or renkan.image == settings.DEFAULT_RENKAN_ICON:
         return
     renkan.image.delete(False)
     renkan.image.delete_thumbnails()
 
-    
+
 RENKAN_MODERATION_UUID = "e2f84503-609b-4efa-819d-908e2efe7b1b"
 RENKAN_RENDERING_UUID = "b8830748-be2b-479a-8aef-c8d952437b2f"
 RENKAN_DELETE_UUID = "09c23ca2-4d59-4c29-b94a-2c2672d5a89b"
--- a/src/hdalab/views/__init__.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/views/__init__.py	Wed Apr 11 12:19:47 2018 +0200
@@ -1,4 +1,7 @@
+"""
+HDALab views.
 
+"""
 import logging
 import sys
 
@@ -15,4 +18,4 @@
         import traceback
         logger.error("server_error %s : %s", sys.exc_info()[0], traceback.format_exc())
     response.status_code = 500
-    return response
\ No newline at end of file
+    return response
--- a/src/hdalab/views/ajax.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/views/ajax.py	Wed Apr 11 12:19:47 2018 +0200
@@ -23,6 +23,23 @@
 logger = logging.getLogger(__name__)
 
 def tagtranslation(request):
+    """
+    Vue donnant des traductions de label de tag pour une langue.
+    la recherche se fait dans les objets :class:`hdalab.models.DbpediaFieldsTranslation`.
+
+    Paramêtres GET:
+        :var lang: La langue demandée
+        :var labels: Un ou plusieurs labels de tag (séparateur : ",")
+
+    Réponse (application/json):
+        Un dictionnaire sous la forme ::
+
+            {
+                "<label1>": "<translation>",
+                "<label2>": "<translation>"
+            }
+
+    """
 
     lang = request.GET.get('lang',request.LANGUAGE_CODE)
     labels = request.GET.get('labels',None)
@@ -46,7 +63,19 @@
 
     return HttpResponse(content=json.dumps(translations), content_type='application/json')
 
-def subcat(category, globtags, level, max_level ):
+
+
+def subcat(category, globtags, level, max_level):
+    """
+    Méthode récursive utilisée pour reconstruire un arbre de catégories.
+
+    :param object category: La catégorie racine.
+    :param dict globtags: dictionnaire flobal des tags.
+    :param int level: Niveau de récursion.
+    :param int max_level: Niveau maximum de récursion (level <= max_level)
+
+    :returns: L'arbre des catégories.
+    """
     # recursive function used by cattree
     catlabel = category.label
     tags = Tag.objects.filter(wp_categories__wp_category = category).distinct()
@@ -70,6 +99,15 @@
     return resobj
 
 def cleantags(category):
+    """
+    Methode annexe qui nettoie recursivement un arbre de catégorie. elle effectue les actions suivantes:
+      - retire les clefs correspondant à des listes vides ('contents' et 'themes')
+      - trie les listes 'themes' par label
+      - trie les listes 'contents' par score
+
+    :param category: la catégorie racine où commencer le traitement.
+
+    """
     if category.has_key('contents') and len(category['contents']) == 0:
         del category['contents']
     if category.has_key('contents'):
@@ -86,6 +124,37 @@
     return category
 
 def cattree(request):
+    """
+    Contruit l'arbre de catégorie pour un label.
+    Les contenus attachés aux noeud sont des listes de fiches hdalab triées par score.
+    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.
+
+    Paramêtres GET :
+        :var label: Le label
+
+    Réponse (application/json):
+        Un json représentant l'arbre des catégories avec pour chaque noeud une liste ordonnée de fiches liée à la catégorie.
+
+        exemple ::
+
+            {
+                "label": "<label1>",
+                "themes": [ { "label": "<label1.1>", "themes": [...], "contents": [...]}, ...],
+                "contents": [
+                    {
+                        "organization": "Ciclic",
+                        "description": "Ciclic propose...",
+                        "score": 7,
+                        "title": "Vocabulaire de l'analyse filmique...",
+                        "url": "http://upopi.ciclic.fr/vocabulaire/definition/sceance-11",
+                        "hda_id": "5879",
+                        "organization_url": "http://www.ciclic.fr/",
+                        "id": 14852
+                    },
+                    ...
+                ]
+            }
+    """
     # Gets the category tree from a label
     ROOT_MAX_TAG_ORDER = 8
     MAX_TAG_ORDER = 8
@@ -146,7 +215,12 @@
 
     return HttpResponse(content=json.dumps(resobj), content_type='application/json')
 
+
 def sessioninfo(request):
+    """
+    Vue gérant les session Hda permettant de sauvegarder un état d'interface.
+    Note : Cette vue n'est pas mappée dans le module `hdalab.url`.
+    """
 
     data = json.loads(request.GET.get('data', "{}"))
     write = False
@@ -188,6 +262,41 @@
 
 
 def tagsearch(request):
+    """
+    Vue permettant la recherche dans les tag.
+    La recherche se fait dans les objets :class:`hdabo.models.Tag`, :class:`hdalab.models.DbpediaFields` et :class:`hdalab.models.DbpediaFieldsTranslation`.
+
+    Paramêtres GET:
+        :var (str) term: Le terme à rechercher.
+        :var (str) lang: La langue dans laquelle il faut faire la recherche.
+        :var (int) count: Le nombre maximum de résultat.
+        :var (bool) count_notices: Ajoute ou pas le nombre de notices par tag.
+
+    Réponse (application/json):
+        Une liste comprenant les résultats de la recherche.
+
+        exemple ::
+
+            [
+                {
+                    "original_label": "Cathédrale Notre-Dame de Chartres",
+                    "url": "http://fr.wikipedia.org/wiki/Cath%C3%A9drale_Notre-Dame_de_Chartres",
+                    "abstract": "La cathédrale Notre-Dame de Chartres ...",
+                    "value": "Cathédrale Notre-Dame de Chartres",
+                    "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Chartres_Cath+Gare.JPG?width=300",
+                    "nb": 7
+                },
+                {
+                    "original_label": "Cathédrale Notre-Dame de Paris",
+                    "url": "http://fr.wikipedia.org/wiki/Cath%C3%A9drale_Notre-Dame_de_Paris",
+                    "abstract": "La cathédrale Notre-Dame de Paris...",
+                    "value": "Cathédrale Notre-Dame de Paris",
+                    "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Notre_Dame_de_Paris_DSC_0846w.jpg?width=300",
+                    "nb": 6
+                },
+                ...
+            ]
+    """
 
     q = request.GET.get('term',None)
     maxcount = int(request.GET.get('count','40'))
@@ -252,7 +361,29 @@
 
     return HttpResponse(content=json.dumps(res), content_type='application/json')
 
+
+
 def catsearch(request):
+    """
+    Vue permettant la recherche de catégorie. On se restreint aux catégories qui sont aussi des tags.
+
+    Paramêtres GET:
+        :var (str) term: Le terme à rechercher.
+
+    Réponse (application/json):
+        Une liste comprenant le résultat de la recherche.
+
+        exemple ::
+
+            [
+                { "value": "1982 au cinéma" },
+                { "value": "Cinéma italien" },
+                { "value": "2003 au cinéma" },
+                ...
+            ]
+
+    """
+
 
     q = request.GET.get('term',None)
 
@@ -268,7 +399,27 @@
 
     return HttpResponse(content=json.dumps(res), content_type='application/json')
 
+
+
 def filter(request):
+    """
+    Vue permettant de filtrer par facette des fiches HDA.
+    Cette méthode est en fait un simple wrapper pour la méthode `filter_generic`.
+
+    Paramêtres GET:
+        :var lang: la langue de recherche (défaut: fr-fr).
+        :var period: Période dans laquelle doit se faire la recherche.
+        :var label: un mot-clef.
+        :var country: Une liste de pays limitant la recherche.
+        :var contentlist: Liste de fiches limitant la recherche.
+        :var mto: Ordre maximum des tags (défaut: 12).
+        :var contentcount: nombre de fiches maximum (défaut : 8).
+        :var tagcount: nombre maximum de tag (défaut: 30).
+
+    Réponse (application/json):
+        Un objet comprenant le résultat de la recherche.
+    """
+
 
     lang = request.GET.get('lang',request.LANGUAGE_CODE)
     periode = request.GET.get('period',None)
@@ -285,6 +436,128 @@
 
 
 def filter_generic(lang="fr-fr", periode=None, label=None, country=None, contentlist=None, max_tag_order=12, content_count=8, tag_count=30):
+    """
+    Méthode de recherche par facette sur les fiches HDA.
+
+    :param str lang: La langue de recherche (défaut: "fr-fr").
+    :param str period: Période d'année limitant la recherche. Le format est `<année-début>,<année-fin>` (défaut: None).
+    :param str label: Limite la recherche à un label de tag (défaut: None).
+    :param str country: Liste de pays où limiter la recherche. Le format est `<uri dbpedia pays 1>,<uri dbpedia pays 2>...` (défaut: None).
+    :param str contentlist: Liste d'id de fiche HDA (:class:`hdabo.models.Datasheet`) limitant la recherche. Le format est `<id1>,<id2>...` (défaut: None)
+    :param int max_tag_order: Limite le nombre maximum de tag par fiche (défaut: 12).
+    :param int content_count: Limite le nombre de fiches résultat (défaut: 8).
+    :param int tag_count: Limite le nombre de tag dans le résultat (défaut: 30).
+    :rtype: string
+    :returns: Un objet json sérialisé comprenant les résultats de la recherche pour les différentes facettes.
+
+
+    Clefs de l'objet:
+        - :count: Nombre total de fiches.
+        - :disciplines: Liste de disciplines artistiques en relation avec les reesultats, triée par score.
+        - :countries: Objet dont les clef sont des uri dbpedia de pays et les valeurs sont le nombre de fiches.
+        - :tags: Liste de tag triés par score.
+        - :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.
+        - :contents: Liste de fiches HDA répondant à la recherche, classée par score. Chaque fiche comporte une liste de tag.
+        - :tagtranslations: Objet donnant les traductions de label de tag rencontrés dans les résultats.
+
+    exemple::
+
+        {
+            "count": 936,
+            "disciplines": [
+                {
+                "translated_label": "Peinture",
+                "score": 936,
+                "label": "Peinture"
+                },
+                {
+                "translated_label": "Sculpture",
+                "score": 88,
+                "label": "Sculpture"
+                },
+                ...
+            ],
+            "countries": {
+                "http://fr.dbpedia.org/resource/Iran": 1,
+                "http://fr.dbpedia.org/resource/Espagne": 16,
+                ...
+            },
+            "tags": [
+                {
+                "url": "http://fr.dbpedia.org/resource/Portrait",
+                "id": 63452,
+                "translated_label": "Portrait",
+                "score": 179,
+                "wkpd_url": "http://fr.wikipedia.org/wiki/Portrait",
+                "label": "Portrait",
+                "thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Fayum02.jpg?width=300"
+                },
+                ...
+            ],
+            "sparkline": [
+                {
+                "score": 2,
+                "year": -600
+                },
+                {
+                "score": 4,
+                "year": -500
+                },
+                ...
+                {
+                "score": 18,
+                "year": 2001
+                }
+            ],
+            "contents": [
+                {
+                "description": "Le palais Fesch, ...",
+                "title": "Histoires bibliques",
+                "url": "http://www.musee-fesch.com/index.php/musee_fesch/content/view/ef_catalogue_sommaire/1513/%28node_id_theme%29/33459",
+                "tags": [
+                    {
+                    "url": "http://fr.dbpedia.org/resource/Peinture",
+                    "id": 54648,
+                    "translated_label": "Peinture",
+                    "wkpd_url": "http://fr.wikipedia.org/wiki/Peinture",
+                    "label": "Peinture",
+                    "order": 1,
+                    "match": true
+                    },
+                    ...
+                ],
+                "score": 23,
+                "coords": {
+                    "city_name": "Ajaccio",
+                    "latitude": 41.916667,
+                    "longitude": 8.733333
+                },
+                "hda_id": "4448",
+                "id": 13855
+                },
+                {
+                "description": "...",
+                "title": "Le XIXe siècle",
+                "url": "http://www.grandpalais.fr/fr/article/le-xixe-siecle",
+                "tags": [ ... ],
+                "score": 22,
+                "hda_id": "5217",
+                "id": 13582
+                },
+                ...
+            ],
+            "tagtranslations": {
+                "Paul Cézanne": "Paul Cézanne",
+                "Politique": "Politique",
+                "Poésie": "Poésie",
+                "Religion": "Religion",
+                "Empereur": "Empereur",
+                "Saint": "Saint",
+                ...
+            }
+        }
+
+    """
 
     no_translate_langs = [ 'fr' ]
 
@@ -474,6 +747,66 @@
 
 
 def subtree(tree):
+    """
+    Methode récursive permettant de remplir un arbre ce catégories avec les fiches HDA correspondantes.
+
+    :param tree: L'arbre de catégorie
+
+    :returns:Un arbre de catégorie rempli de fiches HDA.
+
+    format du paramêtre `tree` ::
+
+        {
+            "label": "secteur urbain",
+            "contents": [
+                { "label": "banlieue",
+                    "contents": [
+                        { "label": "faubourg" }
+                    ] },
+                { "label": "îlot" },
+                ...
+            ]
+        }
+
+    Exemple de retour ::
+
+
+        {
+            "label": "secteur urbain",
+            "contents": [
+                {
+                    "score": 6,
+                    "organization": "Institut national de l'audiovisuel ( INA )",
+                    "description": "Pour faire face à la ...",
+                    "title": "La construction des grands ensembles de banlieue : l'exemple de Sarcelles",
+                    "url": "http://fresques.ina.fr/jalons/fiche-media/InaEdu01075/la-construction-des-grands-ensembles-de-banlieue--l-exemple-de-sarcelles",
+                    "hda_id": "2090",
+                    "organization_url": "http://www.ina.fr",
+                    "id": 12360
+                },
+                {
+                    "score": 6,
+                    "organization": "Maison de banlieue et d'architecture",
+                    "description": "La Maison de banlieue et d'architecture...",
+                    "title": "Des ensembles assez grands. Mémoire et projets en Essonne",
+                    "url": "http://maisondebanlieue.fr/wp-content/uploads/2011/05/Cahier11_grands_ensembles.pdf",
+                    "hda_id": "5893",
+                    "organization_url": "http://www.maisondebanlieue.fr/",
+                    "id": 14821
+                },
+                ...
+            ]
+            "themes": [
+                {
+                    "label": "faubourg",
+                    "content":  [...],
+                    "themes": [...]
+                },
+                ...
+            ]
+        }
+
+    """
     MAX_TAG_ORDER = 16
     label = tree['label']
     sub = tree.get('contents',[])
@@ -497,6 +830,31 @@
     return res
 
 def filltree(request):
+    """
+    Vue permettant d'ajouter des fiches à un arbre de catégories.
+    Cette méthode est en fait un simple wrapper pour la méthode :meth:`subtree`.
+
+    Paramêtres GET:
+        :var tree: Serialisation json d'un arbre de catégories à remplir. exemple:
+
+        ::
+
+            {
+                "label": "secteur urbain",
+                "contents": [
+                    { "label": "banlieue",
+                      "contents": [
+                          { "label": "faubourg" }
+                      ] },
+                    { "label": "îlot" },
+                    ...
+                ]
+            }
+
+    Réponse (application/json):
+        L'arbre de catégories remplis de fiches HDA (c.f. retour methode :meth:`subtree`)
+
+    """
 
     tree = request.GET.get('tree','{}')
 
--- a/src/hdalab/views/pages.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/views/pages.py	Wed Apr 11 12:19:47 2018 +0200
@@ -13,6 +13,10 @@
 
 
 def datasheet(request, hda_id=None):
+    """
+    Methode Vue affichant le détail d'une fiche HDA.
+    Cette vue affiche en fait un résumé de la notice mise en relation avec les notices liées, via les mots clefs.
+    """
     MAX_TAG = 15
     MAX_RELATED = 50
 
@@ -70,6 +74,10 @@
 
 
 class HdalabAboutPage(TemplateView):
+    """
+    Classe de vue en charge de l'affichage de la page à propos.
+    C'est une simple django.views.generic.TemplateView qui ajoute quelques informations dans le contexte de rendu du template.
+    """
 
     template_name = "a_propos.html"
 
--- a/src/hdalab/views/profile.py	Thu Apr 12 01:27:16 2018 +0200
+++ b/src/hdalab/views/profile.py	Wed Apr 11 12:19:47 2018 +0200
@@ -5,24 +5,23 @@
 @author: tc
 '''
 
-from datetime import datetime
 import json
 import logging
-from renkanmanager.views import RenkanGetPut
 import uuid
+from datetime import datetime
 
 from django.conf import settings
-from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login
+from django.contrib.auth import login as auth_login
+from django.contrib.auth import REDIRECT_FIELD_NAME
 from django.contrib.auth.forms import AuthenticationForm
 from django.contrib.sites.models import get_current_site
-from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
+from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
 from django.core.urlresolvers import reverse
 from django.db.models import Q
-from django.http import HttpResponse, HttpResponseBadRequest
-from django.http import HttpResponseRedirect
+from django.http import (HttpResponse, HttpResponseBadRequest,
+                         HttpResponseRedirect)
 from django.http.response import Http404
-from django.shortcuts import get_object_or_404, redirect
-from django.shortcuts import resolve_url
+from django.shortcuts import get_object_or_404, redirect, resolve_url
 from django.template.response import TemplateResponse
 from django.templatetags.static import static
 from django.utils.http import is_safe_url
@@ -32,22 +31,61 @@
 from django.views.decorators.debug import sensitive_post_parameters
 from django.views.generic import TemplateView, View
 from django.views.generic.edit import UpdateView
-from renkanmanager.models import Renkan
-from renkanmanager.utils import LineNodePlacer, HorLineNodePlacer, renkan_copier, renkan_deleter, \
-    CircleNodePlacer
-
-from hdabo.models import Tag, Datasheet, TaggedSheet, Folder
-from hdalab.forms import HdalabRenkanStateForm, HdalabRenkanFavoriteForm
+from hdabo.models import Datasheet, Folder, Tag, TaggedSheet
+from hdalab.forms import HdalabRenkanFavoriteForm, HdalabRenkanStateForm
 from hdalab.models.dataviz import DbpediaFieldsTranslation
 from hdalab.models.renkan import HdalabRenkan
 from hdalab.services import change_renkan_state
 from hdalab.views.ajax import filter_generic
-
+from renkanmanager.models import Renkan
+from renkanmanager.utils import (CircleNodePlacer, HorLineNodePlacer,
+                                 LineNodePlacer, renkan_copier, renkan_deleter)
+from renkanmanager.views import RenkanGetPut
 
 logger = logging.getLogger(__name__)
 
 
 class BaseRenkanList(TemplateView):
+    """
+    Classe de vue permettant la gestion de l'affichage d'une liste de Renkan.
+    Cette classe fourni une méthode gérant les filtres, le tri et la pagination.
+    Cette classe de vue n'est pas directement utilisée mais est dérivé par des classe de vue concrêtes.
+
+    Liste des paramêtres GET:
+
+    +-----------+------------------------------------------------------------+--------+--------+
+    | nom       | description                                                | type   | défaut |
+    +===========+============================================================+========+========+
+    | title     | Le titre du renkan contient la chaine de caractères.       | chaine | vide   |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | username  | Le nom de l'utilisateur ayant créé le renkan.              | chaine | vide   |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | state     | Le status du renkan est (c.f. _models/renkan/HdalabRenkan) | entier | (*)    |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | startdate | La date de modification du renkan est supérieure à.        | epoch  | vide   |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | enddate   | La date de modification du renkan est inférieure à.        | epoch  | vide   |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | favorite  | Le renkan est marqué comme favori ou non (0 ou 1)          | 0/1    | (*)    |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | sort      | Champ sur lequel se fait le tri:                           | chaine | date   |
+    |           | - date : date de modification du renkan                    | /énum. |        |
+    |           | - title : titre du renkan                                  |        |        |
+    |           | - state : status du renkan (c.f _)                         |        |        |
+    |           | - user : créateur du renkan                                |        |        |
+    |           | - favorite : renkan marqué comme avori                     |        |        |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | order     | ordre de tri :                                             | chaine | desc   |
+    |           | - desc : tri descendant                                    | /énum. |        |
+    |           | - asc : tris ascendant                                     |        |        |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | page      | Le numéro de page pour la pagination                       | entier | 1      |
+    |           | La première page est la page 1.                            |        |        |
+    +-----------+------------------------------------------------------------+--------+--------+
+
+    (*) : La valeur par défaut de ce paramètre dépend de la vue concrète.
+
+    """
 
     default_sort_field = "date"
     default_sort_order = "desc"
@@ -115,6 +153,11 @@
 
 
 class ProfileHome(BaseRenkanList):
+    """
+    Page de profile d'un utilisateur.
+
+    Cette vue étend la vue de base :class:`.BaseRenkanList`.
+    """
 
     template_name = "profile_home.html"
 
@@ -123,6 +166,14 @@
 
 
 class RenkanPublicList(BaseRenkanList):
+    """
+    Page des renkan publics.
+
+    La colonne de l'auteur du renkan n'est affiché que si l'utilisateur est membre de l'équipe.
+    Cette list ne comprend pas les renkan marqués commme favoris. Le paramêtre "favorite" est ignoré.
+
+    Cette vue étend la vue de base :class:`.BaseRenkanList`.
+    """
 
     template_name = "renkan_list.html"
 
@@ -142,6 +193,13 @@
 
 
 class RenkanFavoriteList(BaseRenkanList):
+    """
+    Page des renkan favoris. Affiche uniquement les renkan marqués comme favoris. Cela implique que le paramêtre "favorite" est ignoré par cette vue.
+
+    La colonne de l'auteur du renkan n'est affiché que si l'utilisateur est membre de l'équipe.
+
+    Cette vue étend la vue de base :class:`.BaseRenkanList`.
+    """
 
     template_name = "renkan_list_favorite.html"
 
@@ -160,6 +218,10 @@
 
 
 class RenkanNew(TemplateView):
+    """
+    Page permettant la création de nouveau Renkan vide.
+    Une fois le renkan est créé (POST), l'utilisateur est redirigé vers la page d'édition de Renkan
+    """
 
     template_name="renkan_new_confirm.html"
 
@@ -180,6 +242,23 @@
 
 
 class RenkanEdit(TemplateView):
+    """
+    Page permettant l'édition de Renkan.
+    Le principal rôle de cette page est d'afficher l'éditeur de Renkan.
+
+    Paramêtres GET pris en compte par cette page:
+
+    +-----------+------------------------------------------------------------+--------+--------+
+    | nom       | description                                                | type   | défaut |
+    +===========+============================================================+========+========+
+    | rk_id     | Identifiant d'un renan à éditer.                           | chaine | vide   |
+    +-----------+------------------------------------------------------------+--------+--------+
+    | shape     | Forme du renkan généré                                     | chaine | circle |
+    |           | Ce paramêmtre n'a pas d'effet si le renkan existe déjà     |        |        |
+    |           | (utilisation de rk_id) ou bien si il a été sauvegardé.     |        |        |
+    +-----------+------------------------------------------------------------+--------+--------+
+
+    """
 
     template_name="renkan_edit.html"
 
@@ -219,12 +298,59 @@
 
 
 class HdalabRenkanGetPut(RenkanGetPut):
+    """
+    Vue permettant la gestion de la création, de l'édition et de la sauvegarde d'un renkan.
+    """
 
     @csrf_exempt
     def dispatch(self, *args, **kwargs):
         return super(HdalabRenkanGetPut, self).dispatch(*args, **kwargs)
 
     def get(self, request):
+        """
+        Méthode qui fournit un renkan au client d'édition. Son origine est fonction des paramêtres fournit.
+
+        Si le paramêtre `rk_id` est fourni, la source du renkan est le contenu d'un objet existant.
+        Sinon, le renkan est créé à partir des paramêtres fournis.
+
+        Liste des paramêtres de requête:
+
+        +-------------+------------------------------------------------------------+--------+--------+
+        | nom         | description                                                | type   | défaut |
+        +=============+============================================================+========+========+
+        | rk_id       | Identifiant d'un renan à éditer.                           | chaine | vide   |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | shape       | Forme du renkan généré (circle, vert, hor)                 | chaine | circle |
+        |             | Ce paramêmtre n'a pas d'effet si le renkan existe déjà     |        |        |
+        |             | (utilisation de rk_id) ou bien si il a été sauvegardé.     |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | lang        | La langue de l'utilisateur. par défaut c'est la langue de  | chaine | vide   |
+        |             | la requête.                                                |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | notice      | Un identifiant de notice HDA. Si ce paramêtre est fourni,  | chaine | vide   |
+        |             | le renkan est généré à partir des tags et notices liées.   |        |        |
+        |             | Le centre du renkan est la notice fournie.                 |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | folder      | Identifiant d'un dossier de ressource HDA. Si ce paramêtre | chaine | vide   |
+        |             | est fourni, le renkan est généré à partir des notices      |        |        |
+        |             | contenues dans le dossier, ainsi que les tags liés.        |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | label (*)   | Une liste de labels de mots clef, séparés par `,`          | chaine | vide   |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | country (*) | Une liste d'identifiants de pays, séparés par `,`. Un      | chaine | vide   |
+        |             | identifiant de pays est sont URI DBPedia.                  |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+        | period (*)  | Période de recherche.                                      | chaine | vide   |
+        |             | Le format est `<année-début>,<année-fin>`.                 |        |        |
+        +-------------+------------------------------------------------------------+--------+--------+
+
+
+        (*) Si les paramêtres `label`, `country`, 'period` sont fournis, ils sont utilisés pour former un filtre sur les fiches HDA en appelant la méthode :func:`hdalab.views.ajax.filter_generic`.
+        Le résultat de cet appel est ensuite utilisé avec le paramêtre `shape` pour retourner un nouveau renkan.
+
+        Attention, il faut noter que les nouveau projets renkan créés par cette méthode ne sont pas sauvagardé en base et que donc elle n'a pas d'effet de bord.
+
+        """
 
         # If a renkan id is set
         rk_id = request.GET.get("rk_id", "")
@@ -634,6 +760,24 @@
 
 
     def post(self, request):
+        """
+        Sauvegarde d'un renkan.
+        La sauvegarde n'est possible que dans les condition suivantes:
+        - si il s'agit d'une création de renkan (pas de paramêtre `rk_id`), il faut être identifié
+        - si un renkan est modifié, il faut être identifié et en être le propriétaire.
+
+        Paramêtres de requête:
+
+        +-----------+------------------------------------------------------------+--------+--------+
+        | nom       | description                                                | type   | défaut |
+        +===========+============================================================+========+========+
+        | rk_id     | Identifiant du renkan à sauvegarder                        | chaine | vide   |
+        +-----------+------------------------------------------------------------+--------+--------+
+
+        Le contenu du renkan à sauvegarder est dans le corps de la requête.
+        Le contenu d'un renkan est décrit sommairement dans la documentation renkan.
+        À part pour les champs "id" et "title" qui sont utilisés pour la gestion de l'affichage, le contenu d'un renkan n'est pas modifié par cette meethode et est directement sauvegardé.
+        """
 
         rk_id = request.GET.get("rk_id", "")
         #data = json.loads(request.body)
@@ -676,8 +820,17 @@
 
 
 class HdalabRenkanCopy(View):
+    """
+    Vue permettant de copier un renkan.
+    """
 
     def post(self, request, rk_id):
+        """
+        Copie un renkan.
+        L'id du renkan à copier est un paramêtre d'URL.
+        Le nouveau titre est "ancien titre (copy)".
+        """
+
         rk = renkan_copier(request.user, rk_id)
         hr = HdalabRenkan()
         hr.renkan = rk
@@ -689,8 +842,15 @@
 
 
 class HdalabRenkanDelete(View):
+    """
+    Vue permettant d'effacer un Renkan.
+    """
 
     def post(self, request, rk_id):
+        """
+        Efface un renkan.
+        L'id du renkan à copier est un paramêtre d'URL.
+        """
         try:
             hr = HdalabRenkan.objects.get(renkan__rk_id=rk_id)
         except:
@@ -703,8 +863,35 @@
 
 
 class HdalabRenkanModerate(View):
+    """
+    Vue pour modérer un renkan.
+    """
 
     def post(self, request, rk_id):
+        """
+        Modère un Renkan, i.e. modifie son état.
+
+        :param:rk_id: L'identifiant de renkan, passé comme paramêtre d'URL.
+
+        Paramêtres POST:
+
+        +-----------+------------------------------------------------------------+--------+--------+-------------+
+        | nom       | description                                                | type   | défaut | obligatoire |
+        +===========+============================================================+========+========+=============+
+        | id        | Identifiant de renkan (n'est pas pris en compte)           | chaine |        | oui         |
+        +-----------+------------------------------------------------------------+--------+--------+-------------+
+        | state     | Le prochain état.                                          | entier |        | oui         |
+        |           | c.f.                                                       |        |        |             |
+        |           | :class:`hdalab.models.renkan.HdalabRenkanStateTransition`  |        |        |             |
+        +-----------+------------------------------------------------------------+--------+--------+-------------+
+        | message   | Message optionel de modération.                            | chaine | vide   | non         |
+        +-----------+------------------------------------------------------------+--------+--------+-------------+
+        | next (*)  | Url de redirection.                                        | chaine | vide   | non         |
+        +-----------+------------------------------------------------------------+--------+--------+-------------+
+
+        (*) Si non précisée, redirige vers l'url intitulée `profile_home` (/hdalab/profile/).
+
+        """
         form = HdalabRenkanStateForm(request.POST)
         if form.is_valid():
             logger.debug("FORM DATA %r", form.cleaned_data)
@@ -719,9 +906,28 @@
             logger.debug("FORM INVALID %r : %r", request.POST, form.errors)
             return HttpResponseBadRequest("State form invalid")
 
+
+
 class HdalabRenkanFavorite(View):
+    """
+    Vue pour marquer un renkan comme favori.
+    """
 
     def post(self, request, rk_id):
+        """
+        Marque un renkan comme favoris.
+
+        :param:rk_id: L'identifiant de renkan, passé comme paramêtre d'URL.
+
+        Paramêtres POST:
+
+        +-----------+------------------------------------------------------------+---------+--------+-------------+
+        | nom       | description                                                | type    | défaut | obligatoire |
+        +===========+============================================================+=========+========+=============+
+        | favorite  | Indique si le renkan est marqué comme favoris ou pas       | booléen |        | oui         |
+        +-----------+------------------------------------------------------------+---------+--------+-------------+
+
+        """
         form = HdalabRenkanFavoriteForm(request.POST)
         if form.is_valid():
             renkan_hda =  get_object_or_404(HdalabRenkan.objects.select_related(), renkan__rk_id=rk_id)
@@ -734,6 +940,11 @@
 
 
 class UserProfileUpdate(UpdateView):
+    """
+    Simple classe de vue permettant la gestion des pages de mise à jour des informations de profile de l'utilisateur.
+    utilise en particulier le template `hdalab/templates/hdabo/user_update_form.html` comme formulaire de saisie.
+    Elle étend la vue `django.views.generic.edit.UpdateView <https://docs.djangoproject.com/en/1.8/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView>`_ .
+    """
     fields = ['email']
     template_name_suffix = '_update_form'
 
@@ -753,7 +964,8 @@
           authentication_form=AuthenticationForm,
           current_app=None, extra_context=None):
     """
-    Displays the login form and handles the login action.
+    Affiche le formulaire de connection et gère l'action de connexion.
+    Cette fonction a été copiée de :func:`django.contrib.auth.views.login` pour faciliter la connexion `ajax`.
     """
     redirect_to = request.REQUEST.get(redirect_field_name, '')
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/virtualenv/web/res/doc_requirements.txt	Wed Apr 11 12:19:47 2018 +0200
@@ -0,0 +1,2 @@
+sphinx
+sphinx-autobuild