Update object changes templates
`event_diff.html` should show more fields. The same for `person_diff.html`, additionally we may extend `object_diff.html` to work with relational fields (see `views.object_changes`) since e.g. changes to `Task` object don't show anything.

diff --git a/workshops/templates/workshops/event_diff.html b/workshops/templates/workshops/event_diff.html
deleted file mode 100644
index be955c82..00000000
--- a/workshops/templates/workshops/event_diff.html
+++ /dev/null
@@ -1,81 +0,0 @@
-{% extends "workshops/object_diff.html" %}
-
-{% load diff %}
-
-{% block title %}<h1>Event {{ object }}</h1>{% endblock %}
-{% block difftable %}
-<table class="table table-striped">
-  <tr>
-    <th>slug:</th>
-    <td>{% semantic_diff previous_version current_version 'slug' %}</td>
-  </tr>
-  <tr>
-    <th>start date:</th>
-    <td>{% semantic_diff previous_version current_version 'start' %}</td>
-  </tr>
-  <tr>
-    <th>end date:</th>
-    <td>{% semantic_diff previous_version current_version 'end' %}</td>
-  </tr>
-  <tr>
-    <th>host:</th>
-    <td>{% semantic_diff previous_version current_version 'host' %}</td>
-  </tr>
-  <tr>
-    <th>administrator:</th>
-    <td>{% semantic_diff previous_version current_version 'administrator' %}</td>
-  </tr>
-  <tr>
-    <th>tags:</th>
-    <td>{% semantic_diff previous_version current_version 'tags' %}</td>
-  </tr>
-  <tr>
-    <th>url:</th>
-    <td>{% semantic_diff previous_version current_version 'url' %}</td>
-  </tr>
-  <tr>
-    <th>eventbrite key:</th>
-    <td>{% semantic_diff previous_version current_version 'reg_key' %}</td>
-  </tr>
-  <tr>
-    <th>admin fee:</th>
-    <td>{% semantic_diff previous_version current_version 'admin_fee' %}</td>
-  </tr>
-  <tr>
-    <th>invoice:</th>
-    <td>{% semantic_diff previous_version current_version 'invoice_status' %}</td>
-  </tr>
-  <tr>
-    <th>attendance:</th>
-    <td>{% semantic_diff previous_version current_version 'attendance' %}</td>
-  </tr>
-  <tr>
-    <th>contact:</th>
-    <td>{% semantic_diff previous_version current_version 'contact' %}</td>
-  </tr>
-  <tr>
-    <th>location country:</th>
-    <td>{% semantic_diff previous_version current_version 'country' %}</td>
-  </tr>
-  <tr>
-    <th>location venue:</th>
-    <td>{% semantic_diff previous_version current_version 'venue' %}</td>
-  </tr>
-  <tr>
-    <th>location address:</th>
-    <td>{% semantic_diff previous_version current_version 'address' %}</td>
-  </tr>
-  <tr>
-    <th>location latitude:</th>
-    <td>{% semantic_diff previous_version current_version 'latitude' %}</td>
-  </tr>
-  <tr>
-    <th>location longitude:</th>
-    <td>{% semantic_diff previous_version current_version 'longitude' %}</td>
-  </tr>
-  <tr>
-    <th>notes:</th>
-    <td>{% semantic_diff previous_version current_version 'notes' %}</td>
-  </tr>
-</table>
-{% endblock %}
diff --git a/workshops/templates/workshops/object_diff.html b/workshops/templates/workshops/object_diff.html
index d5c653aa..686d6f23 100644
--- a/workshops/templates/workshops/object_diff.html
+++ b/workshops/templates/workshops/object_diff.html
@@ -8,13 +8,20 @@
   <a href="{{ object.get_absolute_url }}" class="btn btn-primary">View newest</a>
 </p>
 <p>Changed on {{ revision.date_created|date:'M j, P' }} by {{ revision.user|default:'Unknown user' }}.</p>
+{% if previous_version == current_version %}
+<p>This is a new object, it doesn't have any previous revisions.</p>
+{% endif %}
 {% block difftable %}
 <table class="table table-striped">
   {% for field in fields %}
     {% if field.name != 'id' %}
   <tr>
     <th>{{ field.verbose_name }}:</th>
+    {% if field.is_relation %}
+    <td>{% relation_diff previous_version current_version field %}</td>
+    {% else %}
     <td>{% semantic_diff previous_version current_version field.name %}</td>
+    {% endif %}
   </tr>
     {% endif %}
   {% endfor %}
