Backend work on tags (needs testing) + model changes (image_guid, Tag)
authordurandn
Fri, 24 Jun 2016 12:36:44 +0200
changeset 33 f9d4c9a63e4e
parent 30 7ff344b4bf6d
child 34 1ede957a6868
Backend work on tags (needs testing) + model changes (image_guid, Tag)
README.md
src/iconolab/fixtures/dev_initial_data.json
src/iconolab/forms/annotations.py
src/iconolab/migrations/0001_initial.py
src/iconolab/models.py
src/iconolab/settings/__init__.py
src/iconolab/settings/dev.py.tmpl
src/iconolab/templates/iconolab/change_annotation.html
src/iconolab/templates/iconolab/detail_annotation.html
src/iconolab/templates/iconolab/detail_image.html
src/iconolab/urls.py
src/iconolab/utils.py
src/iconolab/views.py
--- a/README.md	Wed Jun 22 17:53:40 2016 +0200
+++ b/README.md	Fri Jun 24 12:36:44 2016 +0200
@@ -97,8 +97,8 @@
 
 To access the loaded annotation, follow:
 
-	/collections/ingres/images/1234567890/annotations/34ae39ae-a9a2-4736-bc59-ba6f00e37f52/detail
-	/collections/ingres/images/1234567890/annotations/34ae39ae-a9a2-4736-bc59-ba6f00e37f52/edit
+	/collections/ingres/images/26aec320-dcfe-4cbc-b912-6a6c13e8916e/annotations/34ae39ae-a9a2-4736-bc59-ba6f00e37f52/detail
+	/collections/ingres/images/26aec320-dcfe-4cbc-b912-6a6c13e8916e/annotations/34ae39ae-a9a2-4736-bc59-ba6f00e37f52/edit
 	
 The annotation owner is contributeur1, if you try to edit it as another user, it will create the revision but will not publish it in the current state of the project.
 	
--- a/src/iconolab/fixtures/dev_initial_data.json	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/fixtures/dev_initial_data.json	Fri Jun 24 12:36:44 2016 +0200
@@ -39,8 +39,8 @@
 	    "model": "iconolab.Image",
 	    "pk": 1,
 	    "fields": {
+	    	"image_guid" : "26aec320-dcfe-4cbc-b912-6a6c13e8916e",
 	    	"name" : "napoleon.jpg",
-	    	"image_ref": "1234567890",
 			"media" : "uploads/napoleon.jpg",
 			"item": 1,
 			"height": 1400,
--- a/src/iconolab/forms/annotations.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/forms/annotations.py	Fri Jun 24 12:36:44 2016 +0200
@@ -1,6 +1,9 @@
-from django.forms import ModelForm, HiddenInput
+from django.forms import ModelForm, TypedMultipleChoiceField, HiddenInput, MultipleHiddenInput
 from iconolab.models import AnnotationRevision
+import json
 
+class MultipleTagsField(TypedMultipleChoiceField):
+    pass
 
 class AnnotationRevisionForm(ModelForm):
     class Meta:
@@ -8,4 +11,18 @@
         fields = ('title', 'description', 'fragment',)
         widgets = {
             'fragment': HiddenInput(),
-        }
\ No newline at end of file
+            'tags': HiddenInput()
+        }
+    
+    def tags_json(self):
+        if self.instance:
+            tags_list = []
+            for tag_info in self.instance.tagginginfo_set.all():
+                tags_list.push({
+                    'tag_input': tag_info.tag.link,
+                    'relevancy': tag_info.relevancy,
+                    'accuracy': tag_info.accuracy
+                })
+            return json.dumps(tags_list)
+        else:
+            return '[]' 
\ No newline at end of file
--- a/src/iconolab/migrations/0001_initial.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/migrations/0001_initial.py	Fri Jun 24 12:36:44 2016 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.9.7 on 2016-06-21 12:07
+# Generated by Django 1.9.7 on 2016-06-23 15:44
 from __future__ import unicode_literals
 
 from django.conf import settings
