source: telemeta/web/base.py @ 5889b86

cremcrem2devdev2diademsfeature/breadcrumbsfeature/ts-0.5feature/ts-0.5.4feature/writecacheformagenericinstru_searchlamlam2mapsv3mergenlivemultiproductionrelease/1.4.4sabiodsecurityserversocialstoragetelecastertestvideo
Last change on this file since 5889b86 was 5889b86, checked in by olivier <>, 5 years ago

reduce geo navigator loading time, counting related resources on demand ; display both collections and items count in gmap info boxes

  • Property mode set to 100644
File size: 15.4 KB
Line 
1# -*- coding: utf-8 -*-
2# Copyright (C) 2007 Samalyse SARL
3
4# This software is a computer program whose purpose is to backup, analyse,
5# transcode and stream any audio content with its metadata over a web frontend.
6
7# This software is governed by the CeCILL  license under French law and
8# abiding by the rules of distribution of free software.  You can  use,
9# modify and/ or redistribute the software under the terms of the CeCILL
10# license as circulated by CEA, CNRS and INRIA at the following URL
11# "http://www.cecill.info".
12
13# As a counterpart to the access to the source code and  rights to copy,
14# modify and redistribute granted by the license, users are provided only
15# with a limited warranty  and the software's author,  the holder of the
16# economic rights,  and the successive licensors  have only  limited
17# liability.
18
19# In this respect, the user's attention is drawn to the risks associated
20# with loading,  using,  modifying and/or developing or reproducing the
21# software by the user in light of its specific status of free software,
22# that may mean  that it is complicated to manipulate,  and  that  also
23# therefore means  that it is reserved for developers  and  experienced
24# professionals having in-depth computer knowledge. Users are therefore
25# encouraged to load and test the software's suitability as regards their
26# requirements in conditions enabling the security of their systems and/or
27# data to be ensured and,  more generally, to use and operate it in the
28# same conditions as regards security.
29
30# The fact that you are presently reading this means that you have had
31# knowledge of the CeCILL license and that you accept its terms.
32
33# Author: Olivier Guilyardi <olivier@samalyse.com>
34
35import re
36import os
37import sys
38
39from django.template import Context, loader
40from django import template
41from django.http import HttpResponse
42from django.http import Http404
43from django.shortcuts import render_to_response
44from django.views.generic import list_detail
45from django.conf import settings
46
47import telemeta
48from telemeta.models import MediaItem, Location, MediaCollection
49from telemeta.core import Component, ExtensionPoint
50from telemeta.export import *
51from telemeta.visualization import *
52from telemeta.analysis import *
53from telemeta.analysis.vamp import *
54import telemeta.interop.oai as oai
55from telemeta.interop.oaidatasource import TelemetaOAIDataSource
56from django.core.exceptions import ObjectDoesNotExist
57from telemeta.util.unaccent import unaccent
58
59class WebView(Component):
60    """Provide web UI methods"""
61
62    exporters = ExtensionPoint(IExporter)
63    visualizers = ExtensionPoint(IMediaItemVisualizer)
64    analyzers = ExtensionPoint(IMediaItemAnalyzer)
65
66    def index(self, request):
67        """Render the homepage"""
68
69        template = loader.get_template('telemeta/index.html')
70        context = Context({})
71        return HttpResponse(template.render(context))
72
73    def collection_detail(self, request, public_id, template=''):
74        collection = MediaCollection.objects.get(public_id=public_id)
75        return render_to_response(template, {'collection': collection})
76
77
78    def item_detail(self, request, public_id, template='telemeta/mediaitem_detail.html'):
79        """Show the details of a given item"""
80        item = MediaItem.objects.get(public_id=public_id)
81       
82        formats = []
83        for exporter in self.exporters:
84            formats.append({'name': exporter.get_format(), 'extension': exporter.get_file_extension()})
85
86        visualizers = []
87        for visualizer in self.visualizers:
88            visualizers.append({'name':visualizer.get_name(), 'id':
89                visualizer.get_id()})
90        if request.REQUEST.has_key('visualizer_id'):
91            visualizer_id = request.REQUEST['visualizer_id']
92        else:
93            visualizer_id = 'waveform_audiolab'
94
95        analyzers = []
96        for analyzer in self.analyzers:
97            if item.file:
98                value = analyzer.render(item)
99            else:
100                value = 'N/A'
101
102            analyzers.append({'name':analyzer.get_name(),
103                              'id':analyzer.get_id(),
104                              'unit':analyzer.get_unit(),
105                              'value':str(value)})
106
107        vamp = VampCoreAnalyzer()
108        vamp_plugins = vamp.get_plugins_list()
109        vamp_plugin_list = []
110        for plugin in vamp_plugins:
111            vamp_plugin_list.append(':'.join(plugin[1:]))
112         
113        return render_to_response(template, 
114                    {'item': item, 'export_formats': formats, 
115                    'visualizers': visualizers, 'visualizer_id': visualizer_id,
116                    'analysers': analyzers, 'vamp_plugins': vamp_plugin_list})
117                   
118    def item_visualize(self, request, public_id, visualizer_id, width, height):
119        for visualizer in self.visualizers:
120            if visualizer.get_id() == visualizer_id:
121                break
122
123        if visualizer.get_id() != visualizer_id:
124            raise Http404
125       
126        item = MediaItem.objects.get(public_id=public_id)
127
128        visualizer.set_colors((255,255,255), 'purple')
129        stream = visualizer.render(item, width=int(width), height=int(height))
130        response = HttpResponse(stream, mimetype = 'image/png')
131        return response
132
133    def list_export_extensions(self):
134        "Return the recognized item export file extensions, as a list"
135        list = []
136        for exporter in self.exporters:
137            list.append(exporter.get_file_extension())
138        return list
139
140    def item_export(self, request, public_id, extension):                   
141        """Export a given media item in the specified format (OGG, FLAC, ...)"""
142        for exporter in self.exporters:
143            if exporter.get_file_extension() == extension:
144                break
145
146        if exporter.get_file_extension() != extension:
147            raise Http404('Unknown export file extension: %s' % extension)
148
149        mime_type = exporter.get_mime_type()
150
151        exporter.set_cache_dir(settings.TELEMETA_EXPORT_CACHE_DIR)
152
153        item = MediaItem.objects.get(public_id=public_id)
154
155        infile = item.file.path
156        metadata = item.to_dublincore().flatten()
157        stream = exporter.process(item.id, infile, metadata)
158
159        response = HttpResponse(stream, mimetype = mime_type)
160        response['Content-Disposition'] = 'attachment'
161        return response
162
163    def edit_search(self, request):
164        continents = MediaCollection.objects.list_continents()
165        countries = MediaCollection.objects.list_countries()
166        ethnic_groups = MediaItem.objects.list_ethnic_groups()
167        return render_to_response('telemeta/search_criteria.html', 
168            {'continents': continents, 'countries': countries, 
169            'ethnic_groups': ethnic_groups})
170
171    def search(self, request, type = None):
172        """Perform a search through collections and items metadata"""
173        collections = MediaCollection.objects.all()
174        items = MediaItem.objects.all()
175        input = request.REQUEST
176        criteria = {}
177
178        switch = {
179            'pattern': lambda value: ( 
180                collections.quick_search(value), 
181                items.quick_search(value)),
182            'title': lambda value: (
183                collections.word_search('title', value), 
184                items.by_title(value)),
185            'country': lambda value: (
186                collections.by_country(value), 
187                items.filter(etat = value)),
188            'continent': lambda value: (
189                collections.by_continent(value), 
190                items.filter(continent = value)),
191            'ethnic_group': lambda value: (
192                collections.by_ethnic_group(value), 
193                items.filter(ethnie_grsocial = value)),
194            'creator': lambda value: (
195                collections.word_search('creator', value),
196                items.word_search('auteur', value)),
197            'rec_date': lambda value: (
198                collections.by_recording_date(value), 
199                items.by_recording_date(value)),
200            'pub_date': lambda value: (
201                collections.by_publish_date(value), 
202                items.by_publish_date(value))
203        }
204       
205        for key, value in input.items():
206            if key == 'continent' and input.get('country'):
207                continue
208            func = switch.get(key)
209            if func and value:
210                collections, items = func(value)
211                criteria[key] = value
212
213        if type is None:
214            if collections.count() and not items.count():
215                type = 'collections'
216            else:
217                type = 'items'
218
219        if type == 'items':
220            objects = items
221        else:
222            objects = collections
223
224        return list_detail.object_list(request, objects, 
225            template_name='telemeta/search_results.html', paginate_by=20,
226            extra_context={'criteria': criteria, 'collections_num': collections.count(), 
227                'items_num': items.count(), 'type' : type})
228
229    def __get_enumerations_list(self):
230        from django.db.models import get_models
231        models = get_models(telemeta.models)
232
233        enumerations = []
234        for model in models:
235            if getattr(model, "is_enumeration", False):
236                enumerations.append({"name": model._meta.verbose_name_plural, 
237                    "id": model._meta.module_name})
238        return enumerations                   
239   
240    def __get_admin_context_vars(self):
241        return {"enumerations": self.__get_enumerations_list()}
242
243    def admin_index(self, request):
244        return render_to_response('telemeta/admin.html', self. __get_admin_context_vars())
245
246    def __get_enumeration(self, id):
247        from django.db.models import get_models
248        models = get_models(telemeta.models)
249        for model in models:
250            if model._meta.module_name == id:
251                break
252
253        if model._meta.module_name != id:
254            return None
255
256        return model
257
258    def edit_enumeration(self, request, enumeration_id):       
259
260        enumeration  = self.__get_enumeration(enumeration_id)
261        if enumeration == None:
262            raise Http404
263
264        vars = self.__get_admin_context_vars()
265        vars["enumeration_id"] = enumeration._meta.module_name
266        vars["enumeration_name"] = enumeration._meta.verbose_name           
267        vars["enumeration_name_plural"] = enumeration._meta.verbose_name_plural
268        vars["enumeration_values"] = enumeration.objects.all()
269        return render_to_response('telemeta/enumeration_edit.html', vars)
270
271    def add_to_enumeration(self, request, enumeration_id):       
272
273        enumeration  = self.__get_enumeration(enumeration_id)
274        if enumeration == None:
275            raise Http404
276
277        enumeration_value = enumeration(value=request.POST['value'])
278        enumeration_value.save()
279
280        return self.edit_enumeration(request, enumeration_id)
281
282    def update_enumeration(self, request, enumeration_id):       
283       
284        enumeration  = self.__get_enumeration(enumeration_id)
285        if enumeration == None:
286            raise Http404
287
288        if request.POST.has_key("remove"):
289            enumeration.objects.filter(id__in=request.POST.getlist('sel')).delete()
290
291        return self.edit_enumeration(request, enumeration_id)
292
293    def edit_enumeration_value(self, request, enumeration_id, value_id):       
294
295        enumeration  = self.__get_enumeration(enumeration_id)
296        if enumeration == None:
297            raise Http404
298       
299        vars = self.__get_admin_context_vars()
300        vars["enumeration_id"] = enumeration._meta.module_name
301        vars["enumeration_name"] = enumeration._meta.verbose_name           
302        vars["enumeration_name_plural"] = enumeration._meta.verbose_name_plural
303        vars["enumeration_record"] = enumeration.objects.get(id__exact=value_id)
304        return render_to_response('telemeta/enumeration_edit_value.html', vars)
305
306    def update_enumeration_value(self, request, enumeration_id, value_id):       
307
308        if request.POST.has_key("save"):
309            enumeration  = self.__get_enumeration(enumeration_id)
310            if enumeration == None:
311                raise Http404
312       
313            record = enumeration.objects.get(id__exact=value_id)
314            record.value = request.POST["value"]
315            record.save()
316
317        return self.edit_enumeration(request, enumeration_id)
318 
319    def collection_playlist(self, request, public_id, template, mimetype):
320        try:
321            collection = MediaCollection.objects.get(public_id=public_id)
322        except ObjectDoesNotExist:
323            raise Http404
324
325        template = loader.get_template(template)
326        context = Context({'collection': collection, 'host': request.META['HTTP_HOST']})
327        return HttpResponse(template.render(context), mimetype=mimetype)
328
329    def item_playlist(self, request, public_id, template, mimetype):
330        try:
331            item = MediaItem.objects.get(public_id=public_id)
332        except ObjectDoesNotExist:
333            raise Http404
334
335        template = loader.get_template(template)
336        context = Context({'item': item, 'host': request.META['HTTP_HOST']})
337        return HttpResponse(template.render(context), mimetype=mimetype)
338
339    def list_continents(self, request):
340        continents = MediaItem.objects.all().countries(group_by_continent=True)
341        return render_to_response('telemeta/geo_continents.html', 
342                    {'continents': continents, 'gmap_key': settings.TELEMETA_GMAP_KEY })
343
344    def country_info(self, request, id):
345        country = Location.objects.get(pk=id)
346        return render_to_response('telemeta/country_info.html', {
347            'country': country, 'continent': country.continents()[0]})
348
349    def get_continents_js(self, request):
350        countries = MediaCollection.objects.list_countries()
351        return render_to_response('telemeta/geo_continents.js', 
352                    {'countries': countries})
353
354    def list_countries(self, request, continent):                   
355        continent = Location.objects.by_flatname(continent)[0]
356        data = MediaCollection.objects.stat_continents(only_continent=continent)
357
358        return render_to_response('telemeta/geo_countries.html', {'continent': data[0] })
359
360    def list_country_collections(self, request, continent, country):
361        continent = Location.objects.by_flatname(continent)[0]
362        country = Location.objects.by_flatname(country)[0]
363        objects = MediaCollection.objects.by_location(country)
364        return list_detail.object_list(request, objects, 
365            template_name='telemeta/geo_country_collections.html', paginate_by=20,
366            extra_context={'country': country, 'continent': continent})
367
368    def list_country_items(self, request, continent, country):
369        continent = Location.objects.by_flatname(continent)[0]
370        country = Location.objects.by_flatname(country)[0]
371        objects = MediaItem.objects.by_location(country)
372        return list_detail.object_list(request, objects, 
373            template_name='telemeta/geo_country_items.html', paginate_by=20,
374            extra_context={'country': country, 'continent': continent})
375
376    def handle_oai_request(self, request):
377        url         = 'http://' + request.META['HTTP_HOST'] + request.path
378        datasource  = TelemetaOAIDataSource()
379        admin       = settings.ADMINS[0][1]
380        provider    = oai.DataProvider(datasource, "Telemeta", url, admin)
381        args        = request.GET.copy()
382        args.update(request.POST)
383        return HttpResponse(provider.handle(args), mimetype='text/xml')
384       
385
Note: See TracBrowser for help on using the repository browser.