diff -r 2f978b081c4c -r 9927a619d2b5 web/ldt/ldt_utils/views.py --- a/web/ldt/ldt_utils/views.py Thu Oct 14 12:17:31 2010 +0200 +++ b/web/ldt/ldt_utils/views.py Fri Oct 15 12:36:43 2010 +0200 @@ -1,32 +1,45 @@ -import django.core.urlresolvers -from django.http import HttpResponse, HttpResponseRedirect -from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404 +from contentindexer import * +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.core import serializers +from django.core.urlresolvers import reverse +from django.db.models import Q +from django.forms.util import ErrorList +from django.http import HttpResponse, HttpResponseRedirect, \ + HttpResponseForbidden, HttpResponseServerError +from django.shortcuts import render_to_response, get_object_or_404, \ + get_list_or_404 from django.template import RequestContext -from django.core.urlresolvers import reverse -from django.contrib.auth.decorators import login_required -from django.conf import settings -from django.core import serializers +from django.template.loader import render_to_string from django.utils import simplejson from django.utils.html import escape +from django.utils.translation import ugettext as _, ungettext from fileimport import * -from forms import LdtImportForm, LdtAddForm, SearchForm, AddProjectForm, CopyProjectForm, ContentForm, MediaForm +from forms import LdtImportForm, LdtAddForm, SearchForm, AddProjectForm, \ + CopyProjectForm, ContentForm, MediaForm from ldt.core.models import Owner +from ldt.ldt_utils.models import Content, Project, Owner +from ldt.ldt_utils.projectserializer import ProjectSerializer +from ldt.ldt_utils.utils import boolean_convert +from lxml import etree +from lxml.html import fromstring, fragment_fromstring from models import * -from utils import * -from contentindexer import * from projectserializer import * from string import Template +from urllib2 import urlparse +from utils import * +import StringIO +import base64 import cgi -import uuid -import base64 +import django.core.urlresolvers +import ldt.auth as ldt_auth +import ldt.utils.path as ldt_utils_path +import logging import lucene +import lxml.etree import tempfile import urllib2 -from urllib2 import urlparse -from jogging import logging -import lxml.etree -from django.db.models import Q -from django.template.loader import render_to_string +import uuid @login_required @@ -39,24 +52,36 @@ project_list = Project.objects.all() # render list - return render_to_response("ldt/workspace.html", + return render_to_response("ldt/ldt_utils/workspace.html", {'contents': content_list, 'projects': project_list}, context_instance=RequestContext(request)) + def popup_embed(request): json_url = request.GET.get("json_url") player_id = request.GET.get("player_id") + ldt_id = request.GET.get("ldt_id") - embed_rendered = escape(render_to_string('ldt/ldt_utils/embed.html', {'json_url':json_url,'player_id':player_id}, context_instance=RequestContext(request))) + project = Project.objects.get(ldt_id=ldt_id); + if not ldt_auth.checkAccess(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + + ps = ProjectSerializer(project, from_contents=False, from_display=True) + annotations = ps.getAnnotations(first_cutting=True) - return render_to_response("ldt/embed_popup.html", - {'json_url':json_url,'player_id':player_id, 'player_embed_rendered':embed_rendered}, + embed_rendered = dict((typestr, + (lambda s:escape(lxml.etree.tostring(fragment_fromstring(render_to_string("ldt/ldt_utils/partial/embed_%s.html"%(s), {'json_url':json_url,'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id}, context_instance=RequestContext(request))),pretty_print=True)))(typestr)) + for typestr in ('player','seo_body', 'seo_meta', 'links') ) + + return render_to_response("ldt/ldt_utils/embed_popup.html", + {'json_url':json_url,'player_id':player_id, 'embed_rendered':embed_rendered, 'annotations':annotations}, context_instance=RequestContext(request)) + @login_required def projectsfilter(request, filter, is_owner=False, status=0): @@ -76,34 +101,39 @@ if status > 0: query &= Q(state=status) - if filter and filter != "_": + if filter: + if len(filter) > 0 and filter[0] == '_': + filter = filter[1:] query &= Q(title__icontains=filter) project_list = Project.objects.filter(query) - return render_to_response("ldt/ldt_utils/projectslist.html", + return render_to_response("ldt/ldt_utils/partial/projectslist.html", {'projects': project_list}, context_instance=RequestContext(request)) + + + + @login_required def contentsfilter(request, filter): - if filter == "_": - filter = "" + if filter and len(filter) > 0 and filter[0] == '_': + filter = filter[1:] + if filter: content_list = Content.objects.filter(title__icontains=filter) else: content_list = Content.objects.all() - return render_to_response("ldt/ldt_utils/contentslist.html", + return render_to_response("ldt/ldt_utils/partial/contentslist.html", {'contents': content_list}, context_instance=RequestContext(request)) - - def searchForm(request): form = SearchForm() - return render_to_response('ldt/ldt_utils_utils/search_form.html',{'form': form} , context_instance=RequestContext(request)) + return render_to_response('ldt/ldt_utils/search_form.html',{'form': form} , context_instance=RequestContext(request)) def searchIndex(request): @@ -126,7 +156,7 @@ language_code = request.LANGUAGE_CODE[:2] url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.searchInit", args=[field, query]) - return render_to_response('irisuser/ldt/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) + return render_to_response('ldt/ldt_utils/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX+'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) def searchInit(request, field, query): @@ -230,11 +260,15 @@ if form.is_valid(): user = request.user Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents']) - return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt")) + form_status = "saved" + contents=[] + #return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt")) else: form = LdtAddForm() - contents = Content.objects.all() - return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form,'create_project_action':reverse(create_ldt_view)}, context_instance=RequestContext(request)) + contents = Content.objects.all() + form_status = "none" + + return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status,'create_project_action':reverse(create_ldt_view)}, context_instance=RequestContext(request)) def created_ldt(request): return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request)) @@ -261,7 +295,8 @@ resp = HttpResponse(mimetype="text/xml") resp['Cache-Control']='no-cache, must-revalidate' resp['Pragma']='no-cache' - doc.write(resp, pretty_print=True) + + resp.write( etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) return resp def ldtProject(request, id): @@ -278,19 +313,22 @@ project = get_object_or_404(Project,ldt_id=id) - return project_json(request, project) + return project_json(request, project, False) def project_json_externalid(request, id): res_proj = get_list_or_404(Project.objects.order_by('-modification_date'),contents__external_id = id) - return project_json(request, res_proj[0]) + return project_json(request, res_proj[0], False) -def project_json(request, project): - +def project_json(request, project, serialize_contents = True): + + if not ldt_auth.checkAccess(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + mimetype = request.REQUEST.get("mimetype") if mimetype is None: mimetype = "application/json; charset=utf-8" @@ -315,7 +353,7 @@ escape_bool = {'true': True, 'false': False, "0": False, "1": True}.get(escape_str.lower()) - ps = ProjectSerializer(project) + ps = ProjectSerializer(project, serialize_contents) project_dict = ps.serialize_to_cinelab() json_str = simplejson.dumps(project_dict, ensure_ascii=False, indent=indent) @@ -330,49 +368,96 @@ return resp +def project_annotations_rdf(request, ldt_id): + + project = Project.objects.get(ldt_id=ldt_id); + + if not ldt_auth.checkAccess(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + + mimetype = request.REQUEST.get("mimetype") + if mimetype is None: + mimetype = "application/rdf+xml; charset=utf-8" + else: + mimetype = mimetype.encode("utf-8") + if "charset" not in mimetype: + mimetype += "; charset=utf-8" + resp = HttpResponse(mimetype=mimetype) + resp['Cache-Control']='no-cache, must-revalidate' + resp['Pragma']='no-cache' + + ps = ProjectSerializer(project, from_content=False, from_display=True) + annotations = project.getAnnotations(first_cutting=True) + + rdf_ns = u"http://www.w3.org/1999/02/22-rdf-syntax-ns#" + dc_ns = u"http://purl.org/dc/elements/1.1/" + rdf = u"{%s}" % rdf_ns + dc = u"{%s}" % dc_ns + nsmap = {u'rdf' : rdf_ns, u'dc':dc_ns} + + rdf_root = etree.Element(rdf+u"RDF", nsmap=nsmap) + + logging.debug("RDF annotations : " + repr(annotations)) + + for annotation in annotations: + uri = u"" + if 'uri' in annotation and annotation['uri']: + uri = unicode(annotation['uri']) + annot_desc = etree.SubElement(rdf_root, rdf+u"Description") + annot_desc.set(rdf+u'about',uri) + if annotation['title']: + etree.SubElement(annot_desc, dc+'title').text = etree.CDATA(unicode(annotation['title'])) + if annotation['desc']: + etree.SubElement(annot_desc, dc+'description').text = etree.CDATA(unicode(annotation['desc'])) + if annotation['tags']: + for tag in annotation['tags']: + etree.SubElement(annot_desc, dc+'subject').text = etree.CDATA(unicode(tag)) + etree.SubElement(annot_desc,dc+'coverage').text = u"start=%s, duration=%s" % (annotation['begin'], annotation['duration']) + + resp.write(u"\n") + resp.write(u"\n") + + resp.write(etree.tostring(rdf_root, xml_declaration=False, encoding="utf-8", pretty_print=True)) + + return resp def save_ldtProject(request): if request.method=="POST": ldt = request.POST['ldt'] id = request.POST['id'] ldtproject=Project.objects.get(ldt_id=id) - - #save xml ldt + + #save xml ldt ldtproject.ldt=ldt - ldtproj = get_attrib(ldtproject) - ldtproj.save() - else: - ldt = '' - - return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':title, 'contents': new_contents}, context_instance=RequestContext(request)) - + doc = lxml.etree.fromstring(ldtproject.ldt.encode( "utf-8" )) + result = doc.xpath("/iri/project") + + #set new title + ldtproject.title = result[0].get("title") + + #get new content list + new_contents=[] + result = doc.xpath("/iri/medias/media") + for medianode in result: + id = medianode.get("id") + new_contents.append(id) -def get_attrib(ldtproject): - doc = lxml.etree.fromstring(ldtproject.ldt.encode( "utf-8" )) - result = doc.xpath("/iri/project") - - for pnode in result: - title = pnode.get("title") - break - - #set new title - ldtproject.title=title - - #get new content list - new_contents=[] - result = doc.xpath("/iri/medias/media") - for medianode in result: - id = medianode.get("id") - new_contents.append(id) - #set new content list for c in ldtproject.contents.all(): if not c.iri_id in new_contents: ldtproject.contents.remove(c) + + ldtproject.save() + else: + ldt = '' + new_contents=[] + + return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request)) - return ldtproject + + @@ -437,7 +522,42 @@ return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProject', args=[project.ldt_id])) else: form = AddProjectForm() - return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'contents':contents, 'iri_id':iri_id, 'create_project_action':reverse("ldt.ldt_utils.views.create_project",args=[iri_id])}, context_instance=RequestContext(request)) + return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.create_project",args=[iri_id])}, context_instance=RequestContext(request)) + +@login_required +def update_project(request, ldt_id): + + project = get_object_or_404(Project, ldt_id=ldt_id) + contents = project.contents.all() + if request.method == "POST" : + submit_action = request.REQUEST.get("submit_button",False) + if submit_action == "prepare_delete": + errors = [] + if project.state == 2: + errors.append(_("the project %(title)s is published. please unpublish before deleting.")%{'title':project.title}) + message = _("can not delete the project. Please correct the following error") + title = _('title error deleting project') + else: + message = _("please confirm deleting project %(title)s")%{'title':project.title} + title = _("confirm deletion") + return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request)) + elif submit_action == "delete": + if project.state != 2: + project.delete() + form_status= 'deleted' + form = AddProjectForm() + else: + form_status= 'saved' + form = AddProjectForm(request.POST) + if form.is_valid(): + project.title=form.cleaned_data['title'] + project.save() + else: + form = AddProjectForm({'title':unicode(project.title)}) + form_status= 'none' + + return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'ldt_id': ldt_id, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.update_project",args=[ldt_id])}, context_instance=RequestContext(request)) + @login_required def copy_project(request, ldt_id): @@ -486,53 +606,71 @@ media = None elif media_input_type == "link": media = content_form.cleaned_data["media_obj"] - elif media_input_type == "url" or media_input_type == "upload" or media_input_type == "create": + created = False + elif media_input_type == "create": + del cleaned_data["media_file"] + if not cleaned_data['videopath']: + cleaned_data['videopath'] = settings.STREAM_URL + media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) + elif media_input_type == "url" or media_input_type == "upload" : # copy file #complet src destination_file = None source_file = None destination_file_path = None - if media_input_type != "create": - try: - if media_input_type == "url": - url = cleaned_data["external_src_url"] - source_file = urllib2.urlopen(url) - source_filename = source_file.info().get('Content-Disposition', None) - if not source_filename: - source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1] - elif media_input_type == "upload": - source_file = request.FILES['media-media_file'] - source_filename = source_file.name - - - destination_filepath = os.path.join(settings.STREAM_PATH, source_filename) - base_source_filename = source_filename - i = 0 - while os.path.exists(destination_filepath): - base_source_filename = source_filename+"(%d)" % (i) - destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename) - i += 1 - - destination_file = open(destination_filepath, "w") - src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/") - if len(src_prefix) > 0: - cleaned_data["src"] = src_prefix + "/" + base_source_filename - else: - cleaned_data["src"] = base_source_filename + try: + if media_input_type == "url": + url = cleaned_data["external_src_url"] + source_file = urllib2.urlopen(url) + source_filename = source_file.info().get('Content-Disposition', None) + if not source_filename: + source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1] + elif media_input_type == "upload": + source_file = request.FILES['media-media_file'] + source_filename = source_file.name + + source_filename = ldt_utils_path.sanitize_filename(source_filename) + destination_filepath = os.path.join(settings.STREAM_PATH, source_filename) + base_source_filename = source_filename + extension = base_source_filename.split(".")[-1] + if extension == base_source_filename: + extension = "" + base_basename_filename = base_source_filename + else: + base_basename_filename = base_source_filename[:-1 *(len(extension)+1)] + i = 0 + while os.path.exists(destination_filepath): + base_source_filename = "%s.%d.%s" % (base_basename_filename,i,extension) + destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename) + i += 1 + destination_file = open(destination_filepath, "w") + src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/") + if len(src_prefix) > 0: + cleaned_data["src"] = src_prefix + "/" + base_source_filename + else: + cleaned_data["src"] = base_source_filename + + chunck = source_file.read(2048) + while chunck: + destination_file.write(chunck) chunck = source_file.read(2048) - while chunck: - destination_file.write(chunck) - chunck = source_file.read(2048) - - except Exception as inst: - logging.debug("write_content_base : POST error when processing file:" + str(inst)) - form_status = "error" - finally: - if destination_file: - destination_file.close() - if source_file: - source_file.close() + + except Exception as inst: + logging.debug("write_content_base : POST error when processing file:" + str(inst)) + form_status = "error" + #set error for form + if media_input_type == "url": + errors = media_form._errors.setdefault("external_src_url", ErrorList()) + errors.append(_("Problem when downloading file from url : ")+str(inst)) + elif media_input_type == "upload": + errors = media_form._errors.setdefault("media_file", ErrorList()) + errors.append(_("Problem when uploading file : ") + str(inst)) + finally: + if destination_file: + destination_file.close() + if source_file: + source_file.close() if form_status != "error": #try: @@ -540,10 +678,13 @@ if not cleaned_data['videopath']: cleaned_data['videopath'] = settings.STREAM_URL media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) - if not created: - for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'): - setattr(media, attribute, cleaned_data.get(attribute)) - media.save() + else: + media = None + + if media and not created: + for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'): + setattr(media, attribute, cleaned_data.get(attribute)) + media.save() #except Exception as inst: # logging.debug("write_content_base : POST error when saving media:" + str(inst)) # form_status = "error" @@ -586,18 +727,59 @@ return content_form, media_form, form_status - +@login_required def write_content(request, iri_id=None): - logging.debug("write_content : " + str(iri_id) ) - content_form, media_form, form_status = write_content_base(request, iri_id) - + submit_action = request.REQUEST.get("submit_button",False) + + if submit_action == "prepare_delete": + errors, titles = prepare_delete_content(request, iri_id) + if errors and len(errors) > 0: + message = ungettext("There is %(count)d error when deleting content", "There are %(count)d errors when deleting content", len(errors)) % { 'count': len(errors)} + title_msg = _('title error deleting content') + else: + message = _("Confirm delete content %(titles)s") % { 'titles' : ",".join(titles) } + title_msg = _("confirm delete content") + return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title_msg}, context_instance=RequestContext(request)) + elif submit_action == "delete": + delete_content(request, iri_id) + form_status = "deleted" + content_form = ContentForm() + media_form = MediaForm() + else: + content_form, media_form, form_status = write_content_base(request, iri_id) + if iri_id: create_content_action = reverse('ldt.ldt_utils.views.write_content', kwargs={'iri_id':iri_id}) else: create_content_action = reverse('ldt.ldt_utils.views.write_content') - return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form,'form_status': form_status,'create_content_action': create_content_action}, context_instance=RequestContext(request)) + return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form,'form_status': form_status,'create_content_action': create_content_action, 'iri_id': iri_id}, context_instance=RequestContext(request)) + +@login_required +def prepare_delete_content(request, iri_id=None): + errors = [] + titles = [] + if not iri_id: + iri_id = request.REQUEST.get("iri_id", None) + + if iri_id: + for content in Content.objects.filter(iri_id=iri_id): + titles.append(unicode(content.title)) + projects = Content.objects.all()[0].project_set.all() + projects_nb = len(projects) + if projects_nb > 0: + project_titles = [lambda p: p.title for p in projects] + errors.append(ungettext("Content '%(title)s' is referenced by this project : %(project_titles)s. Please delete it beforehand.", "Content '%(title)s' is referenced by %(count)d projects: %(project_titles)s. Please delete them beforehand.", projects_nb)%{'title':content.title,'count':projects_nb, 'project_titles': ",".join(project_titles)}) + + return errors, titles +@login_required +def delete_content(request, iri_id=None): + if not iri_id: + iri_id = request.REQUEST.get("iri_id", None) + + if iri_id: + Content.objects.filter(iri_id=iri_id).delete()