Moved code to add annotation to ldt_utils + added tests
authorverrierj
Mon, 10 Oct 2011 11:54:34 +0200
changeset 196 b939a58d13b0
parent 195 6580f5804006
child 197 6dfdc12e338a
Moved code to add annotation to ldt_utils + added tests
src/ldt/ldt/api/ldt/handlers.py
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/search_results.html
src/ldt/ldt/ldt_utils/tests.py
src/ldt/ldt/ldt_utils/utils.py
src/ldt/ldt/locale/en/LC_MESSAGES/django.mo
src/ldt/ldt/locale/en/LC_MESSAGES/django.po
src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo
src/ldt/ldt/locale/fr/LC_MESSAGES/django.po
web/ldtplatform/config.py.tmpl
--- a/src/ldt/ldt/api/ldt/handlers.py	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/api/ldt/handlers.py	Mon Oct 10 11:54:34 2011 +0200
@@ -1,8 +1,10 @@
 from ldt.ldt_utils.models import Project
 from piston.handler import BaseHandler
 from piston.utils import rc, require_extended
+from ldt.ldt_utils.utils import LdtAnnotation
 import logging #@UnresolvedImport
 
+
 class ProjectHandler(BaseHandler):
     allowed_methods = ('GET', 'PUT',)
     model = Project   
@@ -16,21 +18,98 @@
     @require_extended
     def update(self, request, project_id):
         """
-        update a project.
-        """
-        logging.debug("request " + repr(request))
-        data = request.data
-        ldt_str = data["ldt"] 
+        This method is called when a PUT request is sent to http://<plateform_location>/api/ldt/projects/<project_id>.format. The
+        request should contain a content-type header whose value can be either "application/json" or "text/xml" and a valid utf-8
+        encoded JSON/Cinelab or LDT/XML file.
+            <project_id> is the ldt_id field of the project. If <projet_id> does not match any project on the platform, a 410 ("Gone")
+            error will be returned.
+            <format> can be 'json', 'yaml', 'xml', 'pickle'
+        
+        If the submitted file is not valid or if the file refers to a media that is not contained in the project, a 500  ("Bad Request")
+        error will be returned. If the "type" field of an annotation matches an already existing cutting, it will be added to that 
+        cutting. Otherwise, a new cutting will be added (as well as a new ensemble if needed). Several annotations can be added at 
+        the same time if the submitted file contains multiple annotations. In addition to annotations, the submitted file should contain a 
+        meta section with two fields :"date" and "creator". The server returns a 201 ("Created") code if annotations have been added.   
+        
+        Example :
         
