diff --git a/cfp/templates/cfp/participant_confirm_delete.html b/cfp/templates/cfp/participant_confirm_delete.html
new file mode 100644
index 0000000..f8dbf19
--- /dev/null
+++ b/cfp/templates/cfp/participant_confirm_delete.html
@@ -0,0 +1,21 @@
+{% extends 'base.html' %}
+
+{% load crispy_forms_tags i18n %}
+
+{% block content %}
+
+{% endblock %}
diff --git a/cfp/templates/cfp/staff/participant_details.html b/cfp/templates/cfp/staff/participant_details.html
index 323343b..35dc4b3 100644
--- a/cfp/templates/cfp/staff/participant_details.html
+++ b/cfp/templates/cfp/staff/participant_details.html
@@ -10,7 +10,12 @@
{% if participant.vip %}{% trans "VIP" %}{% endif %}
-{% trans "Edit" %}
+
+{% trans "Edit" %}
+{% if not participant.talk_set.exists %} -
+{% trans "Remove" %}
+{% endif %}
+
{% trans "Biography" %}
{{ participant.biography|linebreaksbr }}
diff --git a/cfp/urls.py b/cfp/urls.py
index 13dd32a..3b7fcbf 100644
--- a/cfp/urls.py
+++ b/cfp/urls.py
@@ -42,6 +42,7 @@ urlpatterns = [
url(r'^staff/speakers/(?P[0-9]+)/$', views.participant_details, name='participant-details'),
url(r'^staff/speakers/(?P[0-9]+)/add-talk/$', views.participant_add_talk, name='participant-add-talk'),
url(r'^staff/speakers/(?P[0-9]+)/edit/$', views.ParticipantUpdate.as_view(), name='participant-edit'),
+ url(r'^staff/speakers/(?P[0-9]+)/remove/$', views.ParticipantRemove.as_view(), name='participant-remove'),
url(r'^staff/tracks/$', views.TrackList.as_view(), name='track-list'),
url(r'^staff/tracks/add/$', views.TrackCreate.as_view(), name='track-add'),
url(r'^staff/tracks/(?P[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='track-edit'),
diff --git a/cfp/views.py b/cfp/views.py
index 7be8dcd..75c1881 100644
--- a/cfp/views.py
+++ b/cfp/views.py
@@ -4,9 +4,9 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
-from django.views.generic import FormView, TemplateView
+from django.views.generic import DeleteView, FormView, TemplateView
from django.contrib import messages
-from django.db.models import Q
+from django.db.models import Q, Count
from django.views.generic import CreateView, DetailView, ListView, UpdateView
from django.http import HttpResponse, Http404
from django.utils import timezone
@@ -824,6 +824,15 @@ class ParticipantUpdate(StaffRequiredMixin, OnSiteFormMixin, UpdateView):
)
+class ParticipantRemove(StaffRequiredMixin, OnSiteFormMixin, DeleteView):
+ slug_field = 'pk'
+ slug_url_kwarg = 'participant_id'
+ success_url = reverse_lazy('participant-list')
+
+ def get_queryset(self):
+ return Participant.objects.annotate(talk_count=Count('talk')).filter(talk_count=0)
+
+
@staff_required
def participant_add_talk(request, participant_id):
participant = get_object_or_404(Participant, site=request.conference.site, pk=participant_id)