@@ -67,9 +67,9 @@
             name='Image',
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('image_guid', models.UUIDField(default=uuid.uuid4, editable=False)),
                 ('name', models.CharField(max_length=200)),
                 ('media', models.ImageField(height_field='height', upload_to='uploads/', width_field='width')),
-                ('image_ref', models.CharField(max_length=255, unique=True)),
                 ('height', models.IntegerField()),
                 ('width', models.IntegerField()),
                 ('created', models.DateTimeField(auto_now_add=True, null=True)),
@@ -110,10 +110,9 @@
             name='Tag',
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('type', models.IntegerField(choices=[(0, 'dbpedia'), (1, 'iconolab')])),
-                ('label', models.SlugField()),
-                ('link', models.URLField(blank=True, null=True)),
-                ('description', models.CharField(max_length=255)),
+                ('label', models.SlugField(blank=True, null=True)),
+                ('link', models.URLField(unique=True)),
+                ('description', models.CharField(blank=True, max_length=255, null=True)),
                 ('collection', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='iconolab.Collection')),
             ],
         ),
--- a/src/iconolab/models.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/models.py	Fri Jun 24 12:36:44 2016 +0200
@@ -1,24 +1,19 @@
 from django.db import models, transaction
+from django.conf import settings
 from django.contrib.auth.models import User
-
 from django.contrib.contenttypes.fields import GenericForeignKey
 from django.contrib.contenttypes.models import ContentType
-import uuid
+import uuid, json
 
 
 class Tag(models.Model):
-	DBPEDIA = 0
-	ICONOLAB = 1
-	TAG_TYPES = (
-		(DBPEDIA, 'dbpedia'),
-		(ICONOLAB, 'iconolab')
-	)
+	label = models.SlugField(blank=True, null=True)
+	link = models.URLField(unique=True)
+	description = models.CharField(max_length=255, blank=True, null=True)
+	collection = models.ForeignKey('Collection', blank=True, null=True)
 	
-	type = models.IntegerField(choices=TAG_TYPES)
-	label = models.SlugField()
-	link = models.URLField(blank=True, null=True)
-	description = models.CharField(max_length=255)
-	collection = models.ForeignKey('Collection', blank=True, null=True)
+	def is_internal(self):
+		return link.startswith(settings.BASE_URL)
 
 class TaggingInfo(models.Model):
 	revision = models.ForeignKey('AnnotationRevision', on_delete=models.CASCADE)
@@ -56,9 +51,9 @@
 	tag_count = models.IntegerField(blank=True, null=True, default=0)
 
 class Image(models.Model):
+	image_guid = models.UUIDField(default=uuid.uuid4, editable=False)
 	name = models.CharField(max_length=200)
 	media = models.ImageField(upload_to='uploads/', height_field='height', width_field='width')
-	image_ref = models.CharField(max_length=255, unique=True)
 	item = models.ForeignKey('Item', related_name='images', null=True, blank=True)
 	height = models.IntegerField(null=False, blank=False)
 	width = models.IntegerField(null=False, blank=False)
@@ -80,7 +75,7 @@
 	
 	# Call Annotation.objects.create_annotation to initialize a new Annotation with its associated AnnotationStats and initial AnnotationRevision
 	@transaction.atomic
-	def create_annotation(self, author, image, title='', description='', fragment='', tags=None):
+	def create_annotation(self, author, image, title='', description='', fragment='', tags_json='[]'):
 		# Create annotation object
 		new_annotation = Annotation(
 			image=image, 
@@ -98,6 +93,8 @@
 			state=AnnotationRevision.ACCEPTED
 		)
 		initial_revision.save()
+		initial_revision.set_tags(tags_json)
+		
 		new_annotation.current_revision = initial_revision
 		new_annotation.save()
 		
@@ -197,12 +194,44 @@
 	author = models.ForeignKey(User, null=True)
 	title = models.CharField(max_length=255)
 	description = models.TextField(null=True)
