--- /dev/null
+# Copyright (C) 2007 Samalyse SARL
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://svn.parisson.org/telemeta/TelemetaLicense.
+#
+# Author: Olivier Guilyardi <olivier@samalyse.com>
+
+class Resource(object):
+ "Represent a Dublin Core resource"
+ def __init__(self, *args):
+ self.elements = args
+
+ def flatten(self):
+ """Convert the resource to a dictionary with element names as keys.
+
+ Warnings:
+ - refinements are lost during this conversion,
+ - if there are several occurences of the same element, only the first is
+ used, others are lost.
+ - all values are converted to strings
+ """
+ result = {}
+ for element in self.elements:
+ if not result.has_key(element.name):
+ result[element.name] = element.value
+ return result
+
+class Element(object):
+ "Represent a Dublin Core element"
+ def __init__(self, name, field=None, value=None, refinement=None):
+ self.name = name
+ self.value = value
+ self.refinement = refinement
+ self.field = field
+
font-size: 80%;
}
+a:link, a:visited {
+ border-bottom:1px dotted #BBBBBB;
+ color:#BB0000;
+ text-decoration:none;
+}
+
+a:link:hover, a:visited:hover {
+ background-color:#EEEEEE;
+ color:#555555;
+}
+
#header {
- font-size: 140%;
border-bottom: solid 1px black;
- font-weight: bold;
- padding-bottom: 0.8em;
+ padding-bottom: 0.2em;
padding-top: 0.2em;
}
#header a {
- color: black;
text-decoration: none;
}
#header a img {
border: none;
}
-/*
-label {
- width: 20ex;
- display: block;
- float: left;
-}
-input {
- margin-bottom: 1ex;
-}
-*/
#menu {
text-align: right;
clear: right;
}
-a:link, a:visited {
- border-bottom:1px dotted #BBBBBB;
- color:#BB0000;
- text-decoration:none;
-}
-
-a:link:hover, a:visited:hover {
- background-color:#EEEEEE;
- color:#555555;
+#submenu {
+ clear: right;
+ float: right;
+ padding-top: 1em;
}
-
-#menu a {
+#submenu a {
+ color: #000066;
}
#quick_search {
padding: 0.1em;
background: none;
}
+
+/* HTML dublin core display */
+
+table.dublincore {
+ width: auto;
+}
from django.db.models import Q
from telemeta.core import *
from django.core.exceptions import ObjectDoesNotExist
+from telemeta import dublincore as dc
class MediaModel(Component):
pass
class MediaCore:
- def list(self):
- fields_list = []
- for field in self._meta.fields:
- fields_list.append({'name': field.verbose_name, 'value': getattr(self, field.name)})
- return fields_list
-
- def to_dict(self):
+ def to_dict(self):
+ "Return model fields as a dict of name/value pairs"
fields_dict = {}
for field in self._meta.fields:
fields_dict[field.name] = getattr(self, field.name)
return fields_dict
+# def dc_elements(self):
+# """Return model fields mapped to Dublin Core elements, as a dict of
+# the form: {dc_element_name: [value1, value2, ....], ...}
+# """
+# fields_dict = {}
+# for field in self._meta.fields:
+# if (hasattr(field, 'dc_element')):
+# if fields_dict.has_key(field.dc_element):
+# fields_dict[field.dc_element].append(getattr(self, field.name))
+# else:
+# fields_dict[field.dc_element] = [getattr(self, field.name)]
+#
+# return fields_dict
+
class PhysicalFormat(models.Model):
value = models.CharField(maxlength=250)
is_dictionary = True
physical_format = models.CharField(maxlength=250, blank=True)
id = models.CharField(maxlength=250, primary_key=True,
verbose_name='identifier')
- id.dc_element = 'identifier'
title = models.CharField(maxlength=250)
- title.dc_element = 'title'
native_title = models.CharField(maxlength=250, blank=True)
- native_title.dc_element = 'title'
physical_items_num = models.CharField(maxlength=250, blank=True)
publishing_status = models.CharField(maxlength=250, blank=True)
is_original = models.CharField(maxlength=250)
is_full_copy = models.CharField(maxlength=250)
- copied_from = models.ForeignKey('self', blank=True)
- #copied_from[0].dc_element = 'relation'
+ copied_from = models.ForeignKey('self', null=True, blank=True)
creator = models.CharField(maxlength=250)
- creator.dc_element = 'creator'
booklet_writer = models.CharField(maxlength=250, blank=True)
- booklet_writer.dc_element = 'contributor'
booklet_description = models.TextField(blank=True)
collector = models.CharField(maxlength=250, blank=True)
- collector.dc_element = 'contributor'
publisher = models.CharField(maxlength=250, blank=True)
- publisher.dc_element = 'publisher'
date_published = models.CharField(maxlength=250, blank=True)
- date_published.dc_element = 'date'
publisher_collection = models.CharField(maxlength=250, blank=True)
publisher_serial_id = models.CharField(maxlength=250, blank=True)
ref_biblio = models.TextField(blank=True)
record_author = models.CharField(maxlength=250, blank=True)
record_writer = models.CharField(maxlength=250, blank=True)
rights = models.CharField(maxlength=250, blank=True)
- rights.dc_element = 'rights'
annee_enr = models.CharField(maxlength=250, blank=True)
- annee_enr.dc_element = 'date'
terrain_ou_autre = models.CharField(maxlength=250, blank=True)
duree_approx = models.CharField(maxlength=250, blank=True)
tri_dibm = models.CharField(maxlength=250, blank=True)
numerisation = models.CharField(maxlength=250, blank=True)
champ36 = models.CharField(maxlength=250, blank=True)
-# 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)
-# physical_format = models.ForeignKey(PhysicalFormat, null=True, blank=True)
-
objects = MediaCollectionManager()
+ def to_dublincore(self):
+ if (self.date_published):
+ date = self.date_published
+ else:
+ date = self.annee_enr
+
+ if (self.copied_from):
+ copied_from = self.copied_from.id
+ else:
+ copied_from = ''
+
+ resource = dc.Resource(
+ dc.Element('identifier','id', self.id),
+ dc.Element('type', value='Collection'),
+ dc.Element('title', 'title', self.title),
+ dc.Element('title', 'native_title', self.native_title),
+ dc.Element('creator', 'creator', self.creator),
+ dc.Element('relation', 'copied_from', copied_from,
+ 'isVersionOf'),
+ dc.Element('contributor', 'booklet_writer', self.booklet_writer),
+ dc.Element('contributor', 'collector', self.collector),
+ dc.Element('publisher', 'publisher', self.publisher),
+ dc.Element('date', value=date),
+ dc.Element('rights', 'rights', self.rights),
+ )
+ return resource
+
def __str__(self):
- return self.title
+ #return self.title
+ return self.id
class Meta:
ordering = ['title']
region_village = models.CharField(maxlength=250, blank=True)
ethnie_grsocial = models.CharField(maxlength=250, blank=True)
titre_support = models.CharField(maxlength=250, blank=True)
- _title = models.CharField(maxlength=250, db_column='title', blank=True)
+ _title = models.CharField(maxlength=250, db_column='title')
transcrip_trad = models.CharField(maxlength=250, blank=True)
auteur = models.CharField(maxlength=250, blank=True)
form_genr_style = models.CharField(maxlength=250, blank=True)
repere_bande = models.CharField(maxlength=250, blank=True)
nroband_nropiec = models.CharField(maxlength=250, blank=True)
continent = models.CharField(maxlength=250, blank=True)
- file = models.FileField(upload_to='items/%Y/%m/%d')
-
-# 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)
-#
+ file = models.FileField(upload_to='items/%Y/%m/%d', blank=True)
+
objects = MediaItemManager()
def _get_title(self):
return title
title = property(_get_title)
+ def to_dublincore(self):
+ if self.auteur:
+ creator = self.auteur
+ else:
+ creator = self.collection.creator
+
+ resource = dc.Resource(
+ dc.Element('identifier','id', self.id),
+ dc.Element('type', value='Sound'),
+ dc.Element('relation', 'collection', self.collection.id, 'isPartOf'),
+ dc.Element('title', 'title', self.title),
+ dc.Element('creator', value=creator),
+ dc.Element('publisher', value=self.collection.publisher),
+ )
+ return resource
+
def __str__(self):
return self.title
-->
<div id="header">
<a href="/"><img src="/images/logo.png"></a>
-</div>
<div id="quick_search">
<form action="{% url telemeta-quicksearch %}" method="GET">
<a href="{% url telemeta-items %}">Items</a> |
<a href="{% url telemeta-admin %}">Admin</a>
</div>
+</div>
+<div id="submenu">
+{% block submenu %}{% endblock %}
+</div>
<div id="content">
{% block content %}{% endblock %}
{% extends "base.html" %}
+{% load telemeta_utils %}
+
+{% block submenu %}
+ <a href="{% url telemeta-collection-dublincore object.id|urlencode %}">
+ Dublin Core</a>
+{% endblock %}
{% block content %}
{% if object %}
<h3>Collection: {{ object.title }}</h3>
<ul>
- {% for field in object.list %}
+ {% for field in object.to_dict|tolist %}
{% ifnotequal field.name "title" %}
<li><b>{{ field.name|capfirst }}</b> : {{ field.value }}</li>
<ul>
{% for item in object.items.all %}
<li><b>{{ item.creator }}</b> - {{ item.title }}
- <a href="{% url telemeta-item-detail item.id %}">View</a>
+ <a href="{% url telemeta-item-detail item.id|urlencode %}">View</a>
<a href="#">Edit</a>
</li>
{% endfor %}
--- /dev/null
+{% extends "base.html" %}
+{% load telemeta_utils %}
+
+{% block submenu %}
+ <a href="{% url telemeta-collection-detail object.id|urlencode %}">
+ Normal View</a>
+{% endblock %}
+
+{% block content %}
+{% if object %}
+ <h3>Collection: {{ object.title }}</h3>
+ <table class="dublincore listing">
+ <caption>Dublin Core Expression</caption>
+ <thead>
+ <tr><th>Element</th><th>Refinement</th><th>Value</th></tr>
+ </thead>
+ <tbody>
+ {% for element in object.to_dublincore.elements %}
+ {% if element.value %}
+ <tr><th>{{ element.name }}</th>
+ <td>{{ element.refinement|default:" " }}</td>
+ <td>{{ element.value }}</td>
+ {% endif %}
+ {% endfor %}
+ {% for item in object.items.all %}
+ <tr><th>relation</th><td>hasPart</td><td>
+ <a href="{% url telemeta-item-dublincore item.id|urlencode %}">
+ {{ item.id }}</a>
+ </td>
+ {% endfor %}
+ </tbody>
+ </table>
+{% else %}
+ <p>No such collection</p>
+{% endif %}
+{% endblock %}
{% extends "base.html" %}
+{% load telemeta_utils %}
+
+{% block submenu %}
+ <a href="{% url telemeta-item-dublincore item.id|urlencode %}">
+ Dublin Core</a>
+{% endblock %}
{% block content %}
{% if item %}
<div class="item_visualization">
- <img src="{% url telemeta-item-visualize item.id,visualizer_id %}">
+ <img src="{% url telemeta-item-visualize item.id|urlencode,visualizer_id %}">
<form method="GET">
<select name="visualizer_id" onchange="this.form.submit()">
{% for v in visualizers %}
</div>
<h3>Item: {{ item.title }}</h3>
<ul>
- {% for field in item.list %}
+ {% for field in item.to_dict|tolist %}
{% ifnotequal field.name "id" %}
{% ifnotequal field.name "title" %}
{% ifnotequal field.name "file" %}
<li><b>{{ field.name }}</b> :
{% ifequal field.name "collection" %}
- <a href="{% url telemeta-collection-detail field.value.id %}">
+ <a href="{% url telemeta-collection-detail field.value.id|urlencode %}">
{{ field.value }}</a>
{% else %}
{{ field.value }}
--- /dev/null
+{% extends "base.html" %}
+{% load telemeta_utils %}
+
+{% block submenu %}
+ <a href="{% url telemeta-item-detail item.id|urlencode %}">
+ Normal View</a>
+{% endblock %}
+
+{% block content %}
+{% if item %}
+ <h3>Item: {{ item.title }}</h3>
+ <table class="dublincore listing">
+ <caption>Dublin Core Expression</caption>
+ <thead>
+ <tr><th>Element</th><th>Refinement</th><th>Value</th></tr>
+ </thead>
+ <tbody>
+ {% for element in item.to_dublincore.elements %}
+ {% if element.value %}
+ <tr><th>{{ element.name }}</th>
+ <td>{{ element.refinement|default:" " }}</td>
+ <td>
+ {% ifequal element.field "collection" %}
+ <a href="{% url telemeta-collection-dublincore item.collection.id|urlencode %}">
+ {{ element.value }}</a>
+ {% else %}
+ {{ element.value }}
+ {% endifequal %}
+ </td>
+ </tr>
+ {% endif %}
+ {% endfor %}
+ </tbody>
+ </table>
+{% else %}
+ <p>No such item</p>
+{% endif %}
+{% endblock %}
+
# "Escapes a value for use in a URL (converts slashes)"
# return value.replace('/', '--')
+@register.filter
+def tolist(dict):
+ "Converts a simple dict into a list"
+ list = []
+ for k, v in dict.iteritems():
+ list.append({'name': k, 'value': v})
+ return list
+
url(r'^items/$', 'django.views.generic.list_detail.object_list',
dict(all_items, paginate_by=20, template_name="mediaitem_list.html"),
name="telemeta-items"),
- url(r'^items/(?P<item_id>[0-9A-Z._:-]+)/$', web_view.item_detail,
+ url(r'^items/(?P<item_id>[0-9A-Z._:%?-]+)/$', web_view.item_detail,
name="telemeta-item-detail"),
- url(r'^items/(?P<item_id>[0-9A-Z._:-]+)/download/(?P<format>[0-9A-Z]+)/$',
+ url(r'^items/(?P<item_id>[0-9A-Z._:%?-]+)/dc/$', web_view.item_detail,
+ {'template': 'mediaitem_detail_dc.html'},
+ name="telemeta-item-dublincore"),
+ url(r'^items/(?P<item_id>[0-9A-Z._:%?-]+)/dc/xml/$', web_view.item_detail,
+ {'format': 'dublin_core_xml'},
+ name="telemeta-item-dublincore-xml"),
+ url(r'^items/(?P<item_id>[0-9A-Z._:%?-]+)/download/(?P<format>[0-9A-Z]+)/$',
web_view.item_export,
name="telemeta-item-export"),
- url(r'^items/(?P<item_id>[0-9A-Z._:-]+)/visualize/(?P<visualizer_id>[0-9a-z]+)/$',
+ url(r'^items/(?P<item_id>[0-9A-Z._:%?-]+)/visualize/(?P<visualizer_id>[0-9a-z]+)/$',
web_view.item_visualize,
name="telemeta-item-visualize"),
url(r'^collections/?page=(?P<page>[0-9]+)$',
'django.views.generic.list_detail.object_list',
dict(all_collections, paginate_by=20)),
- url(r'^collections/(?P<object_id>[0-9A-Z._-]+)/$',
+ url(r'^collections/(?P<object_id>[0-9A-Z._%?-]+)/$',
'django.views.generic.list_detail.object_detail',
dict(all_collections, template_name="collection_detail.html"),
name="telemeta-collection-detail"),
+ url(r'^collections/(?P<object_id>[0-9A-Z._%?-]+)/dc/$',
+ 'django.views.generic.list_detail.object_detail',
+ dict(all_collections, template_name="collection_detail_dc.html"),
+ name="telemeta-collection-dublincore"),
# search
url(r'^search/$', web_view.quick_search, name="telemeta-quicksearch"),
context = Context({})
return HttpResponse(template.render(context))
- def item_detail(self, request, item_id):
+ def item_detail(self, request, item_id, template='mediaitem_detail.html'):
"""Show the details of a given item"""
item = MediaItem.objects.get(pk=item_id)
formats = []
visualizer_id = request.REQUEST['visualizer_id']
else:
visualizer_id = 'waveform'
- return render_to_response('mediaitem_detail.html',
+
+ return render_to_response(template,
{'item': item, 'export_formats': formats,
'visualizers': visualizers, 'visualizer_id': visualizer_id})
response = HttpResponse(stream, mimetype = 'image/png')
return response
-
- def __file_stream(self, filepath):
- """Generator for streaming a file from the disk.
-
- This method shouldn't be needed anymore when bug #8 get fixed
- """
-
- 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):
"""Export a given media item in the specified format (OGG, FLAC, ...)"""
for exporter in self.exporters:
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']
-
- stream = exporter.process(item.id, infile, metadata, [])
+ metadata = item.to_dublincore().flatten()
+ stream = exporter.process(item.id, infile, metadata)
- response = HttpResponse(self.__file_stream(outfile),mimetype=mime_type)
- #response = HttpResponse(stream, mimetype = mime_type)
+ response = HttpResponse(stream, mimetype = mime_type)
response['Content-Disposition'] = 'attachment; filename="download.' + \
exporter.get_file_extension() + '"'
return response