From e634d6be86ff68af294ff726dc3fffbeb3711aaa Mon Sep 17 00:00:00 2001 From: olivier <> Date: Tue, 1 May 2007 14:45:31 +0000 Subject: [PATCH] * Created new administration interface. BEWARE: update your site urls (in urls.py), telemeta now provides an internal "admin/" url, that may conflict with django's admin. * Implemented edition of generic "dictionaries" (or "enumerations"). These are the linked tables that contained various predefined values, used in collections, items and/or parts * added "physical format" dictionary (collection field and linked table), see EthnomusDatabase * misc cleanup --- telemeta/models.py | 11 +- telemeta/templates/admin.html | 37 ++++++ telemeta/templates/base.html | 20 ++- telemeta/templates/dictionary_edit.html | 48 +++++++ telemeta/templates/dictionary_edit_value.html | 22 +++ telemeta/templates/dictionary_list.html | 14 ++ telemeta/urls.py | 29 +++- telemeta/views/web.py | 125 +++++++++++++++--- 8 files changed, 276 insertions(+), 30 deletions(-) create mode 100644 telemeta/templates/admin.html create mode 100644 telemeta/templates/dictionary_edit.html create mode 100644 telemeta/templates/dictionary_edit_value.html create mode 100644 telemeta/templates/dictionary_list.html diff --git a/telemeta/models.py b/telemeta/models.py index 0a3b893d..7c6d8995 100644 --- a/telemeta/models.py +++ b/telemeta/models.py @@ -19,6 +19,14 @@ class MediaCore: fields_dict[field.name] = getattr(self, field.name) return fields_dict +class PhysicalFormat(models.Model): + value = models.CharField(maxlength=250) + is_dictionary = True + def __str__(self): + return self.value + class Meta: + ordering = ['value'] + class MediaCollectionManager(models.Manager): def quick_search(self, pattern): return super(MediaCollectionManager, self).get_query_set().filter( @@ -26,6 +34,7 @@ class MediaCollectionManager(models.Manager): Q(description__icontains=pattern) ) + class MediaCollection(models.Model, MediaCore): "Group related media items" @@ -42,6 +51,7 @@ class MediaCollection(models.Model, MediaCore): 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() @@ -131,4 +141,3 @@ class MediaPart(models.Model, MediaCore): class Admin: pass - diff --git a/telemeta/templates/admin.html b/telemeta/templates/admin.html new file mode 100644 index 00000000..e335b3cf --- /dev/null +++ b/telemeta/templates/admin.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% block extra_style %} + +{% endblock %} + +{% block content %} +

Administration

+
+ +
+
+ {% block tabcontents %} + + + + + + {% endblock %} +
+{% endblock %} diff --git a/telemeta/templates/base.html b/telemeta/templates/base.html index 0c4f6335..9fb41880 100644 --- a/telemeta/templates/base.html +++ b/telemeta/templates/base.html @@ -1,9 +1,19 @@ - - + + + +Telemeta + +{% block extra_style %}{% endblock %} + +{% load i18n %} - + +
{% block content %}{% endblock %} +
diff --git a/telemeta/templates/dictionary_edit.html b/telemeta/templates/dictionary_edit.html new file mode 100644 index 00000000..e5a7b3a4 --- /dev/null +++ b/telemeta/templates/dictionary_edit.html @@ -0,0 +1,48 @@ +{% extends "admin.html" %} + +{% block tabcontents %} +

Manage {{ dictionary_name_plural|capfirst }}

+ + + +
+
+ Add {{ dictionary_name|capfirst }} +
+ + +
+
+ +
+
+
+ {% if dictionary_values %} +
+ + + + + + + {% for record in dictionary_values %} + + + + + {% endfor %} + +
 Value
+ {{record.value}}
+
+ +
+
+ {% else %} +

This dictionary is empty.

+ {% endif %} + +
+ +{% endblock %} diff --git a/telemeta/templates/dictionary_edit_value.html b/telemeta/templates/dictionary_edit_value.html new file mode 100644 index 00000000..0f205c69 --- /dev/null +++ b/telemeta/templates/dictionary_edit_value.html @@ -0,0 +1,22 @@ +{% extends "admin.html" %} + +{% block tabcontents %} +

