source: telemeta/web/base.py @ c1a2c1c

cremcrem2devdev2diademsdj1.6feature/breadcrumbsfeature/ts-0.5feature/ts-0.5.4feature/writecacheformagenericinstru_searchlamlam2mapsv3mergenlivemultiproductionrelease/1.4.4sabiodsecurityserversocialstoragetelecastertestvideo
Last change on this file since c1a2c1c was c1a2c1c, checked in by olivier <>, 5 years ago

add autocompleted location input field to advanced search

  • Property mode set to 100644
File size: 15.6 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        ethnic_groups = MediaItem.objects.all().ethnic_groups()
165        return render_to_response('telemeta/search_criteria.html', 
166            {'ethnic_groups': ethnic_groups})
167
168    def complete_location(self, request, with_items=True):
169        input = request.REQUEST
170       
171        token = input['q']
172        limit = int(input['limit'])
173        if with_items:
174            locations = MediaItem.objects.all().locations()
175        else:
176            locations = Location.objects.all()
177
178        locations = locations.filter(name__istartswith=token).order_by('name')[:limit]
179        data = [unicode(l) + " (%d items)" % l.items().count() for l in locations]
180
181        return HttpResponse("\n".join(data))
182
183    def search(self, request, type = None):
184        """Perform a search through collections and items metadata"""
185        collections = MediaCollection.objects.enriched()
186        items = MediaItem.objects.enriched()
187        input = request.REQUEST
188        criteria = {}
189
190        switch = {
191            'pattern': lambda value: ( 
192                collections.quick_search(value), 
193                items.quick_search(value)),
194            'title': lambda value: (
195                collections.word_search('title', value), 
196                items.by_title(value)),
197            'location': lambda value: (
198                collections.by_location(Location.objects.get(name=value)), 
199                items.by_location(Location.objects.get(name=value))),
200            'continent': lambda value: (
201                collections.by_continent(value), 
202                items.filter(continent = value)),
203            'ethnic_group': lambda value: (
204                collections.by_ethnic_group(value), 
205                items.filter(ethnie_grsocial = value)),
206            'creator': lambda value: (
207                collections.word_search('creator', value),
208                items.word_search('auteur', value)),
209            'rec_date': lambda value: (
210                collections.by_recording_date(value), 
211                items.by_recording_date(value)),
212            'pub_date': lambda value: (
213                collections.by_publish_date(value), 
214                items.by_publish_date(value))
215        }
216       
217        for key, value in input.items():
218            if key == 'continent' and input.get('country'):
219                continue
220            func = switch.get(key)
221            if func and value:
222                collections, items = func(value)
223                criteria[key] = value
224
225        if type is None:
226            if collections.count() and not items.count():
227                type = 'collections'
228            else:
229                type = 'items'
230
231        if type == 'items':
232            objects = items
233        else:
234            objects = collections
235
236        return list_detail.object_list(request, objects, 
237            template_name='telemeta/search_results.html', paginate_by=20,
238            extra_context={'criteria': criteria, 'collections_num': collections.count(), 
239                'items_num': items.count(), 'type' : type})
240
241    def __get_enumerations_list(self):
242        from django.db.models import get_models
243        models = get_models(telemeta.models)
244
245        enumerations = []
246        for model in models:
247            if getattr(model, "is_enumeration", False):
248                enumerations.append({"name": model._meta.verbose_name_plural, 
249                    "id": model._meta.module_name})
250        return enumerations                   
251   
252    def __get_admin_context_vars(self):
253        return {"enumerations": self.__get_enumerations_list()}
254
255    def admin_index(self, request):
256        return render_to_response('telemeta/admin.html', self. __get_admin_context_vars())
257
258    def __get_enumeration(self, id):
259        from django.db.models import get_models
260        models = get_models(telemeta.models)
261        for model in models:
262            if model._meta.module_name == id:
263                break
264
265        if model._meta.module_name != id:
266            return None
267
268        return model
269
270    def edit_enumeration(self, request, enumeration_id):       
271
272        enumeration  = self.__get_enumeration(enumeration_id)
273        if enumeration == None:
274            raise Http404
275
276        vars = self.__get_admin_context_vars()
277        vars["enumeration_id"] = enumeration._meta.module_name
278        vars["enumeration_name"] = enumeration._meta.verbose_name           
279        vars["enumeration_name_plural"] = enumeration._meta.verbose_name_plural
280        vars["enumeration_values"] = enumeration.objects.all()
281        return render_to_response('telemeta/enumeration_edit.html', vars)
282
283    def add_to_enumeration(self, request, enumeration_id):       
284
285        enumeration  = self.__get_enumeration(enumeration_id)
286        if enumeration == None:
287            raise Http404
288
289        enumeration_value = enumeration(value=request.POST['value'])
290        enumeration_value.save()
291
292        return self.edit_enumeration(request, enumeration_id)
293
294    def update_enumeration(self, request, enumeration_id):       
295       
296        enumeration  = self.__get_enumeration(enumeration_id)
297        if enumeration == None:
298            raise Http404
299
300        if request.POST.has_key("remove"):
301            enumeration.objects.filter(id__in=request.POST.getlist('sel')).delete()
302
303        return self.edit_enumeration(request, enumeration_id)
304
305    def edit_enumeration_value(self, request, enumeration_id, value_id):       
306
307        enumeration  = self.__get_enumeration(enumeration_id)
308        if enumeration == None:
309            raise Http404
310       
311        vars = self.__get_admin_context_vars()
312        vars["enumeration_id"] = enumeration._meta.module_name
313        vars["enumeration_name"] = enumeration._meta.verbose_name           
314        vars["enumeration_name_plural"] = enumeration._meta.verbose_name_plural
315        vars["enumeration_record"] = enumeration.objects.get(id__exact=value_id)
316        return render_to_response('telemeta/enumeration_edit_value.html', vars)
317
318    def update_enumeration_value(self, request, enumeration_id, value_id):       
319
320        if request.POST.has_key("save"):
321            enumeration  = self.__get_enumeration(enumeration_id)
322            if enumeration == None:
323                raise Http404
324       
325            record = enumeration.objects.get(id__exact=value_id)
326            record.value = request.POST["value"]
327            record.save()
328
329        return self.edit_enumeration(request, enumeration_id)
330 
331    def collection_playlist(self, request, public_id, template, mimetype):
332        try:
333            collection = MediaCollection.objects.get(public_id=public_id)
334        except ObjectDoesNotExist:
335            raise Http404
336
337        template = loader.get_template(template)
338        context = Context({'collection': collection, 'host': request.META['HTTP_HOST']})
339        return HttpResponse(template.render(context), mimetype=mimetype)
340
341    def item_playlist(self, request, public_id, template, mimetype):
342        try:
343            item = MediaItem.objects.get(public_id=public_id)
344        except ObjectDoesNotExist:
345            raise Http404
346
347        template = loader.get_template(template)
348        context = Context({'item': item, 'host': request.META['HTTP_HOST']})
349        return HttpResponse(template.render(context), mimetype=mimetype)
350
351    def list_continents(self, request):
352        continents = MediaItem.objects.all().countries(group_by_continent=True)
353        return render_to_response('telemeta/geo_continents.html', 
354                    {'continents': continents, 'gmap_key': settings.TELEMETA_GMAP_KEY })
355
356    def country_info(self, request, id):
357        country = Location.objects.get(pk=id)
358        return render_to_response('telemeta/country_info.html', {
359            'country': country, 'continent': country.continents()[0]})
360
361    def list_countries(self, request, continent):                   
362        continent = Location.objects.by_flatname(continent)[0]
363        data = MediaCollection.objects.stat_continents(only_continent=continent)
364
365        return render_to_response('telemeta/geo_countries.html', {'continent': data[0] })
366
367    def list_country_collections(self, request, continent, country):
368        continent = Location.objects.by_flatname(continent)[0]
369        country = Location.objects.by_flatname(country)[0]
370        objects = MediaCollection.objects.enriched().by_location(country)
371        return list_detail.object_list(request, objects, 
372            template_name='telemeta/geo_country_collections.html', paginate_by=20,
373            extra_context={'country': country, 'continent': continent})
374
375    def list_country_items(self, request, continent, country):
376        continent = Location.objects.by_flatname(continent)[0]
377        country = Location.objects.by_flatname(country)[0]
378        objects = MediaItem.objects.enriched().by_location(country)
379        return list_detail.object_list(request, objects, 
380            template_name='telemeta/geo_country_items.html', paginate_by=20,
381            extra_context={'country': country, 'continent': continent})
382
383    def handle_oai_request(self, request):
384        url         = 'http://' + request.META['HTTP_HOST'] + request.path
385        datasource  = TelemetaOAIDataSource()
386        admin       = settings.ADMINS[0][1]
387        provider    = oai.DataProvider(datasource, "Telemeta", url, admin)
388        args        = request.GET.copy()
389        args.update(request.POST)
390        return HttpResponse(provider.handle(args), mimetype='text/xml')
391       
392
Note: See TracBrowser for help on using the repository browser.