diff --git a/apps/activity/forms.py b/apps/activity/forms.py
index 081f611cc256ad61e7d3bfb0d952f98cab09e35d..6ef8a27852ae8cf421b9043a35b71ec2142bce4f 100644
--- a/apps/activity/forms.py
+++ b/apps/activity/forms.py
@@ -2,10 +2,13 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from django import forms
-from activity.models import Activity
+from django.contrib.contenttypes.models import ContentType
 from member.models import Club
+from note.models import NoteUser
 from note_kfet.inputs import DateTimePickerInput, AutocompleteModelSelect
 
+from .models import Activity, Guest
+
 
 class ActivityForm(forms.ModelForm):
     class Meta:
@@ -23,3 +26,28 @@ class ActivityForm(forms.ModelForm):
             "date_start": DateTimePickerInput(),
             "date_end": DateTimePickerInput(),
         }
+
+
+class GuestForm(forms.ModelForm):
+    def clean(self, **kwargs):
+        cleaned_data = super().clean()
+
+        self.instance.activity = cleaned_data["activity"] = Activity.objects.get(pk=1)
+
+        return cleaned_data
+
+    class Meta:
+        model = Guest
+        fields = ('last_name', 'first_name', 'inviter', )
+        widgets = {
+            "inviter": AutocompleteModelSelect(
+                NoteUser,
+                attrs={
+                    'api_url': '/api/note/note/',
+                    # We don't evaluate the content type at launch because the DB might be not initialized
+                    'api_url_suffix':
+                        lambda value: '&polymorphic_ctype=' + str(ContentType.objects.get_for_model(NoteUser).pk),
+                    'placeholder': 'Note ...',
+                },
+            ),
+        }
diff --git a/apps/activity/models.py b/apps/activity/models.py
index 8f23060cddd71543003821bf3d27e0366fcb89c2..7151a2a0569df0d7db61d9ca2d77acaac61f42b8 100644
--- a/apps/activity/models.py
+++ b/apps/activity/models.py
@@ -1,9 +1,9 @@
 # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
 # SPDX-License-Identifier: GPL-3.0-or-later
 
-from django.conf import settings
 from django.db import models
 from django.utils.translation import gettext_lazy as _
+from note.models import NoteUser
 
 
 class ActivityType(models.Model):
@@ -77,6 +77,18 @@ class Activity(models.Model):
         verbose_name_plural = _("activities")
 
 