diff --git a/workshops/templates/workshops/person_diff.html b/workshops/templates/workshops/person_diff.html
deleted file mode 100644
index 0b2f4296..00000000
--- a/workshops/templates/workshops/person_diff.html
+++ /dev/null
@@ -1,69 +0,0 @@
-{% extends "workshops/object_diff.html" %}
-
-{% load diff %}
-
-{% block title %}<h1>Person {{ object }}</h1>{% endblock %}
-{% block difftable %}
-<table class="table table-striped">
-  <tr>
-    <th>username:</th>
-    <td>{% semantic_diff previous_version current_version 'username' %}</td>
-  </tr>
-  <tr>
-    <th>personal:</th>
-    <td>{% semantic_diff previous_version current_version 'personal' %}</td>
-  </tr>
-  <tr>
-    <th>middle:</th>
-    <td>{% semantic_diff previous_version current_version 'middle' %}</td>
-  </tr>
-  <tr>
-    <th>family:</th>
-    <td>{% semantic_diff previous_version current_version 'family' %}</td>
-  </tr>
-  <tr>
-    <th>may contact:</th>
-    <td>{% semantic_diff previous_version current_version 'may_contact' %}</td>
-  </tr>
-  <tr>
-    <th>email:</th>
-    <td>{% semantic_diff previous_version current_version 'email' %}</td>
-  </tr>
-  <tr>
-    <th>gender:</th>
-    <td>{% semantic_diff previous_version current_version 'gender' %}</td>
-  </tr>
-  <tr>
-    <th>airport:</th>
-    <td>{% semantic_diff previous_version current_version 'airport' %}</td>
-  </tr>
-  <tr>
-    <th>affiliation:</th>
-    <td>{% semantic_diff previous_version current_version 'affiliation' %}</td>
-  </tr>
-  <tr>
-    <th>github:</th>
-    <td>{% semantic_diff previous_version current_version 'github' %}</td>
-  </tr>
-  <tr>
-    <th>twitter:</th>
-    <td>{% semantic_diff previous_version current_version 'twitter' %}</td>
-  </tr>
-  <tr>
-    <th>url:</th>
-    <td>{% semantic_diff previous_version current_version 'url' %}</td>
-  </tr>
-  <tr>
-    <th>occupation:</th>
-    <td>{% semantic_diff previous_version current_version 'occupation' %}</td>
-  </tr>
-  <tr>
-    <th>ORCID ID:</th>
-    <td>{% semantic_diff previous_version current_version 'orcid' %}</td>
-  </tr>
-  <tr>
-    <th>notes:</th>
-    <td>{% semantic_diff previous_version current_version 'notes' %}</td>
-  </tr>
-</table>
-{% endblock %}
diff --git a/workshops/templatetags/diff.py b/workshops/templatetags/diff.py
index 9092fe5f..7d05ed17 100644
--- a/workshops/templatetags/diff.py
+++ b/workshops/templatetags/diff.py
@@ -1,4 +1,5 @@
 from django import template
+from django.db.models import Q
 from django.utils.safestring import mark_safe
 
 from reversion.helpers import generate_patch_html
@@ -9,3 +10,63 @@ register = template.Library()
 @register.simple_tag
 def semantic_diff(left, right, field):
     return mark_safe(generate_patch_html(left, right, field, cleanup='semantic'))
+
+
+@register.simple_tag
+def relation_diff(left, right, field):
+    model = field.related_model
+    if field.many_to_one or field.one_to_one:
+        # {left,right}.field_dict[field.name] is an integer or does not exist
+        # Cast it to a list(empty or single itemed)
+        if left.field_dict.get(field.name):
+            try:
+                left_PKs = [model.objects.get(pk=left.field_dict.get(field.name))]
+            except model.DoesNotExist:
+                left_PKs = [left.field_dict.get(field.name)]
+        else:
+            left_PKs = []
+        if right.field_dict.get(field.name):
+            try:
+                right_PKs = [model.objects.get(pk=right.field_dict.get(field.name))]
+            except model.DoesNotExist:
+                right_PKs = [right.field_dict.get(field.name)]
+        else:
+            right_PKs = []
+    else:
+        left_PKs = []
+        for pk in left.field_dict.get(field.name, []):
+            try:
+                left_PKs.append(model.objects.get(pk=pk))
+            except model.DoesNotExist:
+                left_PKs.append(pk)
+        right_PKs = []
+        for pk in right.field_dict.get(field.name, []):
+            try:
+                right_PKs.append(model.objects.get(pk=pk))
+            except model.DoesNotExist:
+                right_PKs.append(pk)
+    # Relations that exist only in the current version
+    additions = [obj for obj in right_PKs if obj not in left_PKs]
+    # Relations that exist only in the previous version
+    deletions = [obj for obj in left_PKs if obj not in right_PKs]
+    # Relations that exist only in both versions
+    consistent = [obj for obj in left_PKs if obj in right_PKs]
+    add_label = ''.join('<a class="label label-success" href="{}">+{}</a>'.format(
+            obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else '#',
+            obj
+        )
+        for obj in additions
+    )
+    delete_label = ''.join('<a class="label label-danger" href="{}">-{}</a>'.format(
+            obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else '#',
+            obj
+        )
+        for obj in deletions
+    )
+    consistent_label = ''.join('<a class="label label-default" href="{}">{}</a>'.format(
+            obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else '#',
+            obj
+        )
+        for obj in consistent
+    )
+    return mark_safe(''.join([consistent_label, add_label,delete_label]))
diff --git a/workshops/test/test_diff.py b/workshops/test/test_diff.py
index 543bd561..8aee427e 100644
--- a/workshops/test/test_diff.py
+++ b/workshops/test/test_diff.py
@@ -1,7 +1,7 @@
 from django.core.urlresolvers import reverse
 from reversion.revisions import get_for_object, create_revision
 
