]> git.parisson.com Git - telemeta.git/commitdiff
- coupled the web interface with the export layer
authorolivier <>
Mon, 23 Apr 2007 08:09:32 +0000 (08:09 +0000)
committerolivier <>
Mon, 23 Apr 2007 08:09:32 +0000 (08:09 +0000)
- improved collections and items browsing
- minor CSS improvements
- now using Django typical models instead of "dynamic" ones
- made simple models based on Dublin Core elements

telemeta/css/style.css
telemeta/models.py
telemeta/templates/base.html
telemeta/templates/collection_detail.html [new file with mode: 0644]
telemeta/templates/collection_list.html [new file with mode: 0644]
telemeta/templates/index.html
telemeta/templates/mediaitem_detail.html [new file with mode: 0644]
telemeta/templates/mediaitem_list.html
telemeta/urls.py
telemeta/views/web.py

index 54afe4f6c0bd4624356ae4f7688ac29ec517ab88..5b3036fa80b484540de866e29062e5ea0e0443b6 100644 (file)
@@ -1,5 +1,6 @@
 body {
     font-family: Verdana;
+    font-size: 11px;
 }
 
 #header {
@@ -17,3 +18,21 @@ label {
 input {
     margin-bottom: 4px;
 }
+
+#menu {
+    text-align: right;
+}
+
+#menu a:link, #menu a:visited {
+    border-bottom:1px dotted #BBBBBB;
+    color:#BB0000;
+    text-decoration:none;
+}
+
+#menu a:link:hover, #menu a:visited:hover {
+    background-color:#EEEEEE;
+    color:#555555;
+}
+
+#menu a {
+}
index be0a80c6d32b08cf9a151e1735fd73ce15f31408..ae2028103b5eff1116f8646186426421ac28c2e7 100644 (file)
 import telemeta
 from django.db import models
-from django.core import validators
+from telemeta.core import *
 
-class Collection(models.Model):
-    "Group related media items"
+class MediaModel(Component):
+    pass
 
-    name = models.CharField(maxlength=250)
+class MediaCore:
+    def list(self):
+        fields_list = []
+        for field in self._meta.fields:
+            fields_list.append({'name': field.name, 'value': getattr(self, field.name)})
+        return fields_list
 
-    def __str__(self):
-        return self.name
+    def to_dict(self):        
+        fields_dict = {}
+        for field in self._meta.fields:
+            fields_dict[field.name] = getattr(self, field.name)
+        return fields_dict
 
-    class Admin:
-        pass
-
-class MediaItem(models.Model):
-    "Describe an audio/video item with metadata" 
+class MediaCollection(models.Model, MediaCore):
+    "Group related media items"
 
-    collection = models.ForeignKey(Collection)
     title = models.CharField(maxlength=250)
-    author = models.CharField(maxlength=250)
-
-
-
-    def get_dynamic_properties(self):
-        "Retrieve dynamic properties associated with a given media item"
-
-        definitions = MediaItemPropertyDefinition.objects.all()
-        assigned = MediaItemProperty.objects.filter(media_item=self)
-        assigned_dict = {}
-        for p in assigned:
-            assigned_dict[p.definition.id] = p
-
-        properties = []
-        for d in definitions:
-            enumeration = MediaItemPropertyEnumerationItem.objects.filter(definition=d)
-
-            if d.id in assigned_dict:
-                if d.type == "text":
-                    value = assigned_dict[d.id].value
-                else:
-                    value = assigned_dict[d.id].enum_item
-
-                properties.append({
-                    "id": d.id, "name": d.name, "value": value,
-                    "type" : d.type, "enumeration" : enumeration})
-            else:
-                properties.append({"id": d.id, "name": d.name, "value": "", 
-                    "type" : d.type, "enumeration" : enumeration})
-
-        return properties
+    date = models.DateField()
+    contributor = models.CharField(maxlength=250, blank=True)
+    coverage = models.CharField(maxlength=250, blank=True)
+    creator = models.CharField(maxlength=250, blank=True)
+    description = models.CharField(maxlength=250, blank=True)
+    format = models.CharField(maxlength=250, blank=True)
+    identifier = models.CharField(maxlength=250, blank=True)
+    language = models.CharField(maxlength=250, blank=True)
+    publisher = models.CharField(maxlength=250, blank=True)
+    rights = models.CharField(maxlength=250, blank=True)
+    source = models.CharField(maxlength=250, blank=True)
+    subject = models.CharField(maxlength=250, blank=True)
 
     def __str__(self):