+class Entry(models.Model):
+    time = models.DateTimeField(
+        verbose_name=_("entry time"),
+    )
+
+    note = models.ForeignKey(
+        NoteUser,
+        on_delete=models.PROTECT,
+        verbose_name=_("note"),
+    )
+
+
 class Guest(models.Model):
     """
     People who are not current members of any clubs, and are invited by someone who is a current member.
@@ -86,17 +98,30 @@ class Guest(models.Model):
         on_delete=models.PROTECT,
         related_name='+',
     )
-    name = models.CharField(
+
+    last_name = models.CharField(
         max_length=255,
+        verbose_name=_("last name"),
     )
+
+    first_name = models.CharField(
+        max_length=255,
+        verbose_name=_("first name"),
+    )
+
     inviter = models.ForeignKey(
-        settings.AUTH_USER_MODEL,
+        NoteUser,
         on_delete=models.PROTECT,
         related_name='+',
+        verbose_name=_("inviter"),
     )
-    entry = models.DateTimeField(
+
+    entry = models.OneToOneField(
+        Entry,
+        on_delete=models.PROTECT,
         null=True,
     )
+
     entry_transaction = models.ForeignKey(
         'note.Transaction',
         on_delete=models.PROTECT,
diff --git a/apps/activity/tables.py b/apps/activity/tables.py
new file mode 100644
index 0000000000000000000000000000000000000000..44939bc455d4632ab8f61dd99f66d45791696253
--- /dev/null
+++ b/apps/activity/tables.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from django.utils.translation import gettext_lazy as _
+from django_tables2 import tables, A
+
+from .models import Activity, Guest
+
+
+class ActivityTable(tables.Table):
+    name = tables.columns.LinkColumn('activity:activity_detail',
+                                     args=[A('pk'), ],)
+
+    invite = tables.columns.LinkColumn('activity:activity_invite',
+                                       args=[A('pk'), ],
+                                       verbose_name=_("Invite"),
+                                       text=_("Invite"),)
+
+    class Meta:
+        attrs = {
+            'class': 'table table-condensed table-striped table-hover'
+        }
+        model = Activity
+        template_name = 'django_tables2/bootstrap4.html'
+        fields = ('name', 'activity_type', 'organizer', 'attendees_club', 'date_start', 'date_end', 'invite', )
+
+
+class GuestTable(tables.Table):
+    class Meta:
+        attrs = {
+            'class': 'table table-condensed table-striped table-hover'
+        }
+        model = Guest
+        template_name = 'django_tables2/bootstrap4.html'
+        fields = ('name', 'inviter', )
+        row_attrs = {
+            'class': 'table-row',
+            'id': lambda record: "row-" + str(record.pk),
+            'data-href': lambda record: record.pk
+        }
diff --git a/apps/activity/urls.py b/apps/activity/urls.py
index fc0b4850a17372c1528b9879b724cf7e029ca6b0..006dcce3c064113f6f7b003bf93b340142549c2a 100644
--- a/apps/activity/urls.py
+++ b/apps/activity/urls.py
@@ -10,6 +10,7 @@ app_name = 'activity'
 urlpatterns = [
     path('', views.ActivityListView.as_view(), name='activity_list'),
     path('<int:pk>/', views.ActivityDetailView.as_view(), name='activity_detail'),
+    path('<int:activity_pk>/invite/', views.ActivityInviteView.as_view(), name='activity_invite'),
     path('<int:pk>/entry/', views.ActivityEntryView.as_view(), name='activity_entry'),
     path('<int:pk>/update/', views.ActivityUpdateView.as_view(), name='activity_update'),
     path('new/', views.ActivityCreateView.as_view(), name='activity_create'),
diff --git a/apps/activity/views.py b/apps/activity/views.py
index be3db16d3a12e4593c9c8c456b8720008e978f07..03fa793f7dc1be545c7d33fd256ca0cfd059e448 100644
--- a/apps/activity/views.py
+++ b/apps/activity/views.py
@@ -7,8 +7,9 @@ from django.views.generic import CreateView, DetailView, UpdateView, TemplateVie
 from django.utils.translation import gettext_lazy as _
 from django_tables2.views import SingleTableView
 
-from .forms import ActivityForm
-from .models import Activity
+from .forms import ActivityForm, GuestForm
+from .models import Activity, Guest
+from .tables import ActivityTable
 
 
 class ActivityCreateView(LoginRequiredMixin, CreateView):
@@ -19,6 +20,7 @@ class ActivityCreateView(LoginRequiredMixin, CreateView):
 
 class ActivityListView(LoginRequiredMixin, SingleTableView):
     model = Activity
+    table_class = ActivityTable
 
     def get_context_data(self, **kwargs):
         ctx = super().get_context_data(**kwargs)
@@ -38,5 +40,12 @@ class ActivityUpdateView(LoginRequiredMixin, UpdateView):
     success_url = reverse_lazy('activity:activity_list')
 
 
+class ActivityInviteView(LoginRequiredMixin, CreateView):
+    model = Guest
+    form_class = GuestForm
+    success_url = reverse_lazy('activity:activity_list')
+    template_name = "activity/activity_invite.html"
+
+
 class ActivityEntryView(LoginRequiredMixin, TemplateView):
     pass
diff --git a/apps/member/forms.py b/apps/member/forms.py
index 52dde34a676ea3044a51f53cdd9f3f1a7c00833d..76cd146b1968ff4d95a6742de7cdbe36534e75e2 100644
--- a/apps/member/forms.py
+++ b/apps/member/forms.py
@@ -7,7 +7,6 @@ from crispy_forms.layout import Layout
 from django import forms
 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
 from django.contrib.auth.models import User
-
 from note_kfet.inputs import AutocompleteModelSelect
 from permission.models import PermissionMask
 
diff --git a/apps/note/urls.py b/apps/note/urls.py
index 1bc12b4d163a80b3363b5085aab9555677175a88..9d6af317031ede8fdb8927dae1a82eda5b74e210 100644
--- a/apps/note/urls.py
+++ b/apps/note/urls.py
@@ -4,7 +4,6 @@
 from django.urls import path
 
 from . import views
-from .models import Note
 
 app_name = 'note'
 urlpatterns = [
diff --git a/note_kfet/inputs.py b/note_kfet/inputs.py
index 35b8b605e9617981e66e7e813bb24a616e506bbe..e012c1c2792b73da810c57f72be6db88cad7e271 100644
--- a/note_kfet/inputs.py
+++ b/note_kfet/inputs.py
@@ -40,12 +40,6 @@ class AutocompleteModelSelect(Select):
             return str(self.model.objects.get(pk=int(value)))
         return ""
 
-    def value_from_datadict(self, data, files, name):
-        val = super().value_from_datadict(data, files, name)
-        print(data)
-        print(self.attrs)
-        return val
-
 
 """
 The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github:
diff --git a/templates/activity/activity_invite.html b/templates/activity/activity_invite.html
new file mode 100644
index 0000000000000000000000000000000000000000..8bdb19657cb03900cab8426e4c57ed5f80f8f010
--- /dev/null
+++ b/templates/activity/activity_invite.html
@@ -0,0 +1,15 @@
+{% extends "base.html" %}
+{% load render_table from django_tables2 %}
+{% load i18n crispy_forms_tags %}
+{% block content %}
+    <form method="post">
+        {% csrf_token %}
+        {{ form|crispy }}
+        <button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
+    </form>
+{% endblock %}
+
+{% block extrajavascript %}
+    <script type="text/javascript">
+    </script>
+{% endblock %}