-	fragment = models.TextField() # path string
+	fragment = models.TextField()
 	tags = models.ManyToManyField('Tag', through='TaggingInfo', through_fields=('revision', 'tag'), blank=True, null=True)
 	state = models.IntegerField(choices=REVISION_STATES, default=AWAITING)
 	created = models.DateTimeField(auto_now_add=True, null=True)
 
-
+	def set_tags(self, tags_json_string):
+		try:
+			tags_dict = json.loads(tags_json_string)
+		except ValueError:
+			pass
+		for tag_data in tags_dict:
+			tag_string = tag_data.get("tag_input")
+			tag_accuracy = tag_data.get("accuracy")
+			tag_relevancy = tag_data.get("relevancy")
+			
+			if tag_string.startswith("http://"): #check if url
+				if Tag.objects.exists(link=tag_string): #check if tag already exists
+					tag_obj = Tag.objects.get(link=tag_string)
+				else:
+					tag_obj = Tag.objects.create(
+						link = settings.BASE_URL+tag_string,
+					)
+			else:
+				tag_obj = Tag.objects.create(
+					label = tag_string,
+					description = "",
+					link = settings.BASE_URL+tag_string,
+					collection = self.parent_annotation.image.item.collection
+				)
+			tag_info = TaggingInfo.objects.create(
+				tag=tag_obj, 
+				revision=self,
+				accuracy = tag_accuracy,
+				relevancy = tag_relevancy
+			)
+		
+		
+	
 #class MetaCategory(models.Model):
 #	collection = models.ForeignKey(Collection)
 #	label = models.CharField(max_length=200)
--- a/src/iconolab/settings/__init__.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/settings/__init__.py	Fri Jun 24 12:36:44 2016 +0200
@@ -21,6 +21,7 @@
     os.path.join(BASE_DIR, 'static'),
     os.path.join(BASE_DIR, 'media'),
 ]
+BASE_URL = ''
 STATIC_URL = '/static/'
 MEDIA_URL = '/media/'
 
--- a/src/iconolab/settings/dev.py.tmpl	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/settings/dev.py.tmpl	Fri Jun 24 12:36:44 2016 +0200
@@ -15,12 +15,16 @@
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
-STATIC_ROOT = os.path.join(BASE_DIR, 'web')
+STATIC_ROOT = os.path.join(BASE_DIR, '../../web/static/site')
+MEDIA_ROOT = os.path.join(BASE_DIR, '../../web/media')
+STATICFILES_DIRS = [
+    os.path.join(BASE_DIR, 'static'),
+]
+BASE_URL = ''
+STATIC_URL = '/static/'
+MEDIA_URL = '/media/'
 
 LOGIN_URL = '/account/login/'
-#Static path
-MEDIA_ROOT = os.path.join(BASE_DIR, 'iconolab', 'media')
-
 
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
@@ -145,9 +149,3 @@
 USE_L10N = True
 
 USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/1.9/howto/static-files/
-
-STATIC_URL = '/static/'
--- a/src/iconolab/templates/iconolab/change_annotation.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/change_annotation.html	Fri Jun 24 12:36:44 2016 +0200
@@ -71,21 +71,25 @@
 			</div>
 
 			<div class='col-xs-6' style="">
-				 <form class="form" action="{% if annotation %}{% url 'annotation_edit' collection_name image_ref annotation_guid %}{% else %}{% url 'annotation_create' collection_name image_ref %}{% endif %}" method="POST">
+				 <form class="form" action="{% if annotation %}{% url 'annotation_edit' collection_name image_guid annotation_guid %}{% else %}{% url 'annotation_create' collection_name image_guid %}{% endif %}" method="POST">
 				 	{% csrf_token %}
                     <fieldset class="form-group">
                       <label class="control-label" for="id_{{ form.title.name }}">{{ form.title.label }}</label>
                       <input type="text" class="form-control"
                         name="{{ form.title.name }}"
-                        id="id_{{ form.title.name }}" value="{% if annotation %}{{ annotation.current_revision.title }}{% endif %}">
+                        id="id_{{ form.title.name }}" value="{{ form.title.value}}">
                     </fieldset>
                     <fieldset class="form-group">
                       <label class="control-label" for="id_{{ form.description.name }}">{{ form.description.label }}</label>
                       <textarea class="form-control"
                         name="{{ form.description.name }}"