-        return self.author + " - " + self.title
+        return self.title
 
     class Meta:
-        pass
+        ordering = ['title']
+        db_table = 'telemeta_collection'
 
     class Admin:
         pass
 
-class MediaItemPropertyDefinition(models.Model):
-    "Define a media item dynamic property"
-
-    TYPE_CHOICES = (
-        ('text', 'Text'),
-        ('enumeration', 'Enumeration'),
-    ) 
 
-    name = models.CharField(maxlength=64)
-    type = models.CharField(maxlength=64, choices = TYPE_CHOICES)
-
-    def __str__(self):
-        return self.name
-
-    class Admin:
-        pass
 
-class MediaItemPropertyEnumerationItem(models.Model):
-    "Define a possible value for media item dynamic enumeration properties"
+class MediaItem(models.Model, MediaCore):
+    "Describe a item with metadata" 
 
-    definition = models.ForeignKey(MediaItemPropertyDefinition, core=True)
-    name = models.CharField(maxlength=250)
+    collection = models.ForeignKey(MediaCollection, related_name="items")
+    collection.dublin_core = 'relation'
+    identifier = models.CharField(maxlength=250)
+    title = models.CharField(maxlength=250)
+    creator = models.CharField(maxlength=250)
+    date = models.DateField()
+    file = models.FileField(upload_to='items/%Y/%m/%d')
+    subject = models.CharField(maxlength=250, blank=True)
+    description = models.TextField(maxlength=250, blank=True)
+    contributor = models.CharField(maxlength=250, blank=True)
+    coverage = models.CharField(maxlength=250, blank=True)
+    format = models.CharField(maxlength=25, blank=True)
+    language = models.CharField(maxlength=250, blank=True)
+    publisher = models.CharField(maxlength=250, blank=True)
+    rights = models.CharField(maxlength=250, blank=True)
+    source = models.CharField(maxlength=250, blank=True)
+    duration = models.FloatField(max_digits=11, decimal_places=3, null=True, blank=True)
 
     def __str__(self):
-        return self.definition.name + " / " + self.name
+        return self.title
 
     class Admin:
         pass
-    
-class MediaItemProperty(models.Model):
-    "Associate a value to a media item dynamic property"
 
-    definition = models.ForeignKey(MediaItemPropertyDefinition, core=True)
+    class Meta:
+        ordering = ['title']
+        db_table = 'telemeta_item'
+
+
+class MediaPart(models.Model, MediaCore):
+    "Describe the part of a media item"
+
+    contributor = models.CharField(maxlength=250)
+    coverage = models.CharField(maxlength=250)
+    creator = models.CharField(maxlength=250)
+    date = models.DateField()
+    description = models.CharField(maxlength=250)
+    format = models.CharField(maxlength=250)
+    identifier = models.CharField(maxlength=250)
+    language = models.CharField(maxlength=250)
+    publisher = models.CharField(maxlength=250)
+    rights = models.CharField(maxlength=250)
+    source = models.CharField(maxlength=250)
+    subject = models.CharField(maxlength=250)
+    title = models.CharField(maxlength=250)
     media_item = models.ForeignKey(MediaItem)
-    value = models.CharField(maxlength=250)
-    enum_item = models.ForeignKey(MediaItemPropertyEnumerationItem, null=True)
+    media_item.dublin_core = 'relation'
+    parent = models.ForeignKey('self', null=True, related_name='children')
+    media_item.dublin_core = 'relation'
+    start = models.FloatField(max_digits=11, decimal_places=3)
+    end = models.FloatField(max_digits=11, decimal_places=3)
 
     def __str__(self):
-        return str(self.media_item) + " / " + str(self.definition)
+        return self.title
 
     class Meta:
-        unique_together = (("media_item", "definition"),)
+        ordering = ['title']
+        db_table = 'telemeta_part'
 
     class Admin:
         pass
-  
 
-class Part:
-    media_item = models.ForeignKey(MediaItem)
-    parent = models.ForeignKey('self', null=True, related_name='children')
-    name = models.CharField(maxlength=250)
+
index 38bff8faf9612aecb3ebd1ebd0919c9d4b7437d7..f69b266ed22b2dfcf3b565c9caa2f1aa73be5cba 100644 (file)
@@ -1,9 +1,13 @@
 <html>
-<link rel="stylesheet" href="/telemeta/css/style.css" />
+<link rel="stylesheet" href="/css/style.css" />
 <body>
 <div id="header">
 Telemeta Web Interface
 </div>
