start work on speaker and talk submissions

This commit is contained in:
Thomas Steen Rasmussen 2017-03-08 00:00:17 +01:00
parent 5f9f9bb1d4
commit 334f0477fe
9 changed files with 236 additions and 7 deletions

View File

@ -135,6 +135,16 @@ urlpatterns = [
SpeakerListView.as_view(),
name='speaker_index'
),
url(
r'^speakers/create/$',
SpeakerCreateView.as_view(),
name='speaker_create'
),
url(
r'^speakers/(?P<slug>[-_\w+]+)/edit/$',
SpeakerEditView.as_view(),
name='speaker_edit'
),
url(
r'^speakers/(?P<slug>[-_\w+]+)/$',
SpeakerDetailView.as_view(),

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-06 19:20
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('program', '0025_auto_20170306_1938'),
]
operations = [
migrations.AddField(
model_name='speaker',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-07 16:01
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('camps', '0019_auto_20170131_1849'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('program', '0026_speaker_user'),
]
operations = [
migrations.AlterUniqueTogether(
name='speaker',
unique_together=set([('camp', 'user'), ('camp', 'slug'), ('camp', 'name')]),
),
]

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-07 19:14
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('program', '0027_auto_20170307_1701'),
]
operations = [
migrations.AddField(
model_name='event',
name='submission_status',
field=models.CharField(choices=[('pending', 'Pending approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=50),
),
migrations.AddField(
model_name='speaker',
name='submission_status',
field=models.CharField(choices=[('pending', 'Pending approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=50),
),
]

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-07 19:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('program', '0028_auto_20170307_2014'),
]
operations = [
migrations.AlterField(
model_name='event',
name='submission_status',
field=models.CharField(choices=[('draft', 'Draft'), ('pending', 'Pending approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='draft', max_length=50),
),
migrations.AlterField(
model_name='speaker',
name='submission_status',
field=models.CharField(choices=[('draft', 'Draft'), ('pending', 'Pending approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='draft', max_length=50),
),
]

View File

@ -6,6 +6,37 @@ from django.utils.translation import ugettext_lazy as _
from utils.models import CreatedUpdatedModel
from django.core.exceptions import ValidationError
from datetime import timedelta
from django.core.urlresolvers import reverse_lazy
class UserSubmittedModel(CreatedUpdatedModel):
class Meta:
abstract = True
SUBMISSION_DRAFT = 'draft'
SUBMISSION_PENDING = 'pending'
SUBMISSION_APPROVED = 'approved'
SUBMISSION_REJECTED = 'rejected'
SUBMISSION_STATUSES = [
SUBMISSION_DRAFT,
SUBMISSION_PENDING,
SUBMISSION_APPROVED,
SUBMISSION_REJECTED
]
SUBMISSION_STATUS_CHOICES = [
(SUBMISSION_DRAFT, 'Draft'),
(SUBMISSION_PENDING, 'Pending approval'),
(SUBMISSION_APPROVED, 'Approved'),
(SUBMISSION_REJECTED, 'Rejected'),
]
submission_status = models.CharField(
max_length=50,
choices=SUBMISSION_STATUS_CHOICES,
default=SUBMISSION_DRAFT,
)
class EventLocation(CreatedUpdatedModel):
@ -34,7 +65,7 @@ class EventType(CreatedUpdatedModel):
return self.name
class Event(CreatedUpdatedModel):
class Event(UserSubmittedModel):
""" Something that is on the program one or more times. """
title = models.CharField(max_length=255)
slug = models.SlugField(blank=True, max_length=255)
@ -71,6 +102,9 @@ class Event(CreatedUpdatedModel):
return ", ".join(self.speakers.all().values_list('name', flat=True))
return False
def get_absolute_url(self):
return reverse_lazy('event_detail', kwargs={'camp_slug': self.camp.slug, 'slug': self.slug})
class EventInstance(CreatedUpdatedModel):
""" An instance of an event """
@ -123,7 +157,7 @@ def get_speaker_picture_upload_path(instance, filename):
}
class Speaker(CreatedUpdatedModel):
class Speaker(UserSubmittedModel):
""" A Person anchoring an event. """
name = models.CharField(max_length=150)
biography = models.TextField()
@ -136,9 +170,16 @@ class Speaker(CreatedUpdatedModel):
blank=True,
)
user = models.ForeignKey(
'auth.User',
on_delete=models.PROTECT,
null=True,
blank=True
)
class Meta:
ordering = ['name']
unique_together = (('camp', 'name'), ('camp', 'slug'))
unique_together = (('camp', 'name'), ('camp', 'slug'), ('camp', 'user'))
def __str__(self):
return '%s (%s)' % (self.name, self.camp)
@ -148,4 +189,7 @@ class Speaker(CreatedUpdatedModel):
self.slug = slugify(self.name)
super(Speaker, self).save(**kwargs)
def get_absolute_url(self):
return reverse_lazy('speaker_detail', kwargs={'camp_slug': self.camp.slug, 'slug': self.slug})

View File

@ -0,0 +1,14 @@
{% extends 'program_base.html' %}
{% load bootstrap3 %}
{% block program_content %}
<h3>{% if object %}Update{% else %}Create{% endif %} speaker biography</h3>
<form method="POST">
{% csrf_token %}
{% bootstrap_form form %}
{% bootstrap_button "Save as draft" button_type="submit" button_class="btn-primary" %}
{% bootstrap_button "Save and submit" button_type="submit" button_class="btn-primary" %}
</form>
{% endblock program_content %}

View File

@ -1,6 +1,7 @@
from collections import OrderedDict
import datetime
from django.views.generic import ListView, TemplateView, DetailView
from django.views.generic.edit import CreateView, UpdateView
from camps.mixins import CampViewMixin
from . import models
from django.http import Http404
@ -11,6 +12,75 @@ from django.views.decorators.http import require_safe
from django.http import Http404
from django.utils.decorators import method_decorator
from django.http import HttpResponse
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse
class SpeakerCreateView(LoginRequiredMixin, CampViewMixin, CreateView):
model = models.Speaker
fields = ['name', 'biography', 'picture_small', 'picture_large']
template_name = 'speaker_form.html'
def get(self, request, *args, **kwargs):
# first make sure we don't already have a speaker for this user for this camp
try:
speaker = models.Speaker.objects.get(user=request.user, camp=self.camp)
except models.Speaker.DoesNotExist:
# no speaker exists, just show the create speaker form
return super(SpeakerCreateView, self).get(request, *args, **kwargs)
# speaker already exists, where do we want to redirect?
if speaker.submission_status == models.Speaker.SUBMISSION_DRAFT:
messages.info(request, "You already have a draft speaker profile for %s, you can modify and submit it here" % self.camp.title)
return redirect('speaker_edit', camp_slug=self.camp.slug, slug=speaker.slug)
elif speaker.submission_status == models.Speaker.SUBMISSION_PENDING:
messages.info(request, "You already have a pending speaker profile for %s, you can modify and resubmit it here" % self.camp.title)
return redirect('speaker_edit', camp_slug=self.camp.slug, slug=speaker.slug)
elif speaker.submission_status == models.Speaker.SUBMISSION_REJECTED:
messages.info(request, "You already have a rejected speaker profile for %s, you can modify and resubmit it here" % self.camp.title)
return redirect('speaker_edit', camp_slug=self.camp.slug, slug=speaker.slug)
elif speaker.submission_status == models.Speaker.SUBMISSION_APPROVED:
messages.info(request, "You already have an accepted speaker profile for %s, please contact the organisers if you want to modify it." % self.camp.title)
return redirect('speaker_detail', camp_slug=self.camp.slug, slug=speaker.slug)
else:
# unknown submission status!
return
def form_valid(self, form):
# set camp before saving
form.instance.camp = self.camp
form.instance.user = self.request.user
speaker = form.save()
return redirect(reverse('speaker_detail', kwargs={'camp_slug': speaker.camp.slug, 'slug': speaker.slug}))
class SpeakerEditView(LoginRequiredMixin, CampViewMixin, UpdateView):
model = models.Speaker
fields = ['name', 'biography', 'picture_small', 'picture_large']
template_name = 'speaker_form.html'
def dispatch(self, request, *args, **kwargs):
# call super dispatch now because it ets self.camp which is needed below
response = super(SpeakerEditView, self).dispatch(request, *args, **kwargs)
# first make sure that this speaker belongs to the logged in user
if self.get_object().user.username != request.user.username:
messages.error(request, "No thanks")
return redirect(reverse('speaker_detail', kwargs={'camp_slug': self.get_object().camp.slug, 'slug': self.get_object().slug}))
if self.get_object().submission_status == models.Speaker.SUBMISSION_PENDING:
messages.info(request, "Your speaker profile for %s has already been submitted. If you modify it you will have to resubmit it." % self.get_object().camp.title)
elif self.get_object().submission_status == models.Speaker.SUBMISSION_REJECTED:
messages.info(request, "When you are done editing you will have to resubmit your speaker profile." % self.get_object().camp.title)
elif self.get_object().submission_status == models.Speaker.SUBMISSION_APPROVED:
messages.error(request, "Your speaker profile for %s has already been approved. Please contact the organisers if you want to modify it." % self.get_object().camp.title)
return redirect(reverse('speaker_detail', kwargs={'camp_slug': self.get_object().camp.slug, 'slug': self.get_object().slug}))
# alright, render the form
return super(SpeakerEditView, self).dispatch(request, *args, **kwargs)
@method_decorator(require_safe, name='dispatch')
class SpeakerPictureView(CampViewMixin, DetailView):

View File

@ -1,11 +1,7 @@
from django.core.urlresolvers import reverse_lazy
from django.db import models
from django.utils.text import slugify
from utils.models import CreatedUpdatedModel, UUIDModel
from .managers import VillageQuerySet