-        logging.debug("request data" + repr(ldt_str))
+        A platform is reachable at http://localhost/. It contains a project with ID a0593b58-f258-11df-80e1-00145ea4a2be. This project has
+        a content milosforman_amadeus, which has a cutting Salieri. The following JSON file exists in the current directory :
+    
+        {
+            "annotations": [
+                {
+                    "type": "New cutting name",
+                    "media": "milosforman_amadeus",
+                    "begin": 50000,
+                    "end": 900000,
+                    "content": {
+                        "data": "new annotation"
+                    },
+                    "tags": [ "json" ]
+                },
+                {
+                    "type": "Salieri",
+                    "media": "milosforman_amadeus",
+                    "begin": 700000,
+                    "end": 1200000,
+                    "content": {
+                        "data": "Annotation about Salieri"
+                    },
+                    "tags": [ "xml", "test", "blop" ]
+                }
+            ],
+            
+            "meta": {
+                "creator": "John Doe",
+                "created": "2011-09-10T09:12:58"
+            }
+        }
+            
+        If we send a PUT request with curl :    
+        $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H  "content-type:application/json"
+        A new cutting titled "New cutting name" will be created with one annotation inside, and the annotation "Annotation about Salieri"
+        will be added to the Salieri cutting.
+          
+        """    
         
-        if not ldt_str:
+        try:
+            project = Project.objects.get(ldt_id=project_id)
+        except Project.DoesNotExist:
+            return rc.NOT_HERE   
+        
+        if request.content_type == 'application/json':
+            
+            logging.debug("request json " + repr(request))       
+            adder = LdtAnnotation(project)           
+
+            meta = request.data['meta']
+            author = meta['creator']
+            date = meta['created']
+            new_annotations = request.data['annotations']
+
+            for a in new_annotations:
+                dur = str(a['end'] - a['begin'])
+                begin = str(a['begin'])
+                if not adder.add(a['media'], a['type'], a['content']['data'], '', a['tags'], begin, dur, author, date):
+                    return rc.BAD_REQUEST
+
+            return rc.ALL_OK            
+            
+        elif request.content_type == "text/xml":        
+            logging.debug("request xml" + repr(request))
+            data = request.data
+            ldt_str = data["ldt"] 
+            
+            logging.debug("request data" + repr(ldt_str))
+            
+            if not ldt_str:  
+                return rc.ALL_OK
+                        
+            project.ldt = ldt_str
+            
+            project.save()
+        
             return rc.ALL_OK
         
-        project = Project.objects.get(ldt_id=project_id)
-        
-        project.ldt = ldt_str
-        
-        project.save()
-        
-        return rc.ALL_OK
+        return rc.NOT_IMPLEMENTED
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/search_results.html	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/search_results.html	Mon Oct 10 11:54:34 2011 +0200
@@ -78,12 +78,13 @@
 					{{ segment.title }}
 				{% else %}
 					{% trans "No title" %}
-				{% endif %}
+				{% endif %}</a></span>
 				
-				</a></span><br />
-				{{ segment.context }}<br />
+				{% if segment.context %}
+				<br />{{ segment.context }}
+				{% endif %}
 				{% if segment.tags %}
-				<b>{% trans "Tags"%}</b> : {{ segment.tags }}
+				<br /><b>{% trans "Tags"%}</b> : {{ segment.tags }}
 				{% endif %}
 				</li>
 			{% endfor %}
--- a/src/ldt/ldt/ldt_utils/tests.py	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/tests.py	Mon Oct 10 11:54:34 2011 +0200
@@ -7,16 +7,14 @@
 
 from django.conf import settings
 from django.test import TestCase
-from ldt.core.models import Owner
+from ldt.ldt_utils.models import User
 from models import Project, Content
-from utils import LdtUtils, create_ldt, create_empty_iri, copy_ldt
+from utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
 import lxml.etree
 import tempfile
 import unittest
 import uuid
 
-
-
 class SimpleTest(TestCase):
     def test_basic_addition(self):
         """