+<div id="menu">
+<a href="/collections">Collections</a> |
+<a href="/items">Items</a>
+</div>
 {% block content %}{% endblock %}
 </body>
 </html>
diff --git a/telemeta/templates/collection_detail.html b/telemeta/templates/collection_detail.html
new file mode 100644 (file)
index 0000000..31cbb4e
--- /dev/null
@@ -0,0 +1,30 @@
+{% extends "base.html" %}
+
+{% block content %}
+{% if object %}
+    <h3>Collection: {{ object.title }}</h3>
+    <ul>
+    {% for field in object.list %}
+        {% ifnotequal field.name "id" %}
+        {% ifnotequal field.name "title" %}
+
+        <li><b>{{ field.name }}</b> : {{ field.value }}</li>
+
+        {% endifnotequal %}
+        {% endifnotequal %}
+    {% endfor %}
+    </ul>
+    <hr>
+    <h4>Items</h4>
+    <ul>
+    {% for item in object.items.all %}
+        <li><b>{{ item.creator }}</b> - {{ items.title }}
+            <a href="/items/{{ item.id }}">View</a>
+            <a href="#">Edit</a>
+            </li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>No such collection</p>
+{% endif %}
+{% endblock %}
diff --git a/telemeta/templates/collection_list.html b/telemeta/templates/collection_list.html
new file mode 100644 (file)
index 0000000..d70c35b
--- /dev/null
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% block content %}
+<h3>Collections</h3>
+{% if object_list %}
+    <ul>
+    {% for p in object_list %}
+        <li><b>{{ p.title }}</b>
+            <a href="{{ p.id }}">View</a>
+            <a href="#">Edit</a>
+            </li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>No pieces are available.</p>
+{% endif %}
+{% endblock %}
index 99470102f7e51bfe276c46041c44eca79acb445e..47858bc74ad71abb46fedecff338780784ce1651 100644 (file)
@@ -1,12 +1,17 @@
-<pre>{% debug %}</pre>
+{% extends "base.html" %}
 
-<h3>Pieces</h3>
-{% if pieces %}
+{% block content %}
+<h3>Media items</h3>
+{% if object_list %}
     <ul>
-    {% for p in pieces %}
-        <li><b>{{ p.author }}</b> - {{ p.title }}</li>
+    {% for p in object_list %}
+        <li><b>{{ p.author }}</b> - {{ p.title }}
+            <a href="{{ p.id }}">View</a>
+            <a href="#">Edit</a>
+            </li>
     {% endfor %}
     </ul>
 {% else %}
-    <p>No pieces are available.</p>
+    <p>No media item available.</p>
 {% endif %}
+{% endblock %}
diff --git a/telemeta/templates/mediaitem_detail.html b/telemeta/templates/mediaitem_detail.html
new file mode 100644 (file)
index 0000000..3e529c7
--- /dev/null
@@ -0,0 +1,32 @@
+{% extends "base.html" %}
+
+{% block content %}
+{% if item %}
+    <h3>Item: {{ item.title }}</h3>
+    <ul>
+    {% for field in item.list %}
+        {% ifnotequal field.name "id" %}
+        {% ifnotequal field.name "title" %}
+        {% ifnotequal field.name "file" %}
+
+        <li><b>{{ field.name }}</b> : 
+            {% ifequal field.name "collection" %}
+            <a href="/collections/{{ field.value.id }}">{{ field.value }}</a>
+            {% else %}
+            {{ field.value }}
+            {% endifequal %}
+            </li>
+
+        {% endifnotequal %}
+        {% endifnotequal %}
+        {% endifnotequal %}
+    {% endfor %}
+    </ul>
+    Download:
+    {% for format in export_formats %}
+        <a href="/items/{{ item.id }}/download/{{ format }}">{{ format }}</a>
+    {% endfor %}
+{% else %}
+    <p>No such item</p>
+{% endif %}
+{% endblock %}
index b32353ff9eaf7216628431cc2a34acdb60ce976a..bcdec1b1d8d26ba026cf81c5a0e763668b5cd8d8 100644 (file)
@@ -5,7 +5,7 @@
 {% if object_list %}
     <ul>
     {% for p in object_list %}
-        <li><b>{{ p.author }}</b> - {{ p.title }}
+        <li><b>{{ p.creator }}</b> - {{ p.title }}
             <a href="{{ p.id }}">View</a>
             <a href="#">Edit</a>
             </li>
index 14a33dbed95c2da85ecced7becbd4334682532d1..8ca6fa4e91e28af4da139dfb78610ac87780ea65 100644 (file)
@@ -1,17 +1,31 @@
 from django.conf.urls.defaults import *
-from telemeta.models import MediaItem
+from telemeta.models import MediaItem, MediaCollection
 
-list_dict = {
+all_items = {
     'queryset': MediaItem.objects.all(),
 }
 
+all_collections = {
+    'queryset': MediaCollection.objects.all(),
+}
+
 urlpatterns = patterns('',
     (r'^$', 'telemeta.views.web.index'),
-    (r'^media_item/$', 'django.views.generic.list_detail.object_list', 
-        dict(list_dict, paginate_by=10, template_name="mediaitem_list.html")),
-    (r'^media_item/(?P<media_item_id>[0-9]+)/$', 'telemeta.views.web.media_item_edit'),
+    (r'^items/$', 'django.views.generic.list_detail.object_list', 
+        dict(all_items, paginate_by=10, template_name="mediaitem_list.html")),
+    (r'^items/(?P<item_id>[0-9]+)/$', 'telemeta.views.web.item_detail'),
+    (r'^items/(?P<item_id>[0-9]+)/download/(?P<format>[0-9A-Z]+)/$', 
+        'telemeta.views.web.item_export'),
+    #(r'^media_item/(?P<media_item_id>[0-9]+)/$', 'telemeta.views.web.media_item_edit'),
     (r'^media_item/(?P<media_item_id>[0-9]+)/update/$', 'telemeta.views.web.media_item_update'),
 
+    (r'^collections/$', 'django.views.generic.list_detail.object_list',
+        dict(all_collections, paginate_by=10, template_name="collection_list.html")),
+    (r'^collections/(?P<object_id>[0-9]+)/$', 
+        'django.views.generic.list_detail.object_detail',
+        dict(all_collections, template_name="collection_detail.html")),
+
+
     # CSS (FIXME: for developement only)
     (r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': './telemeta/css'}),
 )
index b8380b4799d6ae526b5968671398023a1989c3e6..a4ff71e9a599453889d834d77f2375c9091a3a29 100644 (file)
@@ -2,12 +2,15 @@
 import telemeta
 from django.template import Context, loader
 from django.http import HttpResponse
+from django.http import Http404
 from telemeta.models import MediaItem
-from telemeta.models import MediaItemPropertyDefinition
-from telemeta.models import MediaItemPropertyEnumerationItem
-from telemeta.models import MediaItemProperty
 from django.shortcuts import render_to_response
 import re
+from telemeta.core import *
+from telemeta.core import ComponentManager
+from telemeta.export import *
+from django.conf import settings
+import os
 
 def index(request):
     "Render the homepage"
@@ -19,6 +22,58 @@ def index(request):
     })
     return HttpResponse(template.render(context))
 
+class WebView(Component):
+
+    exporters = ExtensionPoint(IExporter)
+
+    def item_detail(self, request, item_id):
+        item = MediaItem.objects.get(pk=item_id)
+        formats = []
+        for exporter in self.exporters:
+            formats.append(exporter.get_format())
+        return render_to_response('mediaitem_detail.html', 
+                    {'item': item, 'export_formats': formats})
+
+    def file_stream(self, filepath):
+        buffer_size = 0xFFFF
+        f = open(filepath, 'rb')
+        chunk = f.read(buffer_size)
+        yield chunk
+        while chunk:
+            chunk = f.read(buffer_size)
+            yield chunk
+        f.close()            
+
+    def item_export(self, request, item_id, format):                    
+        for exporter in self.exporters:
+            if exporter.get_format() == format:
+                break
+
+        if exporter.get_format() != format:
+            raise Http404
+
+        mime_type = exporter.get_mime_type()
+
+        exporter.set_cache_dir(settings.TELEMETA_EXPORT_CACHE_DIR)
+
+        item = MediaItem.objects.get(pk=item_id)
+
+        infile = settings.MEDIA_ROOT + "/" + item.file
+        metadata = item.to_dict()
+        metadata['collection'] = str(metadata['collection'])
+        metadata['Collection'] = metadata['collection']
+        metadata['Artist'] = metadata['creator']
+        metadata['Title'] = metadata['title']
+
+        outfile = exporter.process(item.id, infile, metadata, [])
+
+        return HttpResponse(self.file_stream(outfile), mimetype = mime_type)
+
+comp_mgr = ComponentManager()
+view = WebView(comp_mgr)
+item_detail = view.item_detail
+item_export = view.item_export
+
 def media_item_edit(request, media_item_id):
     "Provide MediaItem object edition"