-                        id="id_{{ form.description.name }}" >{% if annotation %}{{ annotation.current_revision.description }}{% endif %}</textarea>
+                        id="id_{{ form.description.name }}" >{{ form.description.value}}</textarea>
+                    </fieldset>
+                    <fieldset class="form-group">
+                      <label class="control-label" for="id_{{ form.tags.name }}">{{ form.tags.label }}</label>
                     </fieldset>
         			<input v-model="normalizePath" type="hidden" name="fragment"></input>
+                    <input id="tags_input" type="hidden" name="tags" value="{{ form.tags_json }}"></input>
         			<button type="submit" class="save btn btn-default">Enregister</button>
     			</form>
 			</div>
--- a/src/iconolab/templates/iconolab/detail_annotation.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_annotation.html	Fri Jun 24 12:36:44 2016 +0200
@@ -33,8 +33,8 @@
 				<p> <strong>Tags:</strong> {{ annotation.current_revision.tags }}</p>
 				<p> <strong>Fragment:</strong> {{ annotation.current_revision.fragment }}</p>
 
-				<a href="{% url 'annotation_edit' collection_name image_ref annotation_guid  %}">Editer</a> | 
-				<a href="{% url 'annotation_edit' collection_name image_ref annotation_guid %}">Proposer une révision</a>
+				<a href="{% url 'annotation_edit' collection_name image_guid annotation_guid  %}">Editer</a> | 
+				<a href="{% url 'annotation_edit' collection_name image_guid annotation_guid %}">Proposer une révision</a>
 			</div>
 		</div>
 	</div>
--- a/src/iconolab/templates/iconolab/detail_image.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_image.html	Fri Jun 24 12:36:44 2016 +0200
@@ -8,6 +8,6 @@
 
 {% block content %}
 <p>detail_image for {{image_ref}} in the collection {{collection_name}}</p>
-<a href="{% url 'annotation_create' collection_name image_ref %}">Create Annotation</a>
+<a href="{% url 'annotation_create' collection_name image_guid %}">Create Annotation</a>
 
 {% endblock %}
\ No newline at end of file
--- a/src/iconolab/urls.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/urls.py	Fri Jun 24 12:36:44 2016 +0200
@@ -26,11 +26,11 @@
     url(r'^admin/', admin.site.urls),
     url(r'^home$', views.GlobalHomepageView.as_view(), name="home"),
     url(r'^collections/(?P<collection_name>[a-z]+)$', views.CollectionHomepageView.as_view(), name='collection_home'), # Home fond
-    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_ref>[a-z0-9]+)$', views.ShowImageView.as_view(), name='image_detail'),
-    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_ref>[a-z0-9]+)/annotations/create$', login_required(views.CreateAnnotationView.as_view()), name='annotation_create'),
-    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_ref>[a-z0-9]+)/annotations/(?P<annotation_guid>[^/]+)/detail$', views.ShowAnnotationView.as_view(), name='annotation_detail'),
-    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_ref>[a-z0-9]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.EditAnnotationView.as_view()), name='annotation_edit'),
-    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_ref>[a-z0-9]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[0-9]+)/merge$', login_required(views.MergeProposalView.as_view()), name='annotation_merge'),
+    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)$', views.ShowImageView.as_view(), name='image_detail'),
+    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/create$', login_required(views.CreateAnnotationView.as_view()), name='annotation_create'),
+    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/detail$', views.ShowAnnotationView.as_view(), name='annotation_detail'),
+    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.EditAnnotationView.as_view()), name='annotation_edit'),
+    url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[0-9]+)/merge$', login_required(views.MergeProposalView.as_view()), name='annotation_merge'),
     url(r'^rest', include('restapi.urls')),
     url(r'^account/', include('iconolab.auth.urls', namespace='account')),
 ]
