diff --git a/partners/forms.py b/partners/forms.py
index 0d62654327d6f48d2e3b9524ed0ab1ffdfdef485..32e4956b75281473bfb567a54da5ed1266126017 100644
--- a/partners/forms.py
+++ b/partners/forms.py
@@ -14,6 +14,140 @@ from .models import Partner, ProspectivePartner, ProspectiveContact, Prospective
 from scipost.models import TITLE_CHOICES
 
 
+class InstitutionForm(forms.ModelForm):
+    class Meta:
+        model = Institution
+        fields = (
+            'kind',
+            'name',
+            'acronym',
+            'address',
+            'country'
+        )
+
+
+class PartnerForm(forms.ModelForm):
+    class Meta:
+        model = Partner
+        fields = (
+            'institution',
+            'status',
+            'main_contact'
+        )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.fields['main_contact'].queryset = self.instance.contact_set.all()
+
+
+class ContactForm(forms.ModelForm):
+    """
+    This Contact form is mainly used for editing Contact instances.
+    """
+    class Meta:
+        model = Contact
+        fields = (
+            'kind',
+        )
+
+
+class NewContactForm(ContactForm):
+    """
+    This Contact form is used to create new Contact instances, as it will also handle
+    possible sending and activation of User instances coming with the new Contact.
+    """
+    title = forms.ChoiceField(choices=TITLE_CHOICES, label='Title')
+    first_name = forms.CharField()
+    last_name = forms.CharField()
+    email = forms.CharField()
+    existing_user = None
+
+    def __init__(self, *args, **kwargs):
+        """
+        Partner is a required argument to tell the formset which Partner the Contact
+        is being edited for in the current form.
+        """
+        self.partner = kwargs.pop('partner')
+        super().__init__(*args, **kwargs)
+
+    def clean_email(self):
+        """
+        Check if User already is known in the system.
+        """
+        email = self.cleaned_data['email']
+        try:
+            self.existing_user = User.objects.get(email=email)
+            if not self.data.get('confirm_use_existing', '') == 'on':
+                # Do not give error if user wants to use existing User
+                self.add_error('email', 'This User is already registered.')
+            self.fields['confirm_use_existing'] = forms.BooleanField(
+                required=False, initial=False, label='Use the existing user instead: %s %s'
+                                                     % (self.existing_user.first_name,
+                                                        self.existing_user.last_name))
+        except User.DoesNotExist:
+            pass
+        return email
+
+    def save(self, commit=True):
+        """
+        If existing user is found, add it to the Partner.
+        """
+        if self.existing_user and self.data.get('confirm_use_existing', '') == 'on':
+            # Do not create new Contact
+            try:
+                # Link Contact to new Partner
+                contact = self.existing_user.partner_contact
+                contact.partners.add(self.partner)
+                # TODO: Send mail to contact informing him/her about the new Partner
+            except Contact.DoesNotExist:
+                # Not yet a 'Contact-User'
+                contact = super().save(commit=False)
+                contact.title = self.existing_user.contributor.title
+                contact.user = self.existing_user
+                contact.save()
+                contact.partners.add(self.partner)
+                # TODO: Send mail to contact informing him/her about the new Partner
+            return contact
+
+        # Create complete new Account (User + Contact)
+        user = User(
+            first_name=self.cleaned_data['first_name'],
+            last_name=self.cleaned_data['last_name'],
+            email=self.cleaned_data['email'],
+            username=self.cleaned_data['email'],
+            is_active=False,
+        )
+        user.save()
+        contact = Contact(
+            user=user,
+            title=self.cleaned_data['title'],
+            kind=self.cleaned_data['kind']
+        )
+        contact.save()
+        contact.partners.add(self.partner)
+        # TODO: Send mail to contact to let him/her activate account
+        return contact
+
+
+class ContactFormset(forms.BaseModelFormSet):
+    """
+    Use custom formset to make sure the delete action will not delete an entire Contact
+    if the Contact still has relations with other Partners.
+    """
+    def __init__(self, *args, **kwargs):
+        """
+        Partner is a required argument to tell the formset which Partner the Contact
+        is being edited for in the current form.
+        """
+        self.partner = kwargs.pop('partner')
+        super().__init__(*args, **kwargs)
+
+    def delete_existing(self, obj, commit=True):
+        '''Deletes an existing model instance.'''
+        if commit:
+            obj.delete_or_remove_partner(self.partner)
+
+
 class PromoteToPartnerForm(forms.ModelForm):
     address = forms.CharField(widget=forms.Textarea(), required=False)
     acronym = forms.CharField()
diff --git a/partners/models.py b/partners/models.py
index 7148f51e6a55dcf32611f58856f2b94cdaba649a..5989cd4abc133c8fffa644bd2073f5cb5aed4de9 100644
--- a/partners/models.py
+++ b/partners/models.py
@@ -130,6 +130,16 @@ class Contact(models.Model):
     def __str__(self):
         return '%s %s, %s' % (self.get_title_display(), self.user.last_name, self.user.first_name)
 