-from workshops.models import Event, Person
+from workshops.models import Event, Person, Tag
 
 from .base import TestBase
 
@@ -10,60 +10,87 @@ class TestRevisions(TestBase):
     def setUp(self):
         self._setUpUsersAndLogin()
         self._setUpHosts()
+        self.tag1, _ = Tag.objects.get_or_create(pk=1)
+        self.tag2, _ = Tag.objects.get_or_create(pk=2)
 
         with create_revision():
             self.event = Event.objects.create(host=self.host_alpha,
                                               slug='event')
+            self.event.tags.add(self.tag1)
+            self.event.save()
 
-        with create_revision():
-            self.person = Person.objects.create(username='gh',
-                                                personal='Hermione',
-                                                family='Granger')
-
-    def test_showing_diff_event(self):
-        # change something
         with create_revision():
             self.event.slug = 'better-event'
+            self.event.host = self.host_beta
+            self.event.tags.add(self.tag2)
             self.event.save()
 
         # load versions
         versions = get_for_object(self.event)
         assert len(versions) == 2
-        newer, older = versions
+        self.newer, self.older = versions
 
+    def test_showing_diff_event(self):
         # get newer revision page
         rv = self.client.get(reverse('object_changes',
-                                     args=[newer.revision.pk]))
-
+                                     args=[self.newer.revision.pk]))
         # test returned context
         context = rv.context
-        assert context['previous_version'] == older
-        assert context['current_version'] == newer
-        assert context['revision'] == newer.revision
+        assert context['previous_version'] == self.older
+        assert context['current_version'] == self.newer
+        assert context['revision'] == self.newer.revision
         assert context['object'] == self.event
         assert 'object_prev' in context
         assert context['object_prev'].__class__ == Event
 
-    def test_showing_diff_person(self):
-        # change something
-        with create_revision():
-            self.person.username = 'granger.hermione'
-            self.person.save()
-
-        # load versions
-        versions = get_for_object(self.person)
-        assert len(versions) == 2
-        newer, older = versions
 
+    def test_diff_shows_coloured_labels(self):
         # get newer revision page
         rv = self.client.get(reverse('object_changes',
-                                     args=[newer.revision.pk]))
+                                     args=[self.newer.revision.pk]))
+        # Red label for removed host
+        self.assertContains(rv,
+            '<a class="label label-danger" href="{}">-{}</a>'.format(
+                self.host_alpha.get_absolute_url(),
+                self.host_alpha
+            ),
+            html=True
+        )
+        # Green label for assigned host
+        self.assertContains(rv,
+            '<a class="label label-success" href="{}">+{}</a>'.format(
+                self.host_beta.get_absolute_url(),
+                self.host_beta
+            ),
+            html=True
+        )
+        # Grey label for pre-assigned tag
+        self.assertContains(rv,
+            '<a class="label label-default" href="#">{}</a>'.format(
+                self.tag1
+            ),
+            html=True
+        )
+        # Green label for additionally assigned tag
+        self.assertContains(rv,
+            '<a class="label label-success" href="#">+{}</a>'.format(
+                self.tag2
+            ),
+            html=True
+        )
 
-        # test returned context
-        context = rv.context
-        assert context['previous_version'] == older
-        assert context['current_version'] == newer
-        assert context['revision'] == newer.revision
-        assert context['object'] == self.person
-        assert 'object_prev' in context
-        assert context['object_prev'].__class__ == Person
+    def test_diff_shows_PK_for_deleted_relationships(self):
+        # Delete the tag
+        self.tag1.delete()
+        self.tag2.delete()
+        # get newer revision page
+        rv = self.client.get(reverse('object_changes',
+                                     args=[self.newer.revision.pk]))
+        self.assertContains(rv,
+            '<a class="label label-default" href="#">1</a>',
+            html=True
+        )
+        self.assertContains(rv,
+            '<a class="label label-success" href="#">+2</a>',
+            html=True
+        )
diff --git a/workshops/views.py b/workshops/views.py
index 25f01091..00e1564c 100644
--- a/workshops/views.py
+++ b/workshops/views.py
@@ -1923,18 +1923,13 @@ def object_changes(request, revision_id):
         'current_version': current_version,
         'revision': revision,
         'title': str(obj),
-    }
-    if obj.__class__ == Person:
-        return render(request, 'workshops/person_diff.html', context)
-    elif obj.__class__ == Event:
-        return render(request, 'workshops/event_diff.html', context)
-    else:
-        context['verbose_name'] = obj._meta.verbose_name
-        context['fields'] = [
+        'verbose_name': obj._meta.verbose_name,
+        'fields': [
             f for f in obj._meta.get_fields()
-            if f.concrete and not f.is_relation
-        ]
-        return render(request, 'workshops/object_diff.html', context)
+            if f.concrete
+        ],
+    }
+    return render(request, 'workshops/object_diff.html', context)
 
 # ------------------------------------------------------------
 
['workshops/test/test_diff.py', 'workshops/templatetags/diff.py', 'workshops/templates/workshops/object_diff.html', 'workshops/views.py']