--- a/src/iconolab/utils.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/utils.py	Fri Jun 24 12:36:44 2016 +0200
@@ -1,35 +1,1 @@
-from django.db.models.signals import post_save
-from notifications.signals import notify
-
-class NotificationManager:
-
-	NEW_ANNOTATION = 'Nouvelle annotation' 
-	NEW_COMMENT = 'Nouveau commentaire'
-
-	class Notification:
-
-		def __init__(self, sender=None, verb=None):
-			self.sender = sender
-			self.verb = verb
-			self.recipient = None
-			self.target = None
-			self.description = None
-
-		def set_recipient(self, recipient):
-			self.recipient = recipient
-			
-		def set_target(self, target):
-			self.target = target
-
-		def set_description(self, description):
-			self.description = description
-
-	@classmethod
-	def create_notification(self, sender=None, verb=None):
-		annotation = NotificationManager.Notification(sender, verb=verb)
-		return annotation
-
-	@classmethod
-	def notify(self, notification=None):
-		#send to all users or a Group
-		notify.send(notification.sender, recipient=notification.sender, verb=notification.verb)
\ No newline at end of file
+
--- a/src/iconolab/views.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/views.py	Fri Jun 24 12:36:44 2016 +0200
@@ -1,12 +1,22 @@
 from django.shortcuts import HttpResponse, get_object_or_404, render
-from iconolab.models import Annotation, Collection, Image
 from django.http import Http404
 from django.contrib.auth.decorators import login_required
 from django.views.generic import View, RedirectView
 from django.views.generic.base import ContextMixin
 from django.core.urlresolvers import reverse
-from .forms.annotations import AnnotationRevisionForm
-from pprint import pprint
+from iconolab.models import Annotation, Collection, Image
+from iconolab.forms.annotations import AnnotationRevisionForm
+
+def make_tags_json(annotation_revision):
+	final_list = []
+	for tagging_info in annotation_revision.tagginginfo_set.all():
+		final_list.push({
+			"tag_label": tagging_info.tag.label,
+			"tag_link": tagging_info.tag.link,
+			"accuracy": tagging_info.accuracy,
+			"relevancy": tagging_info.relevancy
+		})
+	return json.dumps(final_list) 
 
 class GlobalHomepageView(View):
 	def get(self, request, *args, **kwargs):
@@ -26,7 +36,7 @@
 	def get(self, request, *args, **kwargs):
 		context = super(ShowImageView, self).get_context_data(**kwargs)
 		context["collection_name"] = self.kwargs.get("collection_name", "")
-		context["image_ref"] = self.kwargs.get("image_ref", "")
+		context["image_guid"] = self.kwargs.get("image_guid", "")
 		return render(request, 'iconolab/detail_image.html', context);
 
 
@@ -35,7 +45,7 @@
 	def get_context_data(self, **kwargs):
 		context = super(ShowAnnotationView, self).get_context_data(**kwargs)
 		context["collection_name"] = self.kwargs.get("collection_name", "")
-		context["image_ref"] = self.kwargs.get("image_ref", "")
+		context["image_guid"] = self.kwargs.get("image_guid", "")
 		context["annotation_guid"] = self.kwargs.get("annotation_guid", "")
 		return context
 	
@@ -45,7 +55,7 @@
 		except Collection.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		try:
-			image = Image.objects.get(image_ref=kwargs.get("image_ref", ""))
+			image = Image.objects.get(image_guid=kwargs.get("image_guid", ""))
 		except Image.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		try:
@@ -67,7 +77,7 @@
 	def get_context_data(self, **kwargs):
 		context = super(CreateAnnotationView, self).get_context_data(**kwargs)
 		context["collection_name"] = self.kwargs.get("collection_name", "")
-		context["image_ref"] = self.kwargs.get("image_ref", "")
+		context["image_guid"] = self.kwargs.get("image_guid", "")
 		return context
 	
 	def check_kwargs(self, kwargs):
@@ -76,7 +86,7 @@
 		except Collection.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		try:
-			image = Image.objects.get(image_ref=kwargs.get("image_ref", ""))
+			image = Image.objects.get(image_guid=kwargs.get("image_guid", ""))
 		except Image.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		return collection, image
