From a715cba597e610b9ca0c7468f76446ad47a0c5fe Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Thu, 16 Mar 2017 00:30:59 +0100 Subject: [PATCH] add admin commands to approve speaker and event proposals --- src/program/admin.py | 14 +++++- .../migrations/0036_auto_20170316_0004.py | 26 +++++++++++ src/program/mixins.py | 2 +- src/program/models.py | 43 ++++++++++++++++++- src/program/templates/proposal_list.html | 8 +++- 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 src/program/migrations/0036_auto_20170316_0004.py diff --git a/src/program/admin.py b/src/program/admin.py index 37f7fe51..81e2ee27 100644 --- a/src/program/admin.py +++ b/src/program/admin.py @@ -5,12 +5,22 @@ from .models import Event, Speaker, EventType, EventInstance, EventLocation, Spe @admin.register(SpeakerProposal) class SpeakerProposalAdmin(admin.ModelAdmin): - pass + def mark_speakerproposal_as_approved(self, request, queryset): + for sp in queryset: + sp.mark_as_approved() + mark_speakerproposal_as_approved.description = 'Approve and create Speaker object(s)' + + actions = ['mark_speakerproposal_as_approved'] @admin.register(EventProposal) class EventProposalAdmin(admin.ModelAdmin): - pass + def mark_eventproposal_as_approved(self, request, queryset): + for ep in queryset: + ep.mark_as_approved() + mark_eventproposal_as_approved.description = 'Approve and create Event object(s)' + + actions = ['mark_eventproposal_as_approved'] @admin.register(EventLocation) diff --git a/src/program/migrations/0036_auto_20170316_0004.py b/src/program/migrations/0036_auto_20170316_0004.py new file mode 100644 index 00000000..e2168fdc --- /dev/null +++ b/src/program/migrations/0036_auto_20170316_0004.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-03-15 23:04 +from __future__ import unicode_literals + +from django.db import migrations, models +import program.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0035_auto_20170314_2325'), + ] + + operations = [ + migrations.AlterField( + model_name='speakerproposal', + name='picture_large', + field=models.ImageField(blank=True, help_text='A picture of the speaker', max_length=255, null=True, storage=program.models.CustomUrlStorage(), upload_to=program.models.get_speakerproposal_picture_upload_path), + ), + migrations.AlterField( + model_name='speakerproposal', + name='picture_small', + field=models.ImageField(blank=True, help_text='A thumbnail of the speaker picture', max_length=255, null=True, storage=program.models.CustomUrlStorage(), upload_to=program.models.get_speakerproposal_picture_upload_path), + ), + ] diff --git a/src/program/mixins.py b/src/program/mixins.py index 6d7ac60f..34004532 100644 --- a/src/program/mixins.py +++ b/src/program/mixins.py @@ -18,7 +18,7 @@ class EnsureUnapprovedProposalMixin(SingleObjectMixin): def dispatch(self, request, *args, **kwargs): # do not permit editing if the proposal is already approved if self.get_object().proposal_status == models.UserSubmittedModel.PROPOSAL_APPROVED: - messages.error(request, "This proposal has already been approved. Please contact the organisers if you need to modify something." % self.camp.title) + messages.error(request, "This proposal has already been approved. Please contact the organisers if you need to modify something.") return redirect(reverse('proposal_list', kwargs={'camp_slug': self.camp.slug})) # alright, continue with the request diff --git a/src/program/models.py b/src/program/models.py index d235cbad..106ea701 100644 --- a/src/program/models.py +++ b/src/program/models.py @@ -7,10 +7,11 @@ from utils.models import CreatedUpdatedModel, CampRelatedModel from django.core.exceptions import ValidationError from datetime import timedelta from django.core.urlresolvers import reverse_lazy -import uuid +import uuid, os from django.core.files.storage import FileSystemStorage from django.urls import reverse from django.apps import apps +from django.core.files.base import ContentFile class CustomUrlStorage(FileSystemStorage): @@ -138,6 +139,7 @@ class SpeakerProposal(UserSubmittedModel): upload_to=get_speakerproposal_picture_upload_path, help_text='A picture of the speaker', storage=storage, + max_length=255 ) picture_small = models.ImageField( @@ -146,6 +148,7 @@ class SpeakerProposal(UserSubmittedModel): upload_to=get_speakerproposal_picture_upload_path, help_text='A thumbnail of the speaker picture', storage=storage, + max_length=255 ) @property @@ -155,6 +158,26 @@ class SpeakerProposal(UserSubmittedModel): def get_absolute_url(self): return reverse_lazy('speakerproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid}) + def mark_as_approved(self): + speakermodel = apps.get_model('program', 'speaker') + speakerproposalmodel = apps.get_model('program', 'speakerproposal') + speaker = speakermodel() + speaker.camp = self.camp + speaker.name = self.name + speaker.biography = self.biography + if self.picture_small and self.picture_large: + temp = ContentFile(self.picture_small.read()) + temp.name = os.path.basename(self.picture_small.name) + speaker.picture_small = temp + temp = ContentFile(self.picture_large.read()) + temp.name = os.path.basename(self.picture_large.name) + speaker.picture_large = temp + speaker.proposal = self + speaker.save() + + self.proposal_status = speakerproposalmodel.PROPOSAL_APPROVED + self.save() + class EventProposal(UserSubmittedModel): """ An event proposal """ @@ -191,6 +214,24 @@ class EventProposal(UserSubmittedModel): def get_absolute_url(self): return reverse_lazy('eventproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid}) + def mark_as_approved(self): + eventmodel = apps.get_model('program', 'event') + eventproposalmodel = apps.get_model('program', 'eventproposal') + event = eventmodel() + event.camp = self.camp + event.title = self.title + event.abstract = self.abstract + event.event_type = self.event_type + event.proposal = self + event.save() + # loop through the speakerproposals linked to this eventproposal and associate any related speaker objects with this event + for sp in self.speakers.all(): + if sp.speaker: + event.speaker_set.add(sp.speaker) + + self.proposal_status = eventproposalmodel.PROPOSAL_APPROVED + self.save() + ############################################################################################# diff --git a/src/program/templates/proposal_list.html b/src/program/templates/proposal_list.html index 7aa1374f..f65b1ab4 100644 --- a/src/program/templates/proposal_list.html +++ b/src/program/templates/proposal_list.html @@ -24,8 +24,12 @@ Proposals | {{ block.super }} Details {% if not camp.read_only %} - Modify - {% if speakerproposal.proposal_status == "pending" %} + {% if speakerproposal.proposal_status == "approved" %} + Modify + {% else %} + Modify + {% endif %} + {% if speakerproposal.proposal_status == "pending" or speakerproposal.proposal_status == "approved" %} Submit {% else %} Submit