Manage {{ dictionary_name_plural|capfirst }}

+ +
+
+ Modify {{ dictionary_name|capfirst }} +
+ + +
+
+ + +
+
+
+
+ +{% endblock %} diff --git a/telemeta/templates/dictionary_list.html b/telemeta/templates/dictionary_list.html new file mode 100644 index 00000000..bc780f8c --- /dev/null +++ b/telemeta/templates/dictionary_list.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block content %} +

Dictionaries

+{% if dictionaries %} + +{% else %} +

No dictionary.

+{% endif %} +{% endblock %} diff --git a/telemeta/urls.py b/telemeta/urls.py index 09b36cbc..f08699cb 100644 --- a/telemeta/urls.py +++ b/telemeta/urls.py @@ -1,5 +1,10 @@ from django.conf.urls.defaults import * from telemeta.models import MediaItem, MediaCollection +from telemeta.core import ComponentManager +from telemeta.views.web import WebView + +comp_mgr = ComponentManager() +web_view = WebView(comp_mgr) all_items = { 'queryset': MediaItem.objects.all(), @@ -10,12 +15,12 @@ all_collections = { } urlpatterns = patterns('', - (r'^$', 'telemeta.views.web.index'), + (r'^$', web_view.index), (r'^items/$', 'django.views.generic.list_detail.object_list', dict(all_items, paginate_by=10, template_name="mediaitem_list.html")), - (r'^items/(?P[0-9]+)/$', 'telemeta.views.web.item_detail'), + (r'^items/(?P[0-9]+)/$', web_view.item_detail), (r'^items/(?P[0-9]+)/download/(?P[0-9A-Z]+)/$', - 'telemeta.views.web.item_export'), + web_view.item_export), #(r'^media_item/(?P[0-9]+)/$', 'telemeta.views.web.media_item_edit'), (r'^media_item/(?P[0-9]+)/update/$', 'telemeta.views.web.media_item_update'), @@ -24,13 +29,23 @@ urlpatterns = patterns('', (r'^collections/(?P[0-9]+)/$', 'django.views.generic.list_detail.object_detail', dict(all_collections, template_name="collection_detail.html")), + #(r'^dictionaries/$', web_view.dictionary_list), + (r'^admin/$', web_view.admin_index), + (r'^admin/dictionaries/(?P[0-9a-z]+)/$', web_view.edit_dictionary), + (r'^admin/dictionaries/(?P[0-9a-z]+)/add/$', web_view.add_to_dictionary), + (r'^admin/dictionaries/(?P[0-9a-z]+)/update/$', web_view.update_dictionary), + (r'^admin/dictionaries/(?P[0-9a-z]+)/(?P[0-9]+)/$', + web_view.edit_dictionary_value), + + (r'^admin/dictionaries/(?P[0-9a-z]+)/(?P[0-9]+)/update/$', + web_view.update_dictionary_value), - (r'^search/$', - 'telemeta.views.web.quick_search'), + (r'^search/$', web_view.quick_search), - # CSS (FIXME: for developement only) - (r'^css/(?P.*)$', 'django.views.static.serve', {'document_root': './telemeta/css'}), + # CSS+Images (FIXME: for developement only) + (r'^css/(?P.*)$', 'django.views.static.serve', {'document_root': './telemeta/htdocs/css'}), + (r'^images/(?P.*)$', 'django.views.static.serve', {'document_root': './telemeta/htdocs/images'}), ) diff --git a/telemeta/views/web.py b/telemeta/views/web.py index 7b733db0..a23cedc7 100644 --- a/telemeta/views/web.py +++ b/telemeta/views/web.py @@ -8,26 +8,24 @@ from telemeta.models import MediaCollection 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" - - media_items = MediaItem.objects.all() - template = loader.get_template('index.html') - context = Context({ - 'media_items' : media_items, - }) - return HttpResponse(template.render(context)) - class WebView(Component): + """Provide web UI methods""" exporters = ExtensionPoint(IExporter) + def index(self, request): + """Render the homepage""" + + template = loader.get_template('index.html') + context = Context({}) + return HttpResponse(template.render(context)) + def item_detail(self, request, item_id): + """Show the details of a given item""" item = MediaItem.objects.get(pk=item_id) formats = [] for exporter in self.exporters: @@ -35,7 +33,12 @@ class WebView(Component): return render_to_response('mediaitem_detail.html', {'item': item, 'export_formats': formats}) - def file_stream(self, filepath): + 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) @@ -46,6 +49,7 @@ class WebView(Component): 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: if exporter.get_format() == format: break @@ -68,12 +72,13 @@ class WebView(Component): outfile = exporter.process(item.id, infile, metadata, []) - response = HttpResponse(self.file_stream(outfile), mimetype = mime_type) + response = HttpResponse(self.__file_stream(outfile), mimetype = mime_type) response['Content-Disposition'] = 'attachment; filename="download.' + \ exporter.get_file_extension() + '"' return response def quick_search(self, request): + """Perform a simple search through collections and items core metadata""" pattern = request.REQUEST["pattern"] collections = MediaCollection.objects.quick_search(pattern) items = MediaItem.objects.quick_search(pattern) @@ -81,14 +86,98 @@ class WebView(Component): {'pattern': pattern, 'collections': collections, 'items': items}) + def __get_dictionary_list(self): + from django.db.models import get_models + models = get_models(telemeta.models) + + dictionaries = [] + for model in models: + if getattr(model, "is_dictionary", False): + dictionaries.append({"name": model._meta.verbose_name_plural, + "id": model._meta.module_name}) + return dictionaries + + def __get_admin_context_vars(self): + return {"dictionaries": self.__get_dictionary_list()} + + def admin_index(self, request): + return render_to_response('admin.html', self. __get_admin_context_vars()) + + def __get_dictionary(self, id): + from django.db.models import get_models + models = get_models(telemeta.models) + for model in models: + if model._meta.module_name == id: + break + + if model._meta.module_name != id: + return None + + return model -comp_mgr = ComponentManager() -view = WebView(comp_mgr) -item_detail = view.item_detail -item_export = view.item_export -quick_search = view.quick_search + def edit_dictionary(self, request, dictionary_id): + + dictionary = self.__get_dictionary(dictionary_id) + if dictionary == None: + raise Http404 + + vars = self.__get_admin_context_vars() + vars["dictionary_id"] = dictionary._meta.module_name + vars["dictionary_name"] = dictionary._meta.verbose_name + vars["dictionary_name_plural"] = dictionary._meta.verbose_name_plural + vars["dictionary_values"] = dictionary.objects.all() + return render_to_response('dictionary_edit.html', vars) + def add_to_dictionary(self, request, dictionary_id): + + dictionary = self.__get_dictionary(dictionary_id) + if dictionary == None: + raise Http404 + + dictionary_value = dictionary(value=request.POST['value']) + dictionary_value.save() + + return self.edit_dictionary(request, dictionary_id) + + def update_dictionary(self, request, dictionary_id): + + dictionary = self.__get_dictionary(dictionary_id) + if dictionary == None: + raise Http404 + + if request.POST.has_key("remove"): + dictionary.objects.filter(id__in=request.POST['sel']).delete() + + return self.edit_dictionary(request, dictionary_id) + + def edit_dictionary_value(self, request, dictionary_id, value_id): + + dictionary = self.__get_dictionary(dictionary_id) + if dictionary == None: + raise Http404 + + vars = self.__get_admin_context_vars() + vars["dictionary_id"] = dictionary._meta.module_name + vars["dictionary_name"] = dictionary._meta.verbose_name + vars["dictionary_name_plural"] = dictionary._meta.verbose_name_plural + vars["dictionary_record"] = dictionary.objects.get(id__exact=value_id) + return render_to_response('dictionary_edit_value.html', vars) + + def update_dictionary_value(self, request, dictionary_id, value_id): + + if request.POST.has_key("save"): + dictionary = self.__get_dictionary(dictionary_id) + if dictionary == None: + raise Http404 + + record = dictionary.objects.get(id__exact=value_id) + record.value = request.POST["value"] + record.save() + + return self.edit_dictionary(request, dictionary_id) + + def media_item_edit(request, media_item_id): "Provide MediaItem object edition" -- 2.39.5