@@ -31,11 +29,9 @@
 True
 """}
 
-
-
 class UtilsTest(unittest.TestCase):
     def setUp(self):
-        self.user = Owner()
+        self.user = User()
         self.user.username = "toto"
         self.LU = LdtUtils()
     
@@ -43,6 +39,7 @@
         self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
         self.project.id = "11"
         self.project.ldt_id = str(uuid.uuid1())
+        self.project.description = "proj1description"
         self.project.save()
         
         self.projectcopy = Project(title="the2ndproject")
@@ -70,8 +67,8 @@
         doc.write(f, pretty_print=True)
         f.seek(0)
         ldoc = lxml.etree.parse(f)
-        self.assertEqual(ldoc.xpath("/iri/displays/display/content")[9].get("id"), self.cont2.iri_id)
-        self.assertEqual(ldoc.xpath("/iri/medias/media")[8].get("id"), self.cont1.iri_id)
+        self.assertEqual(ldoc.xpath("/iri/displays/display/content")[11].get("id"), self.cont2.iri_id)
+        self.assertEqual(ldoc.xpath("/iri/medias/media")[10].get("id"), self.cont1.iri_id)
         f.close()
 
     def test_generate_init(self):
@@ -143,8 +140,34 @@
         self.assertEqual(ldoc.xpath("/iri/head/meta")[0].get("content"), self.cont9.iri_id)
         self.assertEqual(ldoc.xpath("/iri/body/medias/media/video")[0].get("id"), self.cont9.iri_id)
         tmp.close()
-    
+        
+    def test_add_annotation(self):
+        
+        self.cont11 = Content(iriurl="id11/iriurl1")
+        self.cont11.iri_id = "id11"
+        self.cont11.save()
+        
+        self.cont12 = Content(iriurl="id12/iriurl2")
+        self.cont12.iri_id = "id12"
+        self.cont12.save()
+        
+        self.project.contents.add(self.cont11, self.cont12)
+        self.project.ldt = ""
+        create_ldt(self.project, self.user)
+                
+        self.LA = LdtAnnotation(self.project)
+        
+        self.LA.add("id11", "cutting", "title", "text", ["tag1", "tag2"], "800",
+                    "10000", "jdoe", "2011-09-10T09:12:58")
+        self.LA.save()
+        ldt = lxml.etree.fromstring(self.project.ldt)
+        ann = ldt.xpath('/iri/annotations/content[@id="id11"]/ensemble/decoupage/elements/element')[0]
+        title = ann.xpath('title')[0].text
+        abstract = ann.xpath('abstract')[0].text
 
+        self.assertEqual(ann.get("author"), "jdoe")
+        self.assertEqual(title, "title")
+        self.assertEqual(abstract, "text")
 
 
 class ViewsTest(unittest.TestCase):
--- a/src/ldt/ldt/ldt_utils/utils.py	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/utils.py	Mon Oct 10 11:54:34 2011 +0200
@@ -1,6 +1,8 @@
 from copy import deepcopy
 from django.conf import settings
 from ldt.indexation import get_searcher, get_results_list
+from django.utils.translation import ugettext as _
+from StringIO import StringIO
 import datetime
 import django.core.urlresolvers
 import lxml.etree
@@ -60,7 +62,7 @@
         doc = lxml.etree.ElementTree(iri)
     
         project = lxml.etree.SubElement(iri, u'project')
-        project.set(u"id", unicode(str(uuid.uuid1())))
+        project.set(u"id", generate_uuid())
         project.set(u"title", unicode(title))
         project.set(u"user", author)
         project.set(u"abstract", u"")
@@ -141,7 +143,6 @@
         lxml.etree.SubElement(iri, "edits")
         return doc
         
-
     def generate_init(self, url, method, search=None):
                 
         iri = lxml.etree.Element('iri')
@@ -160,6 +161,84 @@
         return iri 
 
 
+class LdtAnnotation:
+    
+    def __init__(self, project):
+        self.project = project
+        self.parser = lxml.etree.XMLParser(remove_blank_text=True)
+        self.ldtdoc = lxml.etree.parse(StringIO(project.ldt.encode("utf-8")), self.parser)
+        self.to_add = True
+    
+    def add(self, media, cutting, title, text, tags_list, begin, dur, author, date, color="16776960"):
+        """
+        Add an annotation to a project. begin and dur must be strings. Default color is yellow.
+        """
+                
+        path_media = self.ldtdoc.xpath('/iri/medias/media[@id="%s"]' % media)
+
+        if len(path_media) == 0:
+            self.to_add = False
+            return False
+                
+        path_annotations = self.ldtdoc.xpath('/iri/annotations')[0]
+        path_content = path_annotations.xpath('content[@id="%s"]' % media)
+                
+        if len(path_content) == 0:
+            path_content = lxml.etree.SubElement(path_annotations, 'content')
+            path_content.set('id', media)
+            path_content = [path_content]
+                
+        path_ensemble = path_content[0].xpath('ensemble[decoupage[title="%s"]]' % cutting)
+        if len(path_ensemble) == 0:
+            path_ensemble = path_content[0].xpath('ensemble')
+                
+        if len(path_ensemble) == 0:
+            path_ensemble = lxml.etree.SubElement(path_content[0], 'ensemble')
+            path_ensemble.set('id', 'g_' + generate_uuid())
+            path_ensemble.set('title', _('Personal cutting'))
+            path_ensemble.set('author', 'undefined')
+            path_ensemble = [path_ensemble]                
+ 
+        decoupage_elements = path_ensemble[0].xpath('decoupage[title="%s"]/elements' % cutting)
+        if len(decoupage_elements) == 0:
+            decoupage = lxml.etree.SubElement(path_ensemble[0], 'decoupage')
+            decoupage.set('id', 'c_' + generate_uuid())
+            decoupage.set('author', author)
+            decoupage_title = lxml.etree.SubElement(decoupage, 'title')
+            decoupage_title.text = cutting
+            lxml.etree.SubElement(decoupage, 'abstract')
+            decoupage_elements = lxml.etree.SubElement(decoupage, 'elements')
+            decoupage_elements = [decoupage_elements]             
+                
+        element = lxml.etree.SubElement(decoupage_elements[0], 'element')
+        element.set('id', 's_' + generate_uuid())
+        element.set('begin', begin)
+        element.set('dur', dur)
+        element.set('author', author)
+        element.set('date', date)
+        element.set('color', color)
+        abstract = lxml.etree.SubElement(element, 'abstract')
+        abstract.text = text 
+        title_node = lxml.etree.SubElement(element, 'title')
+        title_node.text = title
+        audio = lxml.etree.SubElement(element, 'audio')
+        audio.set('source', '')
+        tags = lxml.etree.SubElement(element, 'tags')
+                                
+        for tag in tags_list:
+            tag_node = lxml.etree.SubElement(tags, 'tag')
+            tag_node.text = tag
+            
+        return True
+    
+    def save(self):
+        if self.to_add:
+            self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True)
+            self.project.save()
+    
+    def __del__(self):
+        self.save()       
+            
 
 def create_ldt(project, user):
     """create xml"""
@@ -364,3 +443,4 @@
         doc.write(f, encoding="UTF-8", pretty_print=True, xml_declaration=True)
     finally:
         f.close()
+        
Binary file src/ldt/ldt/locale/en/LC_MESSAGES/django.mo has changed
--- a/src/ldt/ldt/locale/en/LC_MESSAGES/django.po	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/locale/en/LC_MESSAGES/django.po	Mon Oct 10 11:54:34 2011 +0200
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-09-30 15:55+0200\n"
+"POT-Creation-Date: 2011-10-07 12:22+0200\n"
 "PO-Revision-Date: 2010-02-17 03:53+0100\n"
 "Last-Translator: Yves-Marie Haussonne <ymh.work@gmail.com>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -175,65 +175,69 @@
 msgid "changed by"
 msgstr "changed by"
 
-#: .\ldt_utils\views.py:151 .\ldt_utils\views.py:609 .\ldt_utils\views.py:655
+#: .\ldt_utils\utils.py:195
+msgid "Personal cutting"
+msgstr "Personal cutting"
+
+#: .\ldt_utils\views.py:151 .\ldt_utils\views.py:612 .\ldt_utils\views.py:658
 msgid "You can not access this project"
 msgstr "You can not access this project"
 
-#: .\ldt_utils\views.py:283 .\ldt_utils\views.py:301
+#: .\ldt_utils\views.py:286 .\ldt_utils\views.py:304
 msgid "Please enter valid keywords."
 msgstr "Please enter valid keywords."
 
-#: .\ldt_utils\views.py:821
+#: .\ldt_utils\views.py:824
 #, python-format
 msgid "the project %(title)s is published. please unpublish before deleting."
 msgstr "the project %(title)s is published. please unpublish before deleting."
 
-#: .\ldt_utils\views.py:822
+#: .\ldt_utils\views.py:825
 msgid "can not delete the project. Please correct the following error"
 msgstr "can not delete the project. Please correct the following error"
 
-#: .\ldt_utils\views.py:823
+#: .\ldt_utils\views.py:826
 msgid "title error deleting project"
 msgstr "Error when deleting project"
 
-#: .\ldt_utils\views.py:825
+#: .\ldt_utils\views.py:828
 #, python-format
 msgid "please confirm deleting project %(title)s"
 msgstr "Please confirm deleting project %(title)s"
 
-#: .\ldt_utils\views.py:826
+#: .\ldt_utils\views.py:829
 msgid "confirm deletion"
 msgstr "Confirm deletion"
 
-#: .\ldt_utils\views.py:1003
+#: .\ldt_utils\views.py:1006
 msgid "Problem when downloading file from url : "
 msgstr "Problem when downloading file from url: "
 
-#: .\ldt_utils\views.py:1006
+#: .\ldt_utils\views.py:1009
 msgid "Problem when uploading file : "
 msgstr "Problem when uploading file: "
 
-#: .\ldt_utils\views.py:1075
+#: .\ldt_utils\views.py:1078
 #, python-format
 msgid "There is %(count)d error when deleting content"
 msgid_plural "There are %(count)d errors when deleting content"
 msgstr[0] "There is %(count)d error when deleting content"
 msgstr[1] "There are %(count)d errors when deleting content"
 
-#: .\ldt_utils\views.py:1076
+#: .\ldt_utils\views.py:1079
 msgid "title error deleting content"
 msgstr "Error when deleting content"
 
-#: .\ldt_utils\views.py:1078
+#: .\ldt_utils\views.py:1081
 #, python-format
 msgid "Confirm delete content %(titles)s"
 msgstr "Confirm delete content %(titles)s"
 
-#: .\ldt_utils\views.py:1079
+#: .\ldt_utils\views.py:1082
 msgid "confirm delete content"
 msgstr "Confirm delete content"
 
-#: .\ldt_utils\views.py:1113
+#: .\ldt_utils\views.py:1116
 #, python-format
 msgid ""
 "Content '%(title)s' is referenced by this project : %(project_titles)s. "
@@ -290,7 +294,7 @@
 msgstr "Copy your project"
 
 #: .\ldt_utils\templates\ldt\ldt_utils\copy_ldt.html.py:16
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:79
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:80
 msgid "Title"
 msgstr "Title"
 
@@ -341,7 +345,7 @@
 msgstr "media file is being processed please wait."
 
 #: .\ldt_utils\templates\ldt\ldt_utils\create_content.html.py:124
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:114
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:115
 #: .\ldt_utils\templates\ldt\ldt_utils\error_confirm.html.py:52
 msgid "close_cancel"
 msgstr "Close"
@@ -362,39 +366,39 @@
 msgid "uncheck all"
 msgstr "uncheck all"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:75
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:76
 msgid "Update your project"
 msgstr "Create your project"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:75
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:76
 msgid "Create your project"
 msgstr "Create your project"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:81
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:82
 #, fuzzy
 msgid "Description :"
 msgstr "description"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:83
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:84
 msgid "List of contents"
 msgstr "List of contents"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:96
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:97
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\contentslist.html.py:3
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\projectslist.html.py:3
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\publishedprojectslist.html.py:3
 msgid "name"
 msgstr "name"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:116
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:117
 msgid "delete_project"
 msgstr "delete project"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:117
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:118
 msgid "update_project"
 msgstr "update project"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:119
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:120
 msgid "create_project"
 msgstr "Create new project"
 
Binary file src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo has changed
--- a/src/ldt/ldt/locale/fr/LC_MESSAGES/django.po	Wed Oct 05 11:25:51 2011 +0200
+++ b/src/ldt/ldt/locale/fr/LC_MESSAGES/django.po	Mon Oct 10 11:54:34 2011 +0200
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-09-30 15:55+0200\n"
+"POT-Creation-Date: 2011-10-07 12:22+0200\n"
 "PO-Revision-Date: 2010-03-09 15:52+0100\n"
 "Last-Translator: Yves-Marie Haussonne <ymh.work@gmail.com>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -174,66 +174,70 @@
 msgid "changed by"
 msgstr "modifié par"
 
-#: .\ldt_utils\views.py:151 .\ldt_utils\views.py:609 .\ldt_utils\views.py:655
+#: .\ldt_utils\utils.py:195
+msgid "Personal cutting"
+msgstr "Découpages personnels"
+
+#: .\ldt_utils\views.py:151 .\ldt_utils\views.py:612 .\ldt_utils\views.py:658
 msgid "You can not access this project"
 msgstr "vous n'avez pas l'autorisation d'accéder à ce projet"
 
-#: .\ldt_utils\views.py:283 .\ldt_utils\views.py:301
+#: .\ldt_utils\views.py:286 .\ldt_utils\views.py:304
 msgid "Please enter valid keywords."
 msgstr "Veuillez entrer des mots-clés valides."
 
-#: .\ldt_utils\views.py:821
+#: .\ldt_utils\views.py:824
 #, python-format
 msgid "the project %(title)s is published. please unpublish before deleting."
 msgstr "Le projet %(title)s est publié. Déplublier le avant de l'effacer."
 
-#: .\ldt_utils\views.py:822
+#: .\ldt_utils\views.py:825
 msgid "can not delete the project. Please correct the following error"
 msgstr ""
 "Le projet ne peut pas être effacé. Veuillez corriger les erreurs suivantes."
 
-#: .\ldt_utils\views.py:823
+#: .\ldt_utils\views.py:826
 msgid "title error deleting project"
 msgstr "Erreur lors de l'effacement du projet"
 
-#: .\ldt_utils\views.py:825
+#: .\ldt_utils\views.py:828
 #, python-format
 msgid "please confirm deleting project %(title)s"
 msgstr "Confirmer l'effacement du projet intitulé %(title)s"
 
-#: .\ldt_utils\views.py:826
+#: .\ldt_utils\views.py:829
 msgid "confirm deletion"
 msgstr "Confirmation d'effacement"
 
-#: .\ldt_utils\views.py:1003
+#: .\ldt_utils\views.py:1006
 msgid "Problem when downloading file from url : "
 msgstr "Problème lors du téléchargement du fichier : "
 
-#: .\ldt_utils\views.py:1006
+#: .\ldt_utils\views.py:1009
 msgid "Problem when uploading file : "
 msgstr "Problème lors de l'upload du fichier : "
 
-#: .\ldt_utils\views.py:1075
+#: .\ldt_utils\views.py:1078
 #, python-format
 msgid "There is %(count)d error when deleting content"
 msgid_plural "There are %(count)d errors when deleting content"
 msgstr[0] "Il y a %(count)d erreur lors de l'effacement du contenu"
 msgstr[1] "Il y a %(count)d erreurs lors de l'effacement du contenu"
 
-#: .\ldt_utils\views.py:1076
+#: .\ldt_utils\views.py:1079
 msgid "title error deleting content"
 msgstr "Erreur lors de l'effacement du contenu"
 
-#: .\ldt_utils\views.py:1078
+#: .\ldt_utils\views.py:1081
 #, python-format
 msgid "Confirm delete content %(titles)s"
 msgstr "Veuillez confirmer l'effacement du contenu %(titles)s"
 
-#: .\ldt_utils\views.py:1079
+#: .\ldt_utils\views.py:1082
 msgid "confirm delete content"
 msgstr "Confirmation effacement contenu"
 
-#: .\ldt_utils\views.py:1113
+#: .\ldt_utils\views.py:1116
 #, python-format
 msgid ""
 "Content '%(title)s' is referenced by this project : %(project_titles)s. "
@@ -290,7 +294,7 @@
 msgstr "Copier votre projet"
 
 #: .\ldt_utils\templates\ldt\ldt_utils\copy_ldt.html.py:16
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:79
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:80
 msgid "Title"
 msgstr "Titre"
 
@@ -340,7 +344,7 @@
 msgstr "Le fichier média est en cours de traitement. Veuillez patienter."
 
 #: .\ldt_utils\templates\ldt\ldt_utils\create_content.html.py:124
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:114
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:115
 #: .\ldt_utils\templates\ldt\ldt_utils\error_confirm.html.py:52
 msgid "close_cancel"
 msgstr "Fermer"
@@ -361,39 +365,39 @@
 msgid "uncheck all"
 msgstr "Tout décocher"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:75
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:76
 msgid "Update your project"
 msgstr "Mettre à jour votre projet Lignes de Temps"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:75
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:76
 msgid "Create your project"
 msgstr "Créer votre projet Lignes de Temps"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:81
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:82
 #, fuzzy
 msgid "Description :"
 msgstr "description"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:83
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:84
 msgid "List of contents"
 msgstr "Liste de contenus"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:96
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:97
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\contentslist.html.py:3
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\projectslist.html.py:3
 #: .\ldt_utils\templates\ldt\ldt_utils\partial\publishedprojectslist.html.py:3
 msgid "name"
 msgstr "Nom"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:116
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:117
 msgid "delete_project"
 msgstr "Effacer"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:117
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:118
 msgid "update_project"
 msgstr "Mettre à jour"
 
-#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:119
+#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:120
 msgid "create_project"
 msgstr "Créer un nouveau projet Ligne de Temps"
 
--- a/web/ldtplatform/config.py.tmpl	Wed Oct 05 11:25:51 2011 +0200
+++ b/web/ldtplatform/config.py.tmpl	Mon Oct 10 11:54:34 2011 +0200
@@ -54,6 +54,7 @@
 
 LOG_FILE = os.path.abspath(os.path.join(BASE_DIR,"../log/log.txt"))
 LOG_LEVEL = logging.DEBUG
+logging.basicConfig(filename=LOG_FILE, level=LOG_LEVEL)
 
 INDEX_PATH = os.path.abspath(BASE_DIR + "../index/")