@@ -92,22 +102,22 @@
 	def post(self, request, *args, **kwargs):
 		collection, image = self.check_kwargs(kwargs)
 		collection_name = kwargs["collection_name"]
-		image_ref = kwargs["image_ref"]
+		image_guid = kwargs["image_guid"]
 		annotation_form = AnnotationRevisionForm(request.POST)
 		if annotation_form.is_valid():
 			author = request.user
 			title = annotation_form.cleaned_data["title"]
 			description = annotation_form.cleaned_data["description"]
 			fragment = annotation_form.cleaned_data["fragment"]
-			new_annotation = Annotation.objects.create_annotation(author, image, title=title, description=description, fragment=fragment, tags=None)
-			return RedirectView.as_view(url=reverse("annotation_detail", kwargs={'collection_name': collection_name, 'image_ref': image_ref, 'annotation_guid': new_annotation.annotation_guid}))(request)
+			new_annotation = Annotation.objects.create_annotation(author, image, title=title, description=description, fragment=fragment)
+			return RedirectView.as_view(url=reverse("annotation_detail", kwargs={'collection_name': collection_name, 'image_guid': image_guid, 'annotation_guid': new_annotation.annotation_guid}))(request)
 	
 class EditAnnotationView(View, ContextMixin):
 	
 	def get_context_data(self, **kwargs):
 		context = super(EditAnnotationView, self).get_context_data(**kwargs)
 		context["collection_name"] = self.kwargs.get("collection_name", "")
-		context["image_ref"] = self.kwargs.get("image_ref", "")
+		context["image_guid"] = self.kwargs.get("image_guid", "")
 		context["annotation_guid"] = self.kwargs.get("annotation_guid", "")
 		return context
 	
@@ -117,7 +127,7 @@
 		except Collection.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		try:
-			image = Image.objects.get(image_ref=kwargs.get("image_ref", ""))
+			image = Image.objects.get(image_guid=kwargs.get("image_guid", ""))
 		except Image.DoesNotExist:
 			return RedirectView.as_view(url=reverse("404error"))
 		try:
@@ -128,17 +138,18 @@
 	
 	def get(self, request, *args, **kwargs):
 		collection, image, annotation = self.check_kwargs(kwargs)
-		annotation_form = AnnotationRevisionForm()
+		annotation_form = AnnotationRevisionForm(instance=annotation.current_revision)
 		context = self.get_context_data(**kwargs)
 		context["image"] = image
 		context["annotation"] = annotation
 		context["form"] = annotation_form
+		context["tags_data"] = make_tags_json(annotation.current_revision)
 		return render(request, 'iconolab/change_annotation.html', context) 
 	
 	def post(self, request, *args, **kwargs):
 		collection, image, annotation = self.check_kwargs(kwargs)
 		collection_name = kwargs["collection_name"]
-		image_ref = kwargs["image_ref"]
+		image_guid = kwargs["image_guid"]
 		annotation_guid = kwargs["annotation_guid"]
 		annotation_form = AnnotationRevisionForm(request.POST)
 		if annotation_form.is_valid():
@@ -146,8 +157,9 @@
 			revision_title = annotation_form.cleaned_data["title"]
 			revision_description = annotation_form.cleaned_data["description"]
 			revision_fragment = annotation_form.cleaned_data["fragment"]
-			annotation.make_new_revision(revision_author, revision_title, revision_description, revision_fragment, None)
-			return RedirectView.as_view(url=reverse("annotation_detail", kwargs={'collection_name': collection_name, 'image_ref': image_ref, 'annotation_guid': annotation_guid}))(request)
+			revision_tags_json = annotation_form.cleaned_data["tags_input"]
+			annotation.make_new_revision(revision_author, revision_title, revision_description, revision_fragment, revision_tags_json)
+			return RedirectView.as_view(url=reverse("annotation_detail", kwargs={'collection_name': collection_name, 'image_guid': image_guid, 'annotation_guid': annotation_guid}))(request)
 
 
 class MergeProposalView(View):