def image_allographs(request, image_id): """Returns a list of all the allographs/annotations for the requested image.""" can_edit = has_edit_permission(request, Annotation) annotations = Annotation.objects.filter(image=image_id).exclude_hidden(can_edit).select_related('graph') data_allographs = SortedDict() for a in annotations: if a.graph: hand_label = a.graph.hand allograph_name = a.graph.idiograph.allograph if hand_label in data_allographs: if allograph_name not in data_allographs[hand_label]: data_allographs[hand_label][allograph_name] = [] else: data_allographs[hand_label] = SortedDict() data_allographs[hand_label][allograph_name] = [] data_allographs[hand_label][allograph_name].append(a) context = { 'annotations_list': data_allographs, 'can_edit': can_edit } return render_to_response('digipal/annotations.html', context, context_instance=RequestContext(request))
def image_allographs(request, image_id): """Returns a list of all the allographs/annotations for the requested image.""" can_edit = has_edit_permission(request, Annotation) annotations = Annotation.objects.filter( image=image_id).exclude_hidden(can_edit).select_related('graph') data_allographs = OrderedDict() for a in annotations: if a.graph: hand_label = a.graph.hand allograph_name = a.graph.idiograph.allograph if hand_label in data_allographs: if allograph_name not in data_allographs[hand_label]: data_allographs[hand_label][allograph_name] = [] else: data_allographs[hand_label] = OrderedDict() data_allographs[hand_label][allograph_name] = [] data_allographs[hand_label][allograph_name].append(a) context = {'annotations_list': data_allographs, 'can_edit': can_edit} return render_to_response('digipal/annotations.html', context, context_instance=RequestContext(request))
def idiograph_editor(request): formsetScribe = formset_factory(ScribeAdminForm) formset = formsetScribe() onlyScribeForm = OnlyScribe() newContext = { 'can_edit': has_edit_permission(request, Annotation), 'formset': formset, 'scribeForm': onlyScribeForm } return render_to_response('admin/digipal/idiograph_editor.html', newContext, context_instance=RequestContext(request))
def save_editorial(request, graphs): if settings.ARCHETYPE_API_READ_ONLY: # transaction.rollback() raise Http404 else: data = {'success': False, 'graphs': []} if not graphs or len(graphs) == 0: raise Exception('No data provided') try: graphs = graphs.replace('/"', "'") graphs = json.loads(graphs) for gr in graphs: image = Image.objects.get(id=gr['image']) get_data = request.POST.copy() _id = gr['id'] count = 0 if _id and _id.isdigit(): count = Annotation.objects.filter(image=image, id=_id).count() if 'geoJson' in gr: geo_json = str(gr['geoJson']) else: geo_json = False if count > 0: annotation = Annotation.objects.get(image=image, id=_id) else: annotation = Annotation(image=image, type='editorial') form = ImageAnnotationForm(data=get_data) if form.is_valid(): with transaction.atomic(): clean = form.cleaned_data if geo_json: annotation.geo_json = geo_json # set the note (only if different) - see JIRA # DIGIPAL-477 for f in ['display_note', 'internal_note']: if getattr(annotation, f) != clean[f] and f in get_data: setattr(annotation, f, clean[f]) if not annotation.id: # set the author only when the annotation is # created annotation.author = request.user if geo_json: annotation.set_graph_group() annotation.save() new_graph = [{}] if 'vector_id' in gr: new_graph[0]['vector_id'] = gr['vector_id'] new_graph[0]['annotation_id'] = unicode(annotation.id) if has_edit_permission(request, Annotation): new_graph[0][ 'internal_note'] = annotation.internal_note new_graph[0]['display_note'] = annotation.display_note data['graphs'].append(new_graph[0]) # transaction.commit() data['success'] = True # uncomment this to see the error call stack in the django server output # except ValueError as e: except Exception as e: data['success'] = False data['errors'] = [u'Internal error: %s' % e] # tb = sys.exc_info()[2] return HttpResponse(json.dumps(data), content_type='application/json')
def save(request, graphs): """Saves an annotation and creates a cutout of the annotation.""" if settings.ARCHETYPE_API_READ_ONLY: # transaction.rollback() raise Http404 else: data = {'success': False, 'graphs': []} try: graphs = graphs.replace('/"', "'") graphs = json.loads(graphs) for gr in graphs: graph_object = False if 'id' in gr: graph_object = Graph.objects.get(id=gr['id']) image = Image.objects.get(id=gr['image']) annotation_is_modified = False if graph_object: annotation = graph_object.annotation graph = graph_object else: graph = Graph() annotation = Annotation(image=image) get_data = request.POST.copy() if 'geoJson' in gr: geo_json = str(gr['geoJson']) else: geo_json = False form = ImageAnnotationForm(data=get_data) if form.is_valid(): with transaction.atomic(): clean = form.cleaned_data if geo_json: annotation.geo_json = geo_json annotation_is_modified = True # set the note (only if different) - see JIRA # DIGIPAL-477 for f in ['display_note', 'internal_note']: if getattr(annotation, f) != clean[f]: setattr(annotation, f, clean[f]) annotation_is_modified = True if not annotation.id: # set the author only when the annotation is # created annotation.author = request.user # annotation.before = clean['before'] # annotation.after = clean['after'] allograph = clean['allograph'] hand = clean['hand'] if hand and allograph: scribe = hand.scribe # GN: if this is a new Graph, it has no idiograph # yet, so we test this first if graph.id and (allograph.id != graph.idiograph.allograph.id): graph.graph_components.all().delete() idiograph_list = Idiograph.objects.filter( allograph=allograph, scribe=scribe) if idiograph_list: idiograph = idiograph_list[0] idiograph.id else: idiograph = Idiograph(allograph=allograph, scribe=scribe) idiograph.save() graph.idiograph = idiograph graph.hand = hand graph.save() # error is here feature_list_checked = get_data.getlist('feature') feature_list_unchecked = get_data.getlist('-feature') if feature_list_unchecked: for value in feature_list_unchecked: cid, fid = value.split('::') component = Component.objects.get(id=cid) feature = Feature.objects.get(id=fid) gc_list = GraphComponent.objects.filter( graph=graph, component=component) if gc_list: gc = gc_list[0] gc.features.remove(feature) gc.save() if not gc.features.all(): gc.delete() if feature_list_checked: for value in feature_list_checked: cid, fid = value.split('::') component = Component.objects.get(id=cid) feature = Feature.objects.get(id=fid) gc_list = GraphComponent.objects.filter( graph=graph, component=component) if gc_list: gc = gc_list[0] else: gc = GraphComponent(graph=graph, component=component) gc.save() gc.features.add(feature) gc.save() aspects = get_data.getlist('aspect') aspects_deleted = get_data.getlist('-aspect') if aspects: for aspect in aspects: aspect_model = Aspect.objects.get(id=aspect) graph.aspects.add(aspect_model) if aspects_deleted: for aspect in aspects_deleted: aspect_model = Aspect.objects.get(id=aspect) graph.aspects.remove(aspect_model) graph.save() # Only save the annotation if it has been modified (or new one) # see JIRA DIGIPAL-477 if annotation_is_modified or not annotation.id: annotation.graph = graph annotation.save() # attach the graph to a containing one # cannot be called BEFORE saving the # annotation/graph if geo_json: annotation.set_graph_group() new_graph = json.loads(get_features(graph.id)) if 'vector_id' in gr: new_graph[0]['vector_id'] = gr['vector_id'] if has_edit_permission(request, Annotation): new_graph[0][ 'internal_note'] = annotation.internal_note new_graph[0]['display_note'] = annotation.display_note data['graphs'].append(new_graph[0]) # transaction.commit() data['success'] = True else: # transaction.rollback() data['success'] = False data['errors'] = get_json_error_from_form_errors(form) # uncomment this to see the error call stack in the django server output # except ValueError as e: except Exception as e: data['success'] = False data['errors'] = [u'Internal error: %s' % e] # tb = sys.exc_info()[2] return HttpResponse(json.dumps(data), content_type='application/json')
def image_annotations(request, image_id, annotations_page=True, hand=False): """Returns a JSON of all the annotations for the requested image.""" can_edit = has_edit_permission(request, Annotation) if annotations_page: annotation_list_with_graph = Annotation.objects.filter( image=image_id).with_graph() else: annotation_list_with_graph = Annotation.objects.filter( graph__hand=hand).with_graph() annotation_list_with_graph = annotation_list_with_graph.exclude_hidden( can_edit) annotation_list_with_graph = annotation_list_with_graph.select_related( 'image', 'graph', 'graph__hand', 'graph__idiograph__allograph__character').prefetch_related( 'graph__graph_components__features', 'graph__aspects', 'graph__graph_components__component', 'image__hands').distinct() editorial_annotations = Annotation.objects.filter( image=image_id).editorial().select_related('image') if not can_edit: editorial_annotations = editorial_annotations.editorial( ).publicly_visible() editorial_annotations = editorial_annotations.exclude_hidden(can_edit) annotations = [] an = {} # hands = [] for a in annotation_list_with_graph: # if len(annotations) > 1: break an = {} annotations.append(an) an['vector_id'] = a.vector_id an['status_id'] = a.status_id an['image_id'] = a.image.id an['hidden_hand'] = a.graph.hand.id an['character'] = a.graph.idiograph.allograph.character.name an['hand'] = a.graph.hand_id an['character_id'] = a.graph.idiograph.allograph.character.id an['allograph_id'] = a.graph.idiograph.allograph.id # Now optimised (see select_related and prefect_related in the query # above) features = get_features_from_graph(a.graph, True) an['num_features'] = len(features['features']) an['features'] = [features] geo = a.get_geo_json_as_dict().get('geometry', None) if geo: an['geo_json'] = geo an['hidden_allograph'] = '%d::%s' % (a.graph.idiograph.allograph.id, a.graph.idiograph.allograph.name) an['feature'] = '%s' % (a.graph.idiograph.allograph) an['graph'] = '%s' % (a.graph.id) # hand = a.graph.hand.label # hands.append(a.graph.hand.id) an['display_note'] = a.display_note an['internal_note'] = a.internal_note an['id'] = unicode(a.id) # gc_list = GraphComponent.objects.filter(graph=a.graph) gc_list = a.graph.graph_components.all() if gc_list: an['features'] = [] for gc in gc_list: for f in gc.features.all(): an['features'].append('%d::%d' % (gc.component.id, f.id)) """ if a.before: an['before'] = '%d::%s' % (a.before.id, a.before.name) if a.after: an['after'] = '%d::%s' % (a.after.id, a.after.name) """ for e in editorial_annotations: an = {} annotations.append(an) # an['geo_json'] = vectors[unicode(e.id)]['geometry'] geo = e.get_geo_json_as_dict().get('geometry', None) if geo: an['geo_json'] = geo an['status_id'] = e.status_id an['image_id'] = e.image.id an['display_note'] = e.display_note an['internal_note'] = e.internal_note an['vector_id'] = e.vector_id an['id'] = unicode(e.id) an['is_editorial'] = True # convert to dict data = {} for an in annotations: data[an['id']] = an an['display_order'] = 0 if 'geo_json' in an and 'coordinates' in an['geo_json']: an['display_order'] = min([ float(point[0]) for point in an['geo_json']['coordinates'][0] ]) if annotations_page: return HttpResponse(json.dumps(data), content_type='application/json') else: return data
def image(request, image_id): """The view for the front-end annotator page""" from digipal.utils import request_invisible_model, raise_404 try: image = Image.objects.get(id=image_id) except Image.DoesNotExist: raise_404('This Image record does not exist') # 404 if content type Image not visible request_invisible_model(Image, request, 'Image') # 404 if image is private and user not staff if image.is_private_for_user(request): raise_404('This Image is currently not publicly available') is_admin = has_edit_permission(request, Image) # annotations_count = image.annotation_set.all().values('graph').count() # annotations = image.annotation_set.all() annotations = Annotation.objects.filter( image_id=image_id, graph__isnull=False).exclude_hidden(is_admin).select_related( 'graph__hand', 'graph__idiograph__allograph') dimensions = { 'width': image.dimensions()[0], 'height': image.dimensions()[1] } hands = image.hands.count() url = request.path url = url.split('/') url.pop(len(url) - 1) url = url[len(url) - 1] # Check for a vector_id in image referral, if it exists the request has # come via Scribe/allograph route vector_id = request.GET.get('graph', '') or request.GET.get( 'vector_id', '') hands_list = [] hand = {} hands_object = Hand.objects.filter(images=image_id) data_allographs = OrderedDict() for h in hands_object.values(): if h['label'] == None: label = "None" else: label = mark_safe(h['label']) hand = {'id': h['id'], 'name': label.encode('cp1252')} hands_list.append(hand) # annotations by allograph for a in annotations: if a.graph and a.graph.hand: hand_label = a.graph.hand allograph_name = a.graph.idiograph.allograph if hand_label in data_allographs: if allograph_name not in data_allographs[hand_label]: data_allographs[hand_label][allograph_name] = [] else: data_allographs[hand_label] = OrderedDict() data_allographs[hand_label][allograph_name] = [] data_allographs[hand_label][allograph_name].append(a) image_link = urlresolvers.reverse('admin:digipal_image_change', args=(image.id, )) form = ImageAnnotationForm(auto_id=False) form.fields['hand'].queryset = image.hands.all() width, height = image.dimensions() image_server_url = image.zoomify zoom_levels = settings.ANNOTATOR_ZOOM_LEVELS from digipal.models import OntographType from digipal.utils import is_model_visible images = Image.objects.none() if image.item_part: images = image.item_part.images.exclude(id=image.id).prefetch_related( 'hands', 'annotation_set') images = Image.filter_permissions_from_request(images, request) images = Image.sort_query_set_by_locus(images, True) from digipal_text.models import TextContentXML context = { 'form': form.as_ul(), 'dimensions': dimensions, 'images': images, 'image': image, 'height': height, 'width': width, 'image_server_url': image_server_url, 'hands_list': hands_list, 'image_link': image_link, 'annotations': annotations.count(), 'annotations_list': data_allographs, 'url': url, 'hands': hands, 'is_admin': is_admin, 'no_image_reason': image.get_media_unavailability_reason(), # True is the user can edit the database 'can_edit': has_edit_permission(request, Annotation), 'ontograph_types': OntographType.objects.order_by('name'), 'zoom_levels': zoom_levels, 'repositories': Repository.objects.filter(currentitem__itempart__images=image_id), # hide all annotations and all annotation tools from the user 'hide_annotations': int(not is_model_visible('graph', request)), 'PAGE_IMAGE_SHOW_MSDATE': settings.PAGE_IMAGE_SHOW_MSDATE, 'text_content_xmls': TextContentXML.objects.filter(text_content__item_part=image.item_part), } if settings.PAGE_IMAGE_SHOW_MSSUMMARY: context['document_summary'] = image.get_document_summary() context['annotations_switch_initial'] = 1 - int( context['hide_annotations'] or ((request.GET.get( 'annotations', 'true')).strip().lower() in ['0', 'false'])) context[ 'show_image'] = context['can_edit'] or not context['no_image_reason'] if vector_id: context['vector_id'] = vector_id return render_to_response('digipal/image_annotation.html', context, context_instance=RequestContext(request))
def save_editorial(request, graphs): if settings.REJECT_HTTP_API_REQUESTS: # transaction.rollback() raise Http404 else: data = { 'success': False, 'graphs': [] } if not graphs or len(graphs) == 0: raise Exception('No data provided') try: graphs = graphs.replace('/"', "'") graphs = json.loads(graphs) for gr in graphs: image = Image.objects.get(id=gr['image']) get_data = request.POST.copy() _id = gr['id'] count = 0 if _id and _id.isdigit(): count = Annotation.objects.filter(image=image, id=_id).count() if 'geoJson' in gr: geo_json = str(gr['geoJson']) else: geo_json = False if count > 0: annotation = Annotation.objects.get(image=image, id=_id) else: annotation = Annotation(image=image, type='editorial') form = ImageAnnotationForm(data=get_data) if form.is_valid(): with transaction.atomic(): clean = form.cleaned_data if geo_json: annotation.geo_json = geo_json # set the note (only if different) - see JIRA DIGIPAL-477 for f in ['display_note', 'internal_note']: if getattr(annotation, f) != clean[f] and f in get_data: setattr(annotation, f, clean[f]) if not annotation.id: # set the author only when the annotation is created annotation.author = request.user if geo_json: annotation.set_graph_group() annotation.save() new_graph = [{}] if 'vector_id' in gr: new_graph[0]['vector_id'] = gr['vector_id'] new_graph[0]['annotation_id'] = unicode(annotation.id) if has_edit_permission(request, Annotation): new_graph[0]['internal_note'] = annotation.internal_note new_graph[0]['display_note'] = annotation.display_note data['graphs'].append(new_graph[0]) #transaction.commit() data['success'] = True # uncomment this to see the error call stack in the django server output #except ValueError as e: except Exception as e: data['success'] = False data['errors'] = [u'Internal error: %s' % e] #tb = sys.exc_info()[2] return HttpResponse(json.dumps(data), content_type='application/json')
def save(request, graphs): """Saves an annotation and creates a cutout of the annotation.""" if settings.REJECT_HTTP_API_REQUESTS: # transaction.rollback() raise Http404 else: data = { 'success': False, 'graphs': [] } try: graphs = graphs.replace('/"', "'") graphs = json.loads(graphs) for gr in graphs: graph_object = False if 'id' in gr: graph_object = Graph.objects.get(id=gr['id']) image = Image.objects.get(id=gr['image']) annotation_is_modified = False if graph_object: annotation = graph_object.annotation graph = graph_object else: graph = Graph() annotation = Annotation(image=image) get_data = request.POST.copy() if 'geoJson' in gr: geo_json = str(gr['geoJson']) else: geo_json = False form = ImageAnnotationForm(data=get_data) if form.is_valid(): with transaction.atomic(): clean = form.cleaned_data if geo_json: annotation.geo_json = geo_json annotation_is_modified = True # set the note (only if different) - see JIRA DIGIPAL-477 for f in ['display_note', 'internal_note']: if getattr(annotation, f) != clean[f]: setattr(annotation, f, clean[f]) annotation_is_modified = True if not annotation.id: # set the author only when the annotation is created annotation.author = request.user #annotation.before = clean['before'] #annotation.after = clean['after'] allograph = clean['allograph'] hand = clean['hand'] if hand and allograph: scribe = hand.scribe # GN: if this is a new Graph, it has no idiograph yet, so we test this first if graph.id and (allograph.id != graph.idiograph.allograph.id): graph.graph_components.all().delete() idiograph_list = Idiograph.objects.filter(allograph=allograph, scribe=scribe) if idiograph_list: idiograph = idiograph_list[0] idiograph.id else: idiograph = Idiograph(allograph=allograph, scribe=scribe) idiograph.save() graph.idiograph = idiograph graph.hand = hand graph.save() # error is here feature_list_checked = get_data.getlist('feature') feature_list_unchecked = get_data.getlist('-feature') if feature_list_unchecked: for value in feature_list_unchecked: cid, fid = value.split('::') component = Component.objects.get(id=cid) feature = Feature.objects.get(id=fid) gc_list = GraphComponent.objects.filter(graph=graph, component=component) if gc_list: gc = gc_list[0] gc.features.remove(feature) gc.save() if not gc.features.all(): gc.delete() if feature_list_checked: for value in feature_list_checked: cid, fid = value.split('::') component = Component.objects.get(id=cid) feature = Feature.objects.get(id=fid) gc_list = GraphComponent.objects.filter(graph=graph, component=component) if gc_list: gc = gc_list[0] else: gc = GraphComponent(graph=graph, component=component) gc.save() gc.features.add(feature) gc.save() aspects = get_data.getlist('aspect') aspects_deleted = get_data.getlist('-aspect') if aspects: for aspect in aspects: aspect_model = Aspect.objects.get(id=aspect) graph.aspects.add(aspect_model) if aspects_deleted: for aspect in aspects_deleted: aspect_model = Aspect.objects.get(id=aspect) graph.aspects.remove(aspect_model) graph.save() # Only save the annotation if it has been modified (or new one) # see JIRA DIGIPAL-477 if annotation_is_modified or not annotation.id: annotation.graph = graph annotation.save() # attach the graph to a containing one # cannot be called BEFORE saving the annotation/graph if geo_json: annotation.set_graph_group() new_graph = json.loads(get_features(graph.id)) if 'vector_id' in gr: new_graph[0]['vector_id'] = gr['vector_id'] if has_edit_permission(request, Annotation): new_graph[0]['internal_note'] = annotation.internal_note new_graph[0]['display_note'] = annotation.display_note data['graphs'].append(new_graph[0]) #transaction.commit() data['success'] = True else: #transaction.rollback() data['success'] = False data['errors'] = get_json_error_from_form_errors(form) # uncomment this to see the error call stack in the django server output #except ValueError as e: except Exception as e: data['success'] = False data['errors'] = [u'Internal error: %s' % e] #tb = sys.exc_info()[2] return HttpResponse(json.dumps(data), content_type='application/json')
def image_annotations(request, image_id, annotations_page=True, hand=False): """Returns a JSON of all the annotations for the requested image.""" can_edit = has_edit_permission(request, Annotation) if annotations_page: annotation_list_with_graph = Annotation.objects.filter(image=image_id).with_graph() else: annotation_list_with_graph = Annotation.objects.filter(graph__hand=hand).with_graph() annotation_list_with_graph = annotation_list_with_graph.exclude_hidden(can_edit) annotation_list_with_graph = annotation_list_with_graph.select_related('image', 'graph', 'graph__hand', 'graph__idiograph__allograph__character').prefetch_related('graph__graph_components__features', 'graph__aspects', 'graph__graph_components__component', 'image__hands').distinct() editorial_annotations = Annotation.objects.filter(image=image_id).editorial().select_related('image') if not can_edit: editorial_annotations = editorial_annotations.editorial().publicly_visible() editorial_annotations = editorial_annotations.exclude_hidden(can_edit) annotations = [] an = {} #hands = [] for a in annotation_list_with_graph: #if len(annotations) > 1: break an = {} annotations.append(an) an['vector_id'] = a.vector_id an['status_id'] = a.status_id an['image_id'] = a.image.id an['hidden_hand'] = a.graph.hand.id an['character'] = a.graph.idiograph.allograph.character.name an['hand'] = a.graph.hand_id an['character_id'] = a.graph.idiograph.allograph.character.id an['allograph_id'] = a.graph.idiograph.allograph.id # Now optimised (see select_related and prefect_related in the query above) features = get_features_from_graph(a.graph, True) an['num_features'] = len(features['features']) an['features'] = [features] geo = a.get_geo_json_as_dict().get('geometry', None) if geo: an['geo_json'] = geo an['hidden_allograph'] = '%d::%s' % (a.graph.idiograph.allograph.id, a.graph.idiograph.allograph.name) an['feature'] = '%s' % (a.graph.idiograph.allograph) an['graph'] = '%s' % (a.graph.id) #hand = a.graph.hand.label #hands.append(a.graph.hand.id) an['display_note'] = a.display_note an['internal_note'] = a.internal_note an['id'] = unicode(a.id) #gc_list = GraphComponent.objects.filter(graph=a.graph) gc_list = a.graph.graph_components.all() if gc_list: an['features'] = [] for gc in gc_list: for f in gc.features.all(): an['features'].append('%d::%d' % (gc.component.id, f.id)) """ if a.before: an['before'] = '%d::%s' % (a.before.id, a.before.name) if a.after: an['after'] = '%d::%s' % (a.after.id, a.after.name) """ for e in editorial_annotations: an = {} annotations.append(an) #an['geo_json'] = vectors[unicode(e.id)]['geometry'] geo = e.get_geo_json_as_dict().get('geometry', None) if geo: an['geo_json'] = geo an['status_id'] = e.status_id an['image_id'] = e.image.id an['display_note'] = e.display_note an['internal_note'] = e.internal_note an['vector_id'] = e.vector_id an['id'] = unicode(e.id) an['is_editorial'] = True # convert to dict data = {} for an in annotations: data[an['id']] = an an['display_order'] = 0 if 'geo_json' in an and 'coordinates' in an['geo_json']: an['display_order'] = min([float(point[0]) for point in an['geo_json']['coordinates'][0]]) if annotations_page: return HttpResponse(json.dumps(data), content_type='application/json') else: return data
def image(request, image_id): """The view for the front-end annotator page""" from digipal.utils import request_invisible_model, raise_404 try: image = Image.objects.get(id=image_id) except Image.DoesNotExist: raise_404('This Image record does not exist') # 404 if content type Image not visible request_invisible_model(Image, request, 'Image') # 404 if image is private and user not staff if image.is_private_for_user(request): raise_404('This Image is currently not publicly available') is_admin = has_edit_permission(request, Image) #annotations_count = image.annotation_set.all().values('graph').count() #annotations = image.annotation_set.all() annotations = Annotation.objects.filter(image_id=image_id, graph__isnull=False).exclude_hidden(is_admin).select_related('graph__hand', 'graph__idiograph__allograph') dimensions = { 'width': image.dimensions()[0], 'height': image.dimensions()[1] } hands = image.hands.count() url = request.path url = url.split('/') url.pop(len(url) - 1) url = url[len(url) - 1] # Check for a vector_id in image referral, if it exists the request has # come via Scribe/allograph route vector_id = request.GET.get('graph', '') or request.GET.get('vector_id', '') hands_list = [] hand = {} hands_object = Hand.objects.filter(images=image_id) data_allographs = SortedDict() for h in hands_object.values(): if h['label'] == None: label = "None" else: label = mark_safe(h['label']) hand = {'id': h['id'], 'name': label.encode('cp1252')} hands_list.append(hand) #annotations by allograph for a in annotations: if a.graph and a.graph.hand: hand_label = a.graph.hand allograph_name = a.graph.idiograph.allograph if hand_label in data_allographs: if allograph_name not in data_allographs[hand_label]: data_allographs[hand_label][allograph_name] = [] else: data_allographs[hand_label] = SortedDict() data_allographs[hand_label][allograph_name] = [] data_allographs[hand_label][allograph_name].append(a) image_link = urlresolvers.reverse('admin:digipal_image_change', args=(image.id,)) form = ImageAnnotationForm(auto_id=False) form.fields['hand'].queryset = image.hands.all() width, height = image.dimensions() image_server_url = image.zoomify zoom_levels = settings.ANNOTATOR_ZOOM_LEVELS from digipal.models import OntographType from digipal.utils import is_model_visible images = image.item_part.images.exclude(id=image.id).prefetch_related('hands', 'annotation_set') images = Image.filter_permissions_from_request(images, request) images = Image.sort_query_set_by_locus(images, True) from digipal_text.models import TextContentXML context = { 'form': form.as_ul(), 'dimensions': dimensions, 'images': images, 'image': image, 'height': height, 'width': width, 'image_server_url': image_server_url, 'hands_list': hands_list, 'image_link': image_link, 'annotations': annotations.count(), 'annotations_list': data_allographs, 'url': url, 'hands': hands, 'is_admin': is_admin, 'no_image_reason': image.get_media_unavailability_reason(), # True is the user can edit the database 'can_edit': has_edit_permission(request, Annotation), 'ontograph_types': OntographType.objects.order_by('name'), 'zoom_levels': zoom_levels, 'repositories': Repository.objects.filter(currentitem__itempart__images=image_id), # hide all annotations and all annotation tools from the user 'hide_annotations': int(not is_model_visible('graph', request)), 'PAGE_IMAGE_SHOW_MSDATE': settings.PAGE_IMAGE_SHOW_MSDATE, 'text_content_xmls': TextContentXML.objects.filter(text_content__item_part=image.item_part), } if settings.PAGE_IMAGE_SHOW_MSSUMMARY: context['document_summary'] = image.get_document_summary() context['annotations_switch_initial'] = 1 - int(context['hide_annotations'] or ((request.REQUEST.get('annotations', 'true')).strip().lower() in ['0', 'false'])) context['show_image'] = context['can_edit'] or not context['no_image_reason'] if vector_id: context['vector_id'] = vector_id return render_to_response('digipal/image_annotation.html', context, context_instance=RequestContext(request))
def update_text_image_link(request, image, ret): if ret is None: ret = {} ret['newids'] = {} from digipal.models import has_edit_permission, Annotation if not has_edit_permission(request, Annotation): set_message(ret, 'Insufficient rights to edit annotations', 'error') return ret # print 'TEXT IMAGE LINK: image #%s' % image.id links = dputils.get_request_var(request, 'links', None) if links: ''' links = [ [ [["", "clause"], ["type", "address"]], {"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[270,-1632],[270,-984],[3006,-984],[3006,-1632],[270,-1632]]]},"properties":null} ], [...] ] ''' for link in json.loads(links): # print link attrs, geojson = link[0], link[1] clientid = (geojson.get('properties', {}) or {}).pop('clientid', '') serverid = geojson.pop('id', None) action = geojson.pop('action', 'update') # 1. find the annotation if not clientid and not serverid: raise Exception( 'Cannot find annotation, need either "id" or "clientid"') filter = {} if serverid: filter['id'] = serverid else: filter['clientid'] = clientid annotation = Annotation.objects.filter(**filter).first() # 2. delete or create annotation if action == 'deleted': if annotation: # print 'delete annotation' annotation.delete() annotation = None else: # create annotation if not annotation: if serverid: raise Exception( 'Cannot find annotation by server id %s' % serverid) # print 'create annotation' author = request.user annotation = Annotation( clientid=clientid, image=image, author=author, type='text') # update annotation and link # print 'update annotation' annotation.set_geo_json_from_dict(geojson) annotation.save() if not serverid: ret['newids'][clientid] = annotation.id # update the text-annotation from digipal_text.models import TextAnnotation # text_annotation = TextAnnotation(annotation=annotation, element=json.dumps(attrs)) # TODO: assume a single element per annotation for the moment text_annotation = TextAnnotation.objects.filter( annotation=annotation).first() if not attrs: # delete it if text_annotation: # print 'delete link' text_annotation.delete() else: if not text_annotation: # print 'create link' text_annotation = TextAnnotation(annotation=annotation) # print 'update link' text_annotation.elementid = json.dumps(attrs) text_annotation.save() return ret
def _build_queryset(self, request, term): """ View for Hand record drill-down """ context = {} self.graphs_count = 0 undefined = u'' scribe = request.GET.get('scribe', undefined) # alternative names are for backward compatibility with old-style graph search page script = request.GET.get('script', undefined) chartype = request.GET.get('chartype', undefined) character = request.GET.get('character', undefined) allograph = request.GET.get('allograph', undefined) component = request.GET.get('component', undefined) feature = request.GET.get('feature', undefined) repository = request.GET.get('repository', undefined) index = request.GET.get('index', undefined) excluded_images = None from digipal.utils import is_staff if not is_staff(request): excluded_images = Image.filter_permissions(Image.objects.all(), [MediaPermission.PERM_PRIVATE]) none = u'-1' one_or_more = u'-2' from datetime import datetime t0 = datetime.now() t4 = datetime.now() wheres = [] if self.search_hands: graphs = Graph.objects.filter(hand__id__in=self.search_hands.queryset) else: # .order_by('item_part__current_item__repository__name', 'item_part__current_item__shelfmark', 'descriptions__description','id') # Although we are listing hands on the front-end, we search for graphs and not for hand. # Two reasons: # searching for character and allograh at the same time through a Hand model would generate two separate joins to graph # this would bring potentially invalid results and it is also much slower # it is faster than excluding all the hands without a graph (yet another expensive join) # if term: term = term.replace('"', '') graphs = Graph.objects.filter( Q(hand__descriptions__description__icontains=term) | \ Q(hand__scribe__name__icontains=term) | \ Q(hand__assigned_place__name__icontains=term) | \ Q(hand__assigned_date__date__icontains=term) | \ Q(hand__item_part__current_item__shelfmark__icontains=term) | \ Q(hand__item_part__current_item__repository__name__icontains=term) | \ Q(hand__item_part__current_item__repository__place__name__icontains=term) | \ Q(hand__item_part__historical_items__catalogue_number__icontains=term) | \ # JIRA 423 Q(hand__item_part__historical_items__name__icontains=term) | \ Q(hand__item_part__group__historical_items__name__icontains=term) | \ Q(hand__item_part__display_label__icontains=term) | \ Q(hand__item_part__group__display_label__icontains=term) ) else: graphs = Graph.objects.all() t1 = datetime.now() if index: graphs = graphs.filter(hand__item_part__historical_items__catalogue_number__iexact=index) if repository: matches = re.match(ur'^([^,]+?),([^,]+)$', repository) if matches: graphs = graphs.filter(Q(hand__item_part__current_item__repository__place__name__iexact=matches.group(1).strip()) & Q(hand__item_part__current_item__repository__name__iexact=matches.group(2).strip())) if scribe: graphs = graphs.filter(hand__scribe__name__icontains=scribe) if script: graphs = graphs.filter(hand__script__name=script) if chartype: graphs = graphs.filter(idiograph__allograph__character__ontograph__ontograph_type__name=chartype) if character: graphs = graphs.filter(idiograph__allograph__character__name=character) if allograph: graphs = graphs.filter(idiograph__allograph__name=allograph) # we discard freak graph records (i.e. without annotation) to prevent errors further down the line. graphs = graphs.filter(annotation__isnull=False) # if the user is not logged in we exclude graphs where the allograph is hidden from digipal.models import has_edit_permission if not has_edit_permission(request, self.get_model()): graphs = graphs.exclude(idiograph__allograph__hidden=True) # exclude private images if excluded_images and excluded_images.count(): graphs = graphs.exclude(annotation__image__in=excluded_images) # condition on component if component: component_where = Q(graph_components__component__name=component) if feature in [undefined, none]: # If no feature is specified we find all the graph which are supposed to have a component # according to their idiograph component_where = component_where | Q(idiograph__allograph__allograph_components__component__name=component) wheres.append(component_where) # condition on feature if feature not in [undefined, none, one_or_more]: wheres.append(Q(graph_components__features__name=feature)) if feature in [one_or_more]: wheres.append(Q(graph_components__features__id__isnull=False)) # ANDs all the Q() where clauses together if wheres: where_and = wheres.pop(0) for where in wheres: where_and = where_and & where graphs = graphs.filter(where_and) # Treat the feature=none case if feature == none: excluded_q = Q(graph_components__features__id__isnull=False) if component: excluded_q = excluded_q & Q(graph_components__component__name=component) excluded_graphs = Graph.objects.filter(excluded_q) graphs = graphs.exclude(id__in=excluded_graphs.values_list('id', flat=True)) from digipal.utils import set_left_joins_in_queryset, get_str_from_queryset set_left_joins_in_queryset(graphs) #print get_str_from_queryset(graphs) t2 = datetime.now() # Get the graphs then id of all the related Hands # We use values_list because it is much faster, we don't need to fetch all the Hands at this stage # That will be done after pagination in the template # Distinct is needed here. #graphs = graphs.distinct().order_by('hand__scribe__name', 'hand__id', 'idiograph__allograph__character__ontograph__sort_order') chrono('graph filter:') graphs = graphs.distinct().order_by('hand__scribe__name', 'hand__id') chrono(':graph filter') #print graphs.query chrono('graph values_list:') graph_ids = graphs.values_list('id', 'hand_id') chrono(':graph values_list') # chrono('len:') # l = len(graph_ids) # print graph_ids.query # chrono(':len') # Build a structure that groups all the graph ids by hand id # context['hand_ids'] = [[1, 101, 102], [2, 103, 104]] # In the above we have two hands: 1 and 2. For hand 1 we have Graph 101 and 102. chrono('hand_ids:') context['hand_ids'] = [[0]] last = 0 for g in graph_ids: if g[1] != context['hand_ids'][-1][0]: context['hand_ids'].append([g[1]]) context['hand_ids'][-1].append(g[0]) del(context['hand_ids'][0]) chrono(':hand_ids') t3 = datetime.now() self.graphs_count = len(graph_ids) t4 = datetime.now() #print 'search %s; hands query: %s + graph count: %s' % (t4 - t0, t3 - t2, t4 - t3) t5 = datetime.now() self._queryset = context['hand_ids'] return self._queryset
def _build_queryset(self, request, term): """ View for Hand record drill-down """ context = {} self.graphs_count = 0 undefined = u'' scribe = request.GET.get('scribe', undefined) # alternative names are for backward compatibility with old-style graph # search page script = request.GET.get('script', undefined) chartype = request.GET.get('chartype', undefined) character = request.GET.get('character', undefined) allograph = request.GET.get('allograph', undefined) component = request.GET.get('component', undefined) feature = request.GET.get('feature', undefined) repository = request.GET.get('repository', undefined) index = request.GET.get('index', undefined) excluded_images = None from digipal.utils import is_staff if not is_staff(request): excluded_images = Image.filter_permissions( Image.objects.all(), [MediaPermission.PERM_PRIVATE]) none = u'-1' one_or_more = u'-2' from datetime import datetime t0 = datetime.now() t4 = datetime.now() wheres = [] if self.search_hands: graphs = Graph.objects.filter( hand__id__in=self.search_hands.queryset) else: # .order_by('item_part__current_item__repository__name', 'item_part__current_item__shelfmark', 'descriptions__description','id') # Although we are listing hands on the front-end, we search for graphs and not for hand. # Two reasons: # searching for character and allograh at the same time through a Hand model would generate two separate joins to graph # this would bring potentially invalid results and it is also much slower # it is faster than excluding all the hands without a graph (yet another expensive join) # if term: term = term.replace('"', '') graphs = Graph.objects.filter( Q(hand__descriptions__description__icontains=term) | Q(hand__scribe__name__icontains=term) | Q(hand__assigned_place__name__icontains=term) | Q(hand__assigned_date__date__icontains=term) | Q(hand__item_part__current_item__shelfmark__icontains=term) | Q(hand__item_part__current_item__repository__name__icontains=term) | Q(hand__item_part__current_item__repository__place__name__icontains=term) | Q(hand__item_part__historical_items__catalogue_number__icontains=term) | \ # JIRA 423 Q(hand__item_part__historical_items__name__icontains=term) | \ Q(hand__item_part__group__historical_items__name__icontains=term) | \ Q(hand__item_part__display_label__icontains=term) | \ Q(hand__item_part__group__display_label__icontains=term) ) else: graphs = Graph.objects.all() t1 = datetime.now() if index: graphs = graphs.filter( hand__item_part__historical_items__catalogue_number__iexact=index) if repository: matches = re.match(ur'^([^,]+?),([^,]+)$', repository) if matches: graphs = graphs.filter(Q(hand__item_part__current_item__repository__place__name__iexact=matches.group( 1).strip()) & Q(hand__item_part__current_item__repository__name__iexact=matches.group(2).strip())) if scribe: graphs = graphs.filter(hand__scribe__name__icontains=scribe) if script: graphs = graphs.filter(hand__script__name=script) if chartype: graphs = graphs.filter( idiograph__allograph__character__ontograph__ontograph_type__name=chartype) if character: graphs = graphs.filter( idiograph__allograph__character__name=character) if allograph: graphs = graphs.filter(idiograph__allograph__name=allograph) # we discard freak graph records (i.e. without annotation) to prevent # errors further down the line. graphs = graphs.filter(annotation__isnull=False) # if the user is not logged in we exclude graphs where the allograph is # hidden from digipal.models import has_edit_permission if not has_edit_permission(request, self.get_model()): graphs = graphs.exclude(idiograph__allograph__hidden=True) # exclude private images if excluded_images and excluded_images.count(): graphs = graphs.exclude(annotation__image__in=excluded_images) # condition on component if component: component_where = Q(graph_components__component__name=component) if feature in [undefined, none]: # If no feature is specified we find all the graph which are supposed to have a component # according to their idiograph component_where = component_where | Q( idiograph__allograph__allograph_components__component__name=component) wheres.append(component_where) # condition on feature if feature not in [undefined, none, one_or_more]: wheres.append(Q(graph_components__features__name=feature)) if feature in [one_or_more]: wheres.append(Q(graph_components__features__id__isnull=False)) # ANDs all the Q() where clauses together if wheres: where_and = wheres.pop(0) for where in wheres: where_and = where_and & where graphs = graphs.filter(where_and) # Treat the feature=none case if feature == none: excluded_q = Q(graph_components__features__id__isnull=False) if component: excluded_q = excluded_q & Q( graph_components__component__name=component) excluded_graphs = Graph.objects.filter(excluded_q) graphs = graphs.exclude( id__in=excluded_graphs.values_list('id', flat=True)) from digipal.utils import set_left_joins_in_queryset, get_str_from_queryset set_left_joins_in_queryset(graphs) # print get_str_from_queryset(graphs) t2 = datetime.now() # Get the graphs then id of all the related Hands # We use values_list because it is much faster, we don't need to fetch all the Hands at this stage # That will be done after pagination in the template # Distinct is needed here. #graphs = graphs.distinct().order_by('hand__scribe__name', 'hand__id', 'idiograph__allograph__character__ontograph__sort_order') chrono('graph filter:') graphs = graphs.distinct().order_by('hand__scribe__name', 'hand__id') chrono(':graph filter') # print graphs.query chrono('graph values_list:') graph_ids = graphs.values_list('id', 'hand_id') chrono(':graph values_list') # chrono('len:') # l = len(graph_ids) # print graph_ids.query # chrono(':len') # Build a structure that groups all the graph ids by hand id # context['hand_ids'] = [[1, 101, 102], [2, 103, 104]] # In the above we have two hands: 1 and 2. For hand 1 we have Graph 101 # and 102. chrono('hand_ids:') context['hand_ids'] = [[0]] last = 0 for g in graph_ids: if g[1] != context['hand_ids'][-1][0]: context['hand_ids'].append([g[1]]) context['hand_ids'][-1].append(g[0]) del(context['hand_ids'][0]) chrono(':hand_ids') t3 = datetime.now() self.graphs_count = len(graph_ids) t4 = datetime.now() # print 'search %s; hands query: %s + graph count: %s' % (t4 - t0, t3 - # t2, t4 - t3) t5 = datetime.now() self._queryset = context['hand_ids'] return self._queryset
def update_text_image_link(request, image, ret): if ret is None: ret = {} ret['newids'] = {} from digipal.models import has_edit_permission, Annotation if not has_edit_permission(request, Annotation): set_message(ret, 'Insufficient rights to edit annotations', 'error') return ret # print 'TEXT IMAGE LINK: image #%s' % image.id links = dputils.get_request_var(request, 'links', None) if links: ''' links = [ [ [["", "clause"], ["type", "address"]], {"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[270,-1632],[270,-984],[3006,-984],[3006,-1632],[270,-1632]]]},"properties":null} ], [...] ] ''' for link in json.loads(links): # print link attrs, geojson = link[0], link[1] clientid = (geojson.get('properties', {}) or {}).pop('clientid', '') serverid = geojson.pop('id', None) action = geojson.pop('action', 'update') # 1. find the annotation if not clientid and not serverid: raise Exception( 'Cannot find annotation, need either "id" or "clientid"') filter = {} if serverid: filter['id'] = serverid else: filter['clientid'] = clientid annotation = Annotation.objects.filter(**filter).first() # 2. delete or create annotation if action == 'deleted': if annotation: # print 'delete annotation' annotation.delete() annotation = None else: # create annotation if not annotation: if serverid: raise Exception( 'Cannot find annotation by server id %s' % serverid) # print 'create annotation' author = request.user annotation = Annotation(clientid=clientid, image=image, author=author, type='text') # update annotation and link # print 'update annotation' annotation.set_geo_json_from_dict(geojson) annotation.save() if not serverid: ret['newids'][clientid] = annotation.id # update the text-annotation from digipal_text.models import TextAnnotation # text_annotation = TextAnnotation(annotation=annotation, element=json.dumps(attrs)) # TODO: assume a single element per annotation for the moment text_annotation = TextAnnotation.objects.filter( annotation=annotation).first() if not attrs: # delete it if text_annotation: # print 'delete link' text_annotation.delete() else: if not text_annotation: # print 'create link' text_annotation = TextAnnotation(annotation=annotation) # print 'update link' text_annotation.elementid = json.dumps(attrs) text_annotation.save() return ret