+    def delete_or_remove_partner(self, partner, *args, **kwargs):
+        """
+        Custom `delete` method as the contact does not always need to be deleted,
+        but sometimes just the link with a specific partner needs to be removed.
+        """
+        self.partners.remove(partner)
+        if self.partners.exists():
+            return self
+        return super().delete(*args, **kwargs)
+
     @property
     def kind_display(self):
         """
diff --git a/partners/templates/partners/_partner_card.html b/partners/templates/partners/_partner_card.html
index bfc788abf946493146460ad73181ab23166b94ae..e9f858ee11268356861f7e56be0c1b43ed2d69b7 100644
--- a/partners/templates/partners/_partner_card.html
+++ b/partners/templates/partners/_partner_card.html
@@ -20,7 +20,7 @@
       <ul>
           {% for contact in partner.contact_set.all %}
               <li>
-                  <h4>{{ contact.get_title_display }} {{ contact.user.first_name }} {{ contact.user.last_name }}</h4>
+                  <h4>{{ contact.get_title_display }} {{ contact.user.first_name }} {{ contact.user.last_name }} {% if not contact.user.is_active %}<span class="label label-sm label-warning">Inactive</span>{% endif %}</h4>
                   <div>({{ contact.kind_display }})</div>
                   <div class="mb-2"><a href="mailto:{{ contact.user.email }}">{{ contact.user.email }}</a></div>
               </li>
@@ -28,7 +28,13 @@
       </ul>
     </div>
     <div class="col-md-3">
-      <p>Edit</p>
+        <h3>Actions</h3>
+        <ul>
+            <li><a href="{% url 'partners:partner_edit' partner.id %}">Edit Partner</a></li>
+            <li><a href="{% url 'partners:institution_edit' partner.institution.id %}">Edit Institution</a></li>
+            <li><a href="{% url 'partners:partner_add_contact' partner.id %}">Add Contact</a></li>
+        </ul>
+
     </div>
   </div>
 </div>
diff --git a/partners/templates/partners/dashboard.html b/partners/templates/partners/dashboard.html
index a7b5c0a0a7227efd51264bfaa989f41379139275..30a53fb49169641a39d0b862ad8ae7de2041ab84 100644
--- a/partners/templates/partners/dashboard.html
+++ b/partners/templates/partners/dashboard.html
@@ -59,8 +59,8 @@
             <div class="col-md-6">
                 <h3>Partners</h3>
                 <ul>
-                    {% for partner in request.user.partners.all %}
-                        <li>{{partner}}</li>
+                    {% for partner in request.user.partner_contact.partners.all %}
+                        <li>{{partner.institution}}</li>
                     {% empty %}
                         <li>No partners found. Please contact the SciPost admin.</li>
                     {% endfor %}
diff --git a/partners/templates/partners/institution_edit.html b/partners/templates/partners/institution_edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..69133f2840bc995a941f4390bf080becdbadcec4
--- /dev/null
+++ b/partners/templates/partners/institution_edit.html
@@ -0,0 +1,33 @@
+{% extends 'partners/_partners_page_base.html' %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Edit Institution</span>
+{% endblock %}
+
+{% block pagetitle %}{{block.super}} Edit Institution{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Edit Institution {{institution}}</h1>
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+      <form method="post">
+        {% csrf_token %}
+        <div class="mb-5">
+            {{ form|bootstrap }}
+        </div>
+
+        <input class="btn btn-primary" type="submit" value="Submit"/>
+      </form>
+    </div>
+</div>
+
+{% endblock content %}
diff --git a/partners/templates/partners/partner_add_contact.html b/partners/templates/partners/partner_add_contact.html
new file mode 100644
index 0000000000000000000000000000000000000000..cde33236f75bc734284971ed5f8805edaf364115
--- /dev/null
+++ b/partners/templates/partners/partner_add_contact.html
@@ -0,0 +1,33 @@
+{% extends 'partners/_partners_page_base.html' %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Add Contact</span>
+{% endblock %}
+
+{% block pagetitle %}{{block.super}} Add Contact{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Add Contact for Partner {{partner}}</h1>
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+      <form method="post">
+        {% csrf_token %}
+        <div class="mb-5">
+            {{ form|bootstrap }}
+        </div>
+
+        <input class="btn btn-primary" type="submit" value="Submit"/>
+      </form>
+    </div>
+</div>
+
+{% endblock content %}
diff --git a/partners/templates/partners/partner_edit.html b/partners/templates/partners/partner_edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..434e5832b21f8c7581476c22b250a3197db434af
--- /dev/null
+++ b/partners/templates/partners/partner_edit.html
@@ -0,0 +1,64 @@
+{% extends 'partners/_partners_page_base.html' %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Edit Partner</span>
+{% endblock %}
+
+{% block pagetitle %}{{block.super}} Edit Partner{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Edit Partner</h1>
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+      <form method="post">
+        {% csrf_token %}
+        <div class="mb-5">
+            {{ form|bootstrap }}
+        </div>
+
+        <h2>Contacts</h2>
+        {{ contact_formset.management_form }}
+        {% for form in contact_formset %}
+            <div class="contact-form-group">
+                <h3>{{form.instance}}</h3>
+                <p>{{ form.instance.user.email }}</p>
+                <div class="mb-3">{{ form|bootstrap }}</div>
+            </div>
+        {% endfor %}
+
+        <input class="btn btn-primary" type="submit" value="Submit"/>
+      </form>
+    </div>
+</div>
+
+{% endblock content %}
+
+{% block footer_script %}
+<script>
+    function delete_hide_contact_groups(delete_input) {
+        input_el = $(delete_input);
+        if( input_el.prop('checked') ) {
+            input_el
+            .parents('.contact-form-group')
+            .addClass('delete-form-group');
+        } else {
+            input_el
+            .parents('.contact-form-group')
+            .removeClass('delete-form-group');
+        }
+    }
+
+    $('.contact-form-group [name$="DELETE"]').on('change click', function() {
+        delete_hide_contact_groups(this);
+    });
+</script>
+{% endblock %}
diff --git a/partners/urls.py b/partners/urls.py
index 3297d6d0d184e9c10bf1f87d1fc3af244a47aff6..3c3e1d14fc31304bd9cb181604353b4e7ea66f43 100644
--- a/partners/urls.py
+++ b/partners/urls.py
@@ -6,14 +6,25 @@ urlpatterns = [
     url(r'^$', views.supporting_partners, name='partners'),
     url(r'^dashboard$', views.dashboard, name='dashboard'),
     url(r'^membership_request$', views.membership_request, name='membership_request'),
-    url(r'^prospect_partners/add$', views.add_prospective_partner,
+
+    # Prospects
+    url(r'^prospects/add$', views.add_prospective_partner,
         name='add_prospective_partner'),
-    url(r'^prospect_partners/contacts/(?P<contact_id>[0-9]+)/email$',
+    url(r'^prospects/contacts/(?P<contact_id>[0-9]+)/email$',
         views.email_prospartner_contact, name='email_prospartner_contact'),
-    url(r'^prospect_partner/(?P<prospartner_id>[0-9]+)/contacts/add$',
+    url(r'^prospects/(?P<prospartner_id>[0-9]+)/contacts/add$',
         views.add_prospartner_contact, name='add_prospartner_contact'),
-    url(r'^prospect_partner/(?P<prospartner_id>[0-9]+)/promote$',
+    url(r'^prospects/(?P<prospartner_id>[0-9]+)/promote$',
         views.promote_prospartner, name='promote_prospartner'),
-    url(r'^prospect_partner/(?P<prospartner_id>[0-9]+)/events/add$',
+    url(r'^prospects/(?P<prospartner_id>[0-9]+)/events/add$',
         views.add_prospartner_event, name='add_prospartner_event'),
+
+    # Institutions
+    url(r'institutions/(?P<institution_id>[0-9]+)/edit$', views.institution_edit,
+        name='institution_edit'),
+
+    # Partners
+    url(r'(?P<partner_id>[0-9]+)/edit$', views.partner_edit, name='partner_edit'),
+    url(r'(?P<partner_id>[0-9]+)/contacts/add$', views.partner_add_contact,
+        name='partner_add_contact'),
 ]
diff --git a/partners/views.py b/partners/views.py
index 83b383e5f3c9f10cd19a541e433425a148c6a119..6d0265f2042387775ccae563f2ebf3af7bedf3c4 100644
--- a/partners/views.py
+++ b/partners/views.py
@@ -1,6 +1,6 @@
 from django.contrib import messages
 from django.db import transaction
-from django.forms import modelformset_factory, formset_factory
+from django.forms import modelformset_factory
 from django.shortcuts import get_object_or_404, render, reverse, redirect
 from django.utils import timezone
 
@@ -10,10 +10,12 @@ from .constants import PROSPECTIVE_PARTNER_REQUESTED,\
     PROSPECTIVE_PARTNER_APPROACHED, PROSPECTIVE_PARTNER_ADDED,\
     PROSPECTIVE_PARTNER_EVENT_REQUESTED, PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT
 from .models import Partner, ProspectivePartner, ProspectiveContact,\
-    ProspectivePartnerEvent, MembershipAgreement
+                    ProspectivePartnerEvent, MembershipAgreement, Contact, Institution
 from .forms import ProspectivePartnerForm, ProspectiveContactForm,\
-    EmailProspectivePartnerContactForm, PromoteToPartnerForm,\
-    ProspectivePartnerEventForm, MembershipQueryForm, PromoteToContactForm, PromoteToContactFormset
+                   EmailProspectivePartnerContactForm, PromoteToPartnerForm,\
+                   ProspectivePartnerEventForm, MembershipQueryForm, PromoteToContactForm,\
+                   PromoteToContactFormset, PartnerForm, ContactForm, ContactFormset,\
+                   NewContactForm, InstitutionForm
 
 from .utils import PartnerUtils
 
@@ -100,6 +102,69 @@ def promote_prospartner(request, prospartner_id):
     return render(request, 'partners/promote_prospartner.html', context)
 
 
+###############
+# Partner views
+###############
+@permission_required('scipost.can_manage_SPB', return_403=True)
+@transaction.atomic
+def partner_edit(request, partner_id):
+    partner = get_object_or_404(Partner, id=partner_id)
+
+    # Start/fill forms
+    form = PartnerForm(request.POST or None, instance=partner)
+    ContactModelFormset = modelformset_factory(Contact, ContactForm, can_delete=True, extra=0,
+                                               formset=ContactFormset)
+    contact_formset = ContactModelFormset(request.POST or None, partner=partner,
+                                          queryset=partner.contact_set.all())
+
+    # Validate forms for POST request
+    if form.is_valid() and contact_formset.is_valid():
+        form.save()
+        contact_formset.save()
+        messages.success(request, 'Partner saved')
+        return redirect(reverse('partners:partner_edit', args=(partner.id,)))
+    context = {
+        'form': form,
+        'contact_formset': contact_formset
+    }
+    return render(request, 'partners/partner_edit.html', context)
+
+
+@permission_required('scipost.can_manage_SPB', return_403=True)
+def partner_add_contact(request, partner_id):
+    partner = get_object_or_404(Partner, id=partner_id)
+    form = NewContactForm(request.POST or None, partner=partner)
+    if form.is_valid():
+        contact = form.save()
+        messages.success(request, '<h3>Created contact: %s</h3>Email has been sent.'
+                                  % str(contact))
+        return redirect(reverse('partners:dashboard'))
+    context = {
+        'partner': partner,
+        'form': form
+    }
+    return render(request, 'partners/partner_add_contact.html', context)
+
+
+###################
+# Institution Views
+###################
+@permission_required('scipost.can_manage_SPB', return_403=True)
+def institution_edit(request, institution_id):
+    institution = get_object_or_404(Institution, id=institution_id)
+    form = InstitutionForm(request.POST or None, instance=institution)
+    if form.is_valid():
+        form.save()
+        return redirect(reverse('partners:dashboard'))
+    context = {
+        'form': form
+    }
+    return render(request, 'partners/institution_edit.html', context)
+
+
+###########################
+# Prospective Partner Views
+###########################
 @permission_required('scipost.can_manage_SPB', return_403=True)
 def add_prospective_partner(request):
     form = ProspectivePartnerForm(request.POST or None)
@@ -132,11 +197,11 @@ def email_prospartner_contact(request, contact_id):
     if form.is_valid():
         comments = 'Email sent to %s.' % str(contact)
         prospartnerevent = ProspectivePartnerEvent(
-            prospartner = contact.prospartner,
-            event = PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT,
-            comments = comments,
-            noted_on = timezone.now(),
-            noted_by = request.user.contributor)
+            prospartner=contact.prospartner,
+            event=PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT,
+            comments=comments,
+            noted_on=timezone.now(),
+            noted_by=request.user.contributor)
         prospartnerevent.save()
         if contact.prospartner.status in [PROSPECTIVE_PARTNER_REQUESTED,
                                           PROSPECTIVE_PARTNER_ADDED]:
diff --git a/scipost/static/scipost/assets/css/_form.scss b/scipost/static/scipost/assets/css/_form.scss
index 8c268068e91ec2143644abb1e9a91646fa8435f2..60f2289b07992d78f8c5cb1eed829d31add22677 100644
--- a/scipost/static/scipost/assets/css/_form.scss
+++ b/scipost/static/scipost/assets/css/_form.scss
@@ -47,3 +47,27 @@ input[type="file"] {
     border: 1px solid rgba(0, 0, 0, 0.15);
     border-radius: 0.15rem;
 }
+
+// Formset
+//
+.delete-form-group {
+    > * {
+        opacity: 0.5;
+        color: $brand-danger;
+
+        &:last-child {
+            // The delete button should always be visible
+            opacity: 1.0;
+            color: inherit;
+        }
+    }
+
+    .form-group {
+        display: none;
+
+        &:last-child {
+            // The delete button should always be visible
+            display: block;
+        }
+    }
+}