class TopLevelPage(Page): """Render a top-level page. Useful for things like FAQ/About Us/etc. """ body = StreamField([ ('banner_image', common_blocks.BannerImage()), ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', common_blocks.CaptionImageBlock()), ('h1', common_blocks.HeaderH1(classname="full title")), ('subhead', common_blocks.Subhead(classname="full title")), ('block_quote', common_blocks.BlockQuote()), ('call_to_action', common_blocks.CallToAction()), ('small_call_to_action', common_blocks.CTAButton()), ('embed_code', common_blocks.EmbedCode()), ]) page_date = models.DateField() fundraising_snippet = models.ForeignKey(EmbedCodeSnippet, null=True, blank=True, on_delete=models.SET_NULL, related_name='+') search_fields = Page.search_fields + [ index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('page_date'), StreamFieldPanel('body'), SnippetChooserPanel('fundraising_snippet') ]
class HomePage(OpenGraphMixin, Page): """Controls rendering of PhillyDSA home page. This is the first page that you see hosted at / """ body = StreamField([ ('banner_image', common_blocks.BannerImage()), ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', common_blocks.CaptionImageBlock()), ('h1', common_blocks.HeaderH1(classname="full title")), ('subhead', common_blocks.Subhead(classname="full title")), ('block_quote', common_blocks.BlockQuote()), ('call_to_action', common_blocks.CallToAction()), ('small_call_to_action', common_blocks.CTAButton()), ('embed_code', common_blocks.EmbedCode()), ]) fundraising_snippet = models.ForeignKey(EmbedCodeSnippet, null=True, blank=True, on_delete=models.SET_NULL, related_name='+') search_fields = Page.search_fields + [ index.SearchField('body'), ] content_panels = Page.content_panels + [ StreamFieldPanel('body'), SnippetChooserPanel('fundraising_snippet') ]
class BlogEntry(OpenGraphMixin, Page): """Page for a single blog entry.""" blog_date = models.DateField("Blog Entry Date") blog_author = models.CharField(max_length=255) blog_tags = ClusterTaggableManager(through=BlogEntryTag, blank=True) body = StreamField([ ('banner_image', common_blocks.BannerImage()), ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', common_blocks.CaptionImageBlock()), ('h1', common_blocks.HeaderH1(classname="full title")), ('subhead', common_blocks.Subhead(classname="full title")), ('block_quote', common_blocks.BlockQuote()), ('call_to_action', common_blocks.CallToAction()), ('small_call_to_action', common_blocks.CTAButton()), ]) search_fields = Page.search_fields + [ index.SearchField('body'), ] content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('blog_date'), FieldPanel('blog_author'), FieldPanel('blog_tags'), ], heading="Blog information"), StreamFieldPanel('body'), ] def save(self, *args, **kwargs): """Override to have a more specific slug w/ date & title.""" self.slug = "{0}-{1}".format(self.blog_date.strftime("%Y-%m-%d"), slugify(self.title)) super().save(*args, **kwargs)
class BulletinEmail(OpenGraphMixin, Page): """Page for a single bulletin email.""" bulletin_date = models.DateField("Bulletin Date") body = StreamField([ ('banner_image', common_blocks.BannerImage()), ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', common_blocks.CaptionImageBlock()), ('h1', common_blocks.HeaderH1(classname="full title")), ('subhead', common_blocks.Subhead(classname="full title")), ('block_quote', common_blocks.BlockQuote()), ('call_to_action', common_blocks.CallToAction()), ('small_call_to_action', common_blocks.CTAButton()), ('embed_code', common_blocks.EmbedCode()), ]) search_fields = Page.search_fields + [ index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('bulletin_date'), StreamFieldPanel('body'), ] def save(self, *args, **kwargs): """Override to have a more specific slug w/ date & title.""" self.slug = "{0}-{1}".format(self.bulletin_date.strftime("%Y-%m-%d"), slugify(self.title)) super().save(*args, **kwargs) def to_email(self, *args, **kwargs): """Export a bulletin as an HTML file for emailing.""" request = kwargs.get('request', None) template_string = render_to_string( "bulletins/bulletin_html_email.html", self.get_context(request)) prepared_resp = premailer.Premailer( template_string, base_url=settings.BASE_URL, remove_classes=True, strip_important=True, cssutils_logging_level=logging.CRITICAL).transform() return prepared_resp def serve(self, request): """Serve request based on options in GET method to add email.""" if "format" in request.GET: if request.GET['format'] == 'email': # Export to plaint text email format response = HttpResponse( self.to_email(request=request), content_type='text/plain; charset="UTF8"') return response else: # Unrecognised format error message = 'Could not export bulletin\n\nUnrecognised format.' return HttpResponse(message, content_type='text/plain') else: # Display event page as usual return super().serve(request)
class MemberCalendarEvent(Page): """Page for a single event.""" event_date = models.DateField("Event Date") event_start_time = models.TimeField("Start time") event_end_time = models.TimeField("End time") wheelchair_accessible = models.BooleanField(default=False) asl_available = models.BooleanField(default=False) body = StreamField([ ('banner_image', common_blocks.BannerImage()), ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', common_blocks.CaptionImageBlock()), ('h1', common_blocks.HeaderH1(classname="full title")), ('subhead', common_blocks.Subhead(classname="full title")), ('block_quote', common_blocks.BlockQuote()), ('call_to_action', common_blocks.CallToAction()), ('small_call_to_action', common_blocks.CTAButton()), ('embed_code', common_blocks.EmbedCode()), ]) location_street_address = models.CharField(max_length=255, blank=True) location_city = models.CharField(max_length=255, blank=True) location_zip_code = models.CharField(max_length=5, blank=True) location_state = models.CharField(max_length=100, blank=True) location_name = models.CharField(max_length=500, blank=True) search_fields = Page.search_fields + [ index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('event_date'), FieldPanel('event_start_time'), FieldPanel('event_end_time'), FieldPanel('wheelchair_accessible'), FieldPanel('asl_available'), FieldPanel('location_name'), FieldPanel('location_street_address'), FieldPanel('location_city'), FieldPanel('location_state'), FieldPanel('location_zip_code'), StreamFieldPanel('body'), ] promote_panels = [ MultiFieldPanel([ FieldPanel('seo_title'), FieldPanel('show_in_menus'), FieldPanel('search_description'), ]) ] def serve(self, request): """Serve request based on options in GET method to add ical attachment.""" if "format" in request.GET: if request.GET['format'] == 'ical': # Export to ical format response = HttpResponse(self.to_ical(), content_type='text/calendar') response[ 'Content-Disposition'] = 'attachment; filename=' + self.slug + '.ics' return response else: # Unrecognised format error message = 'Could not export event\n\nUnrecognised format.' return HttpResponse(message, content_type='text/plain') else: # Display event page as usual return super().serve(request) def event_datetime(self, ev_date=None, ev_time=None): """Return a combined datetime.datetime object for the event.""" return datetime.datetime(ev_date.year, ev_date.month, ev_date.day, ev_time.hour, ev_time.minute) @property def event_start_dt(self): """Return event start time as a datetime.datetime obj.""" return self.event_datetime(ev_date=self.event_date, ev_time=self.event_start_time) @property def event_end_dt(self): """Return event end time as a datetime.datetime obj.""" return self.event_datetime(ev_date=self.event_date, ev_time=self.event_end_time) @property def iso_start_time(self): """Return ISO-formatted start time for event.""" return self.event_start_dt.isoformat() @property def iso_end_time(self): """Return ISO-formatted end time for event.""" return self.event_end_dt.isoformat() def save(self, *args, **kwargs): """Override to have a more specific slug w/ date & title.""" self.slug = "{0}-{1}".format(self.event_date.strftime("%Y-%m-%d"), slugify(self.title)) super().save(*args, **kwargs) @property def event_location(self): """Return an event location or "To be determined".""" if not all([ self.location_street_address, self.location_city, self.location_state, self.location_zip_code ]): return "To be determined" else: return ", ".join([ self.location_street_address, self.location_city, self.location_state ]) + " " + self.location_zip_code def to_ical(self): """Return an iCal compatible file representing the event.""" cal = Calendar() event = Event() event.add('summary', self.title) event.add('uid', '{0}@phillydsa.com'.format(self.slug)) event.add('dtstart', self.event_datetime(self.event_date, self.event_start_time)) event.add('dtend', self.event_datetime(self.event_date, self.event_end_time)) event.add( 'location', ','.join([ self.location_street_address, self.location_city, self.location_state, self.location_zip_code ])) event.add('organizer', 'PhillyDSA') cal.add_component(event) return cal.to_ical()