first commit with new rest api urls and resources. new_rest_api
authorcavaliet
Mon, 22 Oct 2012 18:22:39 +0200
branchnew_rest_api
changeset 871 f52567ae138c
parent 870 834ceff06966
child 872 cd56949a3510
first commit with new rest api urls and resources.
src/ldt/ldt/api/ldt/handlers.py
src/ldt/ldt/api/ldt/resources/__init__.py
src/ldt/ldt/api/ldt/resources/annotation.py
src/ldt/ldt/api/ldt/resources/content.py
src/ldt/ldt/api/ldt/resources/project.py
src/ldt/ldt/api/ldt/resources/segment.py
src/ldt/ldt/api/ldt/urls.py
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html
virtualenv/res/src/PyYAML-3.10.tar.gz
virtualenv/res/src/django-tastypie-0.9.11.tar.gz
virtualenv/res/src/mimeparse-0.1.3.tar.gz
virtualenv/res/src/python-dateutil-2.1.tar.gz
virtualenv/res/src/python-digest-1.7.tar.gz
--- a/src/ldt/ldt/api/ldt/handlers.py	Mon Oct 22 18:19:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-from ldt.ldt_utils.models import Project, Content, Segment
-from django.db.models import F, Q
-from piston.handler import BaseHandler
-from piston.utils import rc, require_extended
-from ldt.ldt_utils.utils import LdtAnnotation
-from ldt.ldt_utils.stat import add_annotation_to_stat
-from ldt.security import protect_models, unprotect_models
-from ldt.ldt_utils.segmentserializer import SegmentSerializer
-import logging #@UnresolvedImport
-
-
-class ProjectHandler(BaseHandler):
-    allowed_methods = ('GET', 'PUT',)
-    model = Project   
-
-    def read(self, request, project_id):
-        """
-        returns a single project
-        """
-        return Project.objects.get(ldt_id=project_id)
-    
-    @require_extended
-    def update(self, request, project_id):
-        #return rc.ALL_OK
-        logging.debug("request " + repr(request))
-        data = request.data
-        ldt_str = data["ldt"]
-        
-        logging.debug("request data" + repr(ldt_str))
-        
-        if not ldt_str:
-            return rc.BAD_REQUEST
-        
-        project = Project.objects.get(ldt_id=project_id)
-        
-        project.ldt = ldt_str
-        
-        unprotect_models()
-        project.save()
-        protect_models()
-    
-        return rc.ALL_OK
-
-
-class AnnotationHandler(BaseHandler):
-    allowed_methods = ('PUT',)
-    
-    @require_extended
-    def update(self, request, project_id):
-        """
-        This method is called when a PUT request is sent to http://<plateform_location>/api/ldt/projects/<project_id>.<format>. 
-            <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> is the format of the data sent back by the server. It can be 'json', 'yaml', 'xml' or 'pickle'.
-            
-        If the request contains a content-type header whose value is set to "application/json" and a valid utf-8 encoded JSON file,
-        the following conditions will be checked before the annotations are added : 
-            If the submitted file is not valid or 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). New cuttings are added to the view 
-            "View at the last recording" if it exists, or to the view "Init view" else. If none of those views exist, the server will 
-            not add the cutting to a view. Several annotations can be added at the same time if the submitted file contains multiple 
-            annotations. The server returns the file submitted if all annotations have been added successfully, and adds to this file
-            IDs of created annotations to the file with a 200("OK") error code.
-        
-        If no content-type header is set, the file submitted must be a valid XML file and will replace entirely the ldt field
-        of the project without any verifications.  
-        
-        Example :
-        
-        Remark : The file below contain the minimum necessary fields and attributes for the handler to work. If one field or attribute is
-        missing (e.g. author, or date) during submission, an error will occur.
-        
-        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 inside the view "View at the last recording". The following JSON file exists in the current directory :
-    
-        Example of ajax call with 2 differents annotations :
-        $('#mon_ajax').click(function(e) {
-            var url = "{% url project_api project_id='c8448f21-272d-11e1-876b-c8bcc896c290' emitter_format='.json' %}"; // Don't forget the "." before "json" !
-            
-            var monjson = '{\
-                    "annotations": [\
-                        {\
-                            "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\
-                            "type_title": "New cutting name if necessary",\
-                            "media": "briandepalma_scarfacedepalma",\
-                            "begin": 1600000,\
-                            "end": 2100000,\
-                            "content": {\
-                                "data": "new scar annot"\
-                                "audio": {\
-                                    "mimetype": "audio/mp3",\
-                                    "src": "mic",\
-                                    "href": "rtmp://media.iri.centrepompidou.fr/ddc_micro_record/r_20120606190143793"\
-                                }\
-                            },\
-                            "tags": [ "json","dude" ]\
-                        }\
-                    ],\
-                    "meta": {\
-                        "creator": "John Doe",\
-                        "created": "2011-09-10T09:12:58"\
-                    }\
-                }';
-            var monjson2 = '{\
-                    "annotations": [\
-                        {\
-                            "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\
-                            "type_title": "New cutting name if necessary",\
-                            "media": "briandepalma_scarfacedepalma",\
-                            "begin": 2400000,\
-                            "end": 3000000,\
-                            "content": {\
-                                "data": "ntm iam 2"\
-                            },\
-                            "tags": [ "jak" ]\
-                        }\
-                    ],\
-                    "meta": {\
-                        "creator": "John Doe",\
-                        "created": "2011-09-10T09:12:58"\
-                    }\
-                }';
-            
-            $.ajax({
-                url: url,
-                type: 'PUT',
-                contentType: 'application/json',
-                data: monjson,
-                // bug with jquery >= 1.5, "json" adds a callback so we don't specify dataType
-                //dataType: 'json',
-                success: function(json, textStatus, XMLHttpRequest) {
-                    alert("success = " + json);
-                },
-                error: function(jqXHR, textStatus, errorThrown) {
-                    alert("ERROR = " + jqXHR.responseText + ", " + errorThrown);
-                }
-            });
-        });
-        
-        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 the first annotation inside, and the annotation "Annotation about Salieri"
-        will be added to the Salieri cutting. The returned file is :
-        
-        {
-            "annotations": [
-                {
-                    "id": "6d8baf01-ffb1-11e0-810c-001485352c9a",
-                    "type": "id_annot_type",
-                    "type_title": "New cutting name",
-                    "media": "milosforman_amadeus",
-                    "begin": 50000,
-                    "end": 900000,
-                    "content": {
-                        "data": "new annotation"
-                    },
-                    "tags": [ "json" ]
-                },
-                {
-                    "id": "6d8baf00-ffb1-11e0-8097-001485352c9b",
-                    "type": "another_id_annot_type",
-                    "type_title": "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"
-            }
-        }
-        
-        """
-        #return rc.ALL_OK
-        try:
-            project = Project.objects.get(ldt_id=project_id)
-        except Project.DoesNotExist:
-            return rc.NOT_HERE
-    
-        adder = LdtAnnotation(project)
-        logging.debug("request json " + repr(request.data))
-        
-        unprotect_models() # Allows anonymous user to modify models in this request only 
-
-        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'])
-            # We test if the annotation has audio node
-            audio_src = ""
-            audio_href = ""
-            if a['content'].has_key('audio') :
-                if a['content']['audio'].has_key('src') :
-                    audio_src = a['content']['audio']['src']
-                if a['content']['audio'].has_key('href') :
-                    audio_href = a['content']['audio']['href']
-            type_id, new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href)
-            if not new_id:
-                protect_models()
-                return rc.BAD_REQUEST
-            
-                            
-            content = project.contents.get(iri_id=a['media'])
-            add_annotation_to_stat(content, a['begin'], a['end'])
-            
-            # We update the ids
-            a['type'] = type_id
-            a['id'] = new_id
-            if not a['content'].has_key('audio') :
-                a['content']['audio'] = {'src':audio_src, 'href':audio_href}
-        
-        # We save if there were added annotation
-        if len(new_annotations)>0 :
-            adder.save()
-        
-        protect_models()
-        
-        return request.data
-            
-
-        
-class ContentHandler(BaseHandler):
-    allowed_methods = ('GET', 'PUT')
-    model = Content
-    exclude = (
-               ("media_obj"),
-               )   
-
-    def read(self, request, iri_id):
-        """
-        returns a single content
-        """
-        return Content.objects.get(iri_id=iri_id)   
-
-    @require_extended
-    def update(self, request, iri_id):
-        """
-        Receives a json exactly like AnnotationHandler, but without any project indicated.
-        We get or set the current content front project, and add the annotation
-        """
-        try:
-            content = Content.objects.get(iri_id=iri_id)
-        except Content.DoesNotExist:
-            return rc.NOT_HERE
-        proj = content.get_or_create_front_project()
-        ah = AnnotationHandler()
-        updated_data = ah.update(request, proj.ldt_id)
-        
-        return updated_data
-    
-
-class SegmentHandler(BaseHandler):
-    allowed_methods = ('GET', )
-    model = Segment
-    exclude = (
-               ("project_obj"),
-               ("content"),
-               )
-    
-    def read(self, request, iri_id, begin, end):
-        """
-        returns segments about content iri_id between timecodes begin and end
-        """
-        begin = int(begin)
-        end = int(end)
-        
-        content = Content.objects.filter(iri_id=iri_id)
-        if not content:
-            return rc.NOT_FOUND
-        content = content[0]
-        
-        segments = Segment.objects.filter(content=content).filter(
-                    Q(start_ts__gte=begin, start_ts__lte=end) |                            # segment starts between begin and end
-                    Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end
-                    Q(start_ts__lte=begin, start_ts__gte=end-F('duration'))                # period [begin:end] is included in the segment
-                    )
-        
-        a = SegmentSerializer(content, segments)
-        return a.serialize_to_cinelab()
-    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/__init__.py	Mon Oct 22 18:22:39 2012 +0200
@@ -0,0 +1,6 @@
+from annotation import AnnotationResource
+from content import ContentResource
+from project import ProjectResource
+from segment import SegmentResource
+
+__all__ = ["AnnotationResource", "ContentResource", "ProjectResource", "SegmentResource"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/annotation.py	Mon Oct 22 18:22:39 2012 +0200
@@ -0,0 +1,109 @@
+from ldt.ldt_utils.models import Project, Content
+from ldt.ldt_utils.stat import add_annotation_to_stat
+from ldt.ldt_utils.utils import LdtAnnotation
+from ldt.security import protect_models, unprotect_models
+from tastypie import fields
+from tastypie.authorization import Authorization
+from tastypie.exceptions import NotFound, BadRequest
+from tastypie.resources import Resource
+import logging #@UnresolvedImport
+
+
+class AnnotationObject(object):
+    # For the moment, these attributes are useless. We just need to define AnnotationObject
+    id = ""
+    project = ""
+    type = ""
+    type_title = ""
+    media = ""
+    begin = ""
+    end = "" 
+    content = {"data":""}
+    tags = []
+    meta = {"creator":"","created":""}
+    
+class AnnotationResource(Resource):
+    # For the moment, these attributes are useless. We just prepare relations to AnnotationObject
+    id = fields.CharField(attribute = 'id')
+    project = fields.CharField(attribute = 'project')
+    type = fields.CharField(attribute = 'type')
+    type_title = fields.CharField(attribute = 'type_title')
+    media = fields.CharField(attribute = 'media')
+    begin = fields.IntegerField(attribute = 'begin')
+    end = fields.IntegerField(attribute = 'end')
+    content = fields.DictField(attribute = 'content')
+    tags = fields.ListField(attribute = 'tags')
+    meta = fields.DictField(attribute = 'meta')
+    
+    class Meta:
+        allowed_methods = ['put']
+        resource_name = 'annotations'
+        object_class = AnnotationObject
+        authorization = Authorization()
+        # always_return_data = True because we want the api returns the data with the updated ids
+        always_return_data = True
+    
+    def obj_delete_list(self, request=None, **kwargs):
+        return True
+    
+    def obj_create(self, bundle, request=None, **kwargs):
+        """
+        """
+        logging.debug("ICI 0-1 bundle.data = " + repr(bundle.data))
+        project_id = ""
+        if bundle.data.has_key('project') :
+            project_id = bundle.data["project"]
+        if project_id and project_id != "" :
+            try:
+                project = Project.objects.get(ldt_id=project_id)
+            except Project.DoesNotExist:
+                raise NotFound("Project not found. project_id = " + project_id)
+        else :
+            # If the project's is not defined, we get or create the content's front project.
+            iri_id = bundle.data["media"]
+            try:
+                content = Content.objects.get(iri_id=iri_id)
+            except Content.DoesNotExist:
+                raise NotFound("Content not found. iri_id = " + iri_id)
+            project = content.get_or_create_front_project()
+            bundle.data["project"] = project.ldt_id
+        
+        adder = LdtAnnotation(project)
+        unprotect_models() # Allows anonymous user to modify models in this request only
+        # Here the bundle.data has the datas for only one annotation. The others api's functions parse the "objects" from the request's json.
+        a = bundle.data
+        dur = str(a['end'] - a['begin'])
+        begin = str(a['begin'])
+        # We test if the annotation has audio node
+        audio_src = ""
+        audio_href = ""
+        if a['content'].has_key('audio') :
+            if a['content']['audio'].has_key('src') :
+                audio_src = a['content']['audio']['src']
+            if a['content']['audio'].has_key('href') :
+                audio_href = a['content']['audio']['href']
+        meta = a['meta']
+        author = meta['creator']
+        date = meta['created']
+        type_id, new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href)
+        if not new_id:
+            protect_models()
+            raise BadRequest
+                        
+        content = project.contents.get(iri_id=a['media'])
+        add_annotation_to_stat(content, a['begin'], a['end'])
+        
+        # We update the ids
+        bundle.data['type'] = type_id
+        bundle.data['id'] = new_id
+        if not bundle.data['content'].has_key('audio') :
+            bundle.data['content']['audio'] = {'src':audio_src, 'href':audio_href}
+        # We reinject the datas in the bundle's response
+        bundle = self.full_hydrate(bundle)
+            
+        # We save the added annotation and reprotect the contents and projects
+        adder.save()
+        protect_models()
+        return bundle
+
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/content.py	Mon Oct 22 18:22:39 2012 +0200
@@ -0,0 +1,18 @@
+from django.conf.urls.defaults import url
+from ldt.ldt_utils.models import Content
+from tastypie.resources import ModelResource
+
+        
+class ContentResource(ModelResource):
+    class Meta:
+        allowed_methods = ['get']
+        resource_name = 'contents'
+        queryset = Content.objects.all()
+        excludes = ['media_obj']
+
+    def override_urls(self):
+        # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated 
+        return [
+            url(r"^(?P<resource_name>%s)/(?P<iri_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
+        ]
+            
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/project.py	Mon Oct 22 18:22:39 2012 +0200
@@ -0,0 +1,23 @@
+from django.conf.urls.defaults import url
+from ldt.ldt_utils.models import Project
+from tastypie.authorization import Authorization
+from tastypie.resources import ModelResource
+
+
+class ProjectResource(ModelResource):
+    class Meta:
+        allowed_methods = ['get', 'put']
+        authorization= Authorization() # BE CAREFUL WITH THAT, it's unsecure
+        resource_name = 'projects'
+        queryset = Project.objects.all()
+    
+#    # WARNING : this project API will only accepts and returns json format, no matter format get parameter.
+#    def determine_format(self, request):
+#        return "application/json"
+    
+    def override_urls(self):
+        # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated 
+        return [
+            url(r"^(?P<resource_name>%s)/(?P<ldt_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
+        ]
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/segment.py	Mon Oct 22 18:22:39 2012 +0200
@@ -0,0 +1,99 @@
+from django.conf import settings
+from django.conf.urls.defaults import url
+from django.core.paginator import Paginator, InvalidPage
+from django.db.models import F, Q
+from ldt.indexation import get_results_with_context
+from ldt.ldt_utils.models import Content, Segment
+from ldt.ldt_utils.segmentserializer import SegmentSerializer
+from tastypie.http import HttpNotFound
+from tastypie.resources import ModelResource
+from tastypie.utils import trailing_slash
+
+
+class SegmentResource(ModelResource):
+    class Meta:
+        allowed_methods = ['get']
+        resource_name = 'segments'
+        excludes = ['project_obj', 'content']
+        queryset = Segment.objects.all()
+        filtering = {
+            'iri_id': ['exact'],
+            'start_ts': ['lte', 'gte'],
+        }
+    
+#    # WARNING : this segment API will only return json format, no matter format get parameter.
+#    def determine_format(self, request):
+#        return "application/json"
+    
+    def override_urls(self):
+        # WARNING : in tastypie <= 0.9.11, override_urls is used instead of prepend_urls. From 0.9.12, prepend_urls will be prefered and override_urls deprecated
+        return [
+            url(r"^(?P<resource_name>%s)/search%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_search'), name="api_get_search"),
+            url(r"^(?P<resource_name>%s)/bytimecode%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_segments_by_timecode'), name='segment_api_empty'),
+            url(r"^(?P<resource_name>%s)/bytimecode/(?P<iri_id>.*)/(?P<begin>.*)/(?P<end>.*)$" % self._meta.resource_name, self.wrap_view('get_segments_by_timecode'), name='segment_api'),
+        ]
+
+    def get_search(self, request, **kwargs):
+        self.method_check(request, allowed=['get'])
+        # Do the query.
+        search = request.GET.get('q', '')
+        field = "all"
+        content_list = None
+        if u'author:' in search.lower() :
+            sub = search[7:]
+            sub = sub.upper()
+            if sub[0] != u'"':
+                sub = u'"' + sub
+            if sub[-1] != u'"':
+                sub = sub + u'"'
+            search = u'author:' + sub
+        results = get_results_with_context(field, search, content_list)
+        all_segments = Segment.objects.filter(element_id__in=[e['element_id'] for e in results])
+        paginator = Paginator(all_segments, getattr(settings, 'API_LIMIT_PER_PAGE', 20))
+
+        try:
+            page = paginator.page(int(request.GET.get('page', 1)))
+        except InvalidPage:
+            raise HttpNotFound("Sorry, no results on that page.")
+
+        objects = []
+
+        for segment in page.object_list:
+            bundle = self.build_bundle(obj=segment, request=request)
+            bundle = self.full_dehydrate(bundle)
+            objects.append(bundle)
+
+        object_list = {
+            'objects': objects,
+        }
+
+        self.log_throttled_access(request)
+        return self.create_response(request, object_list)
+    
+    
+    
+    def get_segments_by_timecode(self, request, api_name, resource_name, iri_id=None, begin=None, end=None):
+        """
+        returns segments about content iri_id between timecodes begin and end
+        """
+        if not begin:
+            return HttpNotFound("begin timecode argument is missing.")
+        if not end:
+            return HttpNotFound("end timecode argument is missing.")
+        begin = int(begin)
+        end = int(end)
+        
+        content = Content.objects.filter(iri_id=iri_id)
+        if not content:
+            return HttpNotFound("Content does not exist or id is not correct.")
+        content = content[0]
+        
+        segments = Segment.objects.filter(content=content).filter(
+                    Q(start_ts__gte=begin, start_ts__lte=end) |                            # segment starts between begin and end
+                    Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end
+                    Q(start_ts__lte=begin, start_ts__gte=end-F('duration'))                # period [begin:end] is included in the segment
+                    )
+        
+        a = SegmentSerializer(content, segments)
+        return self.create_response(request, a.serialize_to_cinelab())
+    
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/urls.py	Mon Oct 22 18:19:12 2012 +0200
+++ b/src/ldt/ldt/api/ldt/urls.py	Mon Oct 22 18:22:39 2012 +0200
@@ -1,20 +1,13 @@
-from django.conf.urls.defaults import patterns, url
-from django.views.defaults import page_not_found
-from piston.resource import Resource
-from ldt.api.ldt.handlers import ProjectHandler, AnnotationHandler, ContentHandler, SegmentHandler
+from django.conf.urls.defaults import patterns, include
+from ldt.api.ldt.resources import ProjectResource, ContentResource, SegmentResource, AnnotationResource
+from tastypie.api import Api
 
-project_handler    = Resource(ProjectHandler, None)
-annotation_handler = Resource(AnnotationHandler, None)
-content_handler    = Resource(ContentHandler, None)
-segment_handler    = Resource(SegmentHandler, None)
+v1_api = Api(api_name='1.0')
+v1_api.register(ProjectResource())
+v1_api.register(ContentResource())
+v1_api.register(SegmentResource())
+v1_api.register(AnnotationResource())
 
 urlpatterns = patterns('',
-    url(r'projects/(?P<project_id>[^/.]+)\.?(?P<emitter_format>.*)$', project_handler, name='project_api'),
-    url(r'annotations/$', page_not_found, name='annotation_api_empty'),
-    url(r'annotations/(?P<project_id>[^/.]+)\.?(?P<emitter_format>.*)$', annotation_handler, name='annotation_api'),
-    url(r'contents/(?P<iri_id>[^/.]+)\.?(?P<emitter_format>.*)$', content_handler, name='content_api'),
-    url(r'segments/$', page_not_found, name='segment_api_empty'),
-    url(r'segments/(?P<iri_id>.*)/(?P<begin>.*)/(?P<end>.*)$', segment_handler, name='segment_api'),
+    (r'', include(v1_api.urls)),
 )
-
-
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html	Mon Oct 22 18:19:12 2012 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html	Mon Oct 22 18:22:39 2012 +0200
@@ -69,7 +69,7 @@
         },{
             type: "AnnotationsList",
             container: "AnnotationsList_ext",
-            ajax_url: "{{WEB_URL}}{% url segment_api_empty %}{% templatetag openvariable %}media{% templatetag closevariable %}/{% templatetag openvariable %}begin{% templatetag closevariable %}/{% templatetag openvariable %}end{% templatetag closevariable %}",
+            ajax_url: "{{WEB_URL}}{% url segment_api_empty resource_name='segments' api_name='1.0' %}{% templatetag openvariable %}media{% templatetag closevariable %}/{% templatetag openvariable %}begin{% templatetag closevariable %}/{% templatetag openvariable %}end{% templatetag closevariable %}",
             ajax_granularity : 300000,
             default_thumbnail : "{{WEB_URL}}{{LDT_MEDIA_PREFIX}}css/imgs/video_sequence.png",
             show_audio: true,
Binary file virtualenv/res/src/PyYAML-3.10.tar.gz has changed
Binary file virtualenv/res/src/django-tastypie-0.9.11.tar.gz has changed
Binary file virtualenv/res/src/mimeparse-0.1.3.tar.gz has changed
Binary file virtualenv/res/src/python-dateutil-2.1.tar.gz has changed
Binary file virtualenv/res/src/python-digest-1.7.tar.gz has changed