diff --git a/events/admin.py b/events/admin.py index 97e95f9..1e27747 100644 --- a/events/admin.py +++ b/events/admin.py @@ -10,8 +10,6 @@ from .models.profiles import ( Member, Category, Topic, - Speaker, - Talk, ) from .models.search import Searchable from .models.events import ( @@ -22,7 +20,12 @@ from .models.events import ( EventPhoto, CommonEvent, Attendee, +) +from .models.speakers import ( + Speaker, + Talk, Presentation, + SpeakerRequest, ) admin.site.register(Language) diff --git a/events/forms.py b/events/forms.py index b16a66a..18552a1 100644 --- a/events/forms.py +++ b/events/forms.py @@ -6,7 +6,7 @@ from django.utils import timezone from django.contrib.auth.models import User from .models.locale import Country, SPR, City -from .models.profiles import Team, UserProfile, Speaker, Talk +from .models.profiles import Team, UserProfile from .models.events import ( Event, EventComment, @@ -14,6 +14,10 @@ from .models.events import ( EventSeries, Place, EventPhoto, +) +from .models.speakers import ( + Speaker, + Talk, Presentation, SpeakerRequest, ) @@ -343,6 +347,9 @@ class SpeakerBioForm(forms.ModelForm): model = Speaker fields = ['avatar', 'title', 'bio', 'categories'] +class DeleteSpeakerForm(forms.Form): + confirm = forms.BooleanField(label="Yes, delete series", required=True) + class UserTalkForm(forms.ModelForm): class Meta: model = Talk diff --git a/events/models/__init__.py b/events/models/__init__.py index ca0026c..3d38a72 100644 --- a/events/models/__init__.py +++ b/events/models/__init__.py @@ -2,4 +2,4 @@ from .profiles import * from .locale import * from .search import * from .events import * - +from .speakers import * diff --git a/events/models/events.py b/events/models/events.py index 47aba50..d564aef 100644 --- a/events/models/events.py +++ b/events/models/events.py @@ -376,28 +376,4 @@ class EventSeries(models.Model): def __str__(self): return u'%s by %s at %s' % (self.name, self.team.name, self.start_time) -class SpeakerRequest(models.Model): - event = models.ForeignKey(Event, on_delete=models.CASCADE) - topics = models.ManyToManyField('Topic', blank=True) - -class Presentation(models.Model): - DECLINED=-1 - PROPOSED=0 - ACCEPTED=1 - - STATUSES = [ - (DECLINED, _("Declined")), - (PROPOSED, _("Proposed")), - (ACCEPTED, _("Accepted")), - ] - event = models.ForeignKey(Event, related_name='presentations', on_delete=models.CASCADE) - talk = models.ForeignKey(Talk, related_name='presentations', on_delete=models.SET_NULL, blank=False, null=True) - status = models.SmallIntegerField(choices=STATUSES, default=PROPOSED, db_index=True) - start_time = models.DateTimeField(verbose_name=_('Start Time'), db_index=True, null=True, blank=True) - - created_by = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=False) - created_time = models.DateTimeField(default=timezone.now, db_index=True) - - def __str__(self): - return '%s at %s' % (self.talk.title, self.event.name) diff --git a/events/models/profiles.py b/events/models/profiles.py index 2a8bb67..0ab8c4d 100644 --- a/events/models/profiles.py +++ b/events/models/profiles.py @@ -86,10 +86,6 @@ class UserProfile(models.Model): def moderating(self): return [member.team for member in Member.objects.filter(user=self, role__in=(Member.ADMIN, Member.MODERATOR))] - @property - def talks(self): - return Talk.objects.filter(speaker__user=self) - def can_create_event(self, team): try: if self.user.is_superuser: @@ -306,62 +302,3 @@ class Topic(models.Model): self.slug = slugify(self.name) super().save(*args, **kwargs) -class Speaker(models.Model): - user = models.ForeignKey(UserProfile, on_delete=models.CASCADE) - avatar = ProcessedImageField(verbose_name=_("Photo Image"), - upload_to='avatars', - processors=[ResizeToFill(128, 128)], - format='PNG', - blank=True) - title = models.CharField(max_length=256, blank=True, null=True) - bio = models.TextField(verbose_name=_('Biography'), blank=True) - - categories = models.ManyToManyField('Category', blank=True) - topics = models.ManyToManyField('Topic', blank=True) - - def headshot(self): - if self.avatar: - return self.avatar - else: - return self.user.avatar - - def __str__(self): - if self.title: - return self.title - return self.user.__str__() - -class Talk(models.Model): - PRESENTATION=0 - WORKSHOP=1 - PANEL=2 - ROUNDTABLE=3 - QANDA=4 - DEMO=5 - TYPES = [ - (PRESENTATION, _("Presentation")), - (WORKSHOP, _("Workshop")), - (PANEL, _("Panel")), - (ROUNDTABLE, _("Roundtable")), - (QANDA, _("Q & A")), - (DEMO, _("Demonstration")), - ] - speaker = models.ForeignKey(Speaker, verbose_name=_('Speaker Bio'), on_delete=models.CASCADE) - title = models.CharField(max_length=256) - abstract = models.TextField() - talk_type = models.SmallIntegerField(_("Type"), choices=TYPES, default=PRESENTATION) - web_url = models.URLField(_("Website"), null=True, blank=True) - - category = models.ForeignKey('Category', on_delete=models.SET_NULL, blank=False, null=True) - topics = models.ManyToManyField('Topic', blank=True) - - @property - def future_presentations(self): - return self.presentations.filter(status__gte=0, event__start_time__gt=timezone.now()) - - @property - def past_presentations(self): - return self.presentations.filter(status=1, event__start_time__lte=timezone.now()) - - def __str__(self): - return self.title - diff --git a/events/models/speakers.py b/events/models/speakers.py new file mode 100644 index 0000000..bbd4d72 --- /dev/null +++ b/events/models/speakers.py @@ -0,0 +1,104 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from django.utils import timezone + +from imagekit.models import ImageSpecField +from imagekit.processors import ResizeToFill + +from ..utils import slugify +from .locale import * +from .profiles import * +from .events import * +from .search import * +from .. import location + +import pytz +import datetime + +class Speaker(models.Model): + user = models.ForeignKey(UserProfile, on_delete=models.CASCADE) + avatar = ProcessedImageField(verbose_name=_("Photo Image"), + upload_to='avatars', + processors=[ResizeToFill(128, 128)], + format='PNG', + blank=True) + title = models.CharField(max_length=256, blank=True, null=True) + bio = models.TextField(verbose_name=_('Biography'), blank=True) + + categories = models.ManyToManyField('Category', blank=True) + topics = models.ManyToManyField('Topic', blank=True) + + def headshot(self): + if self.avatar: + return self.avatar + else: + return self.user.avatar + + def __str__(self): + if self.title: + return self.title + return self.user.__str__() + +class Talk(models.Model): + PRESENTATION=0 + WORKSHOP=1 + PANEL=2 + ROUNDTABLE=3 + QANDA=4 + DEMO=5 + TYPES = [ + (PRESENTATION, _("Presentation")), + (WORKSHOP, _("Workshop")), + (PANEL, _("Panel")), + (ROUNDTABLE, _("Roundtable")), + (QANDA, _("Q & A")), + (DEMO, _("Demonstration")), + ] + speaker = models.ForeignKey(Speaker, verbose_name=_('Speaker Bio'), related_name='talks', on_delete=models.CASCADE) + title = models.CharField(max_length=256) + abstract = models.TextField() + talk_type = models.SmallIntegerField(_("Type"), choices=TYPES, default=PRESENTATION) + web_url = models.URLField(_("Website"), null=True, blank=True) + + category = models.ForeignKey('Category', on_delete=models.SET_NULL, blank=False, null=True) + topics = models.ManyToManyField('Topic', blank=True) + + @property + def future_presentations(self): + return self.presentations.filter(status__gte=0, event__start_time__gt=timezone.now()) + + @property + def past_presentations(self): + return self.presentations.filter(status=1, event__start_time__lte=timezone.now()) + + def __str__(self): + return self.title + +class SpeakerRequest(models.Model): + event = models.ForeignKey(Event, on_delete=models.CASCADE) + topics = models.ManyToManyField('Topic', blank=True) + +class Presentation(models.Model): + DECLINED=-1 + PROPOSED=0 + ACCEPTED=1 + + STATUSES = [ + (DECLINED, _("Declined")), + (PROPOSED, _("Proposed")), + (ACCEPTED, _("Accepted")), + ] + event = models.ForeignKey(Event, related_name='presentations', on_delete=models.CASCADE) + talk = models.ForeignKey(Talk, related_name='presentations', on_delete=models.CASCADE, blank=False, null=True) + status = models.SmallIntegerField(choices=STATUSES, default=PROPOSED, db_index=True) + start_time = models.DateTimeField(verbose_name=_('Start Time'), db_index=True, null=True, blank=True) + + created_by = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=False) + created_time = models.DateTimeField(default=timezone.now, db_index=True) + + def __str__(self): + try: + return '%s at %s' % (self.talk.title, self.event.name) + except: + return "No talk" + diff --git a/get_together/templates/get_together/events/show_event.html b/get_together/templates/get_together/events/show_event.html index 5ab01e7..9385540 100644 --- a/get_together/templates/get_together/events/show_event.html +++ b/get_together/templates/get_together/events/show_event.html @@ -151,7 +151,7 @@