class PressReleasePage(ContentPage): date = models.DateField(default=datetime.date.today) formatted_title = models.CharField( max_length=255, null=True, blank=True, default='', help_text= "Use if you need italics in the title. e.g. <em>Italicized words</em>") category = models.CharField( max_length=255, choices=constants.press_release_page_categories.items()) read_next = models.ForeignKey('PressReleasePage', blank=True, null=True, default=get_previous_press_release_page, on_delete=models.SET_NULL) homepage_pin = models.BooleanField(default=False) homepage_pin_expiration = models.DateField(blank=True, null=True) homepage_pin_start = models.DateField(blank=True, null=True) homepage_hide = models.BooleanField(default=False) template = 'home/updates/press_release_page.html' content_panels = ContentPage.content_panels + [ FieldPanel('formatted_title'), FieldPanel('date'), InlinePanel('authors', label="Authors"), FieldPanel('category'), PageChooserPanel('read_next'), ] promote_panels = Page.promote_panels + [ MultiFieldPanel([ FieldPanel('homepage_pin'), FieldPanel('homepage_pin_start'), FieldPanel('homepage_pin_expiration'), FieldPanel('homepage_hide') ], heading="Home page feed") ] search_fields = ContentPage.search_fields + [ index.FilterField('category'), index.FilterField('date') ] @property def content_section(self): return '' @property def get_update_type(self): return constants.update_types['press-release'] @property def get_author_office(self): return 'Press Office' """ Because we removed the boilerplate from all 2016 releases this flag is used to show it in the templates as a print-only element """ @property def no_boilerplate(self): return self.date.year >= 2016
class ProgrammePageRelatedProgramme(RelatedPage): source_page = ParentalKey("ProgrammePage", related_name="related_programmes") panels = [PageChooserPanel("page", "programmes.ProgrammePage")]
class HomePage(Page): headline = models.CharField( max_length=255, help_text='Write a short introductory sentence about Project TIER.') featured_index_page = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text= 'Choose the most important index page on the site. It will be prominently featured on the home page.' ) featured_index_page_2 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Choose an important secondary page to feature.', verbose_name='Secondary featured page') featured_index_page_3 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Choose an important secondary page to feature.', verbose_name='Secondary featured page') featured_events_page = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Select the main events listing page.') promo_headline = models.CharField(max_length=255, blank=True) promo_text = RichTextField(blank=True) promo_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+') promo_cta_link = models.URLField(blank=True) promo_cta_text = models.CharField(max_length=20, blank=True) big_cta_show = models.BooleanField(default=True, verbose_name="Show big CTA?") big_cta_text = models.CharField(max_length=200, blank=True, verbose_name="Big CTA text") big_cta_link = models.URLField(blank=True, verbose_name="Big CTA link") content_panels = Page.content_panels + [ FieldPanel('headline'), PageChooserPanel('featured_index_page', 'standard.StandardIndexPage'), MultiFieldPanel([ PageChooserPanel('featured_index_page_2', 'standard.StandardIndexPage'), PageChooserPanel('featured_index_page_3', 'standard.StandardIndexPage'), PageChooserPanel('featured_events_page', 'events.EventIndexPage'), ], heading="Secondary featured section"), MultiFieldPanel([ FieldPanel('promo_headline'), FieldPanel('promo_text'), ImageChooserPanel('promo_image'), FieldPanel('promo_cta_link'), FieldPanel('promo_cta_text'), ], heading="Promo"), MultiFieldPanel([ FieldPanel('big_cta_show'), FieldPanel('big_cta_text'), FieldPanel('big_cta_link'), ], heading="Big CTA"), ] # Only let the root page be a parent parent_page_types = ['wagtailcore.Page'] @property def children(self): children = self.get_children().live().in_menu().specific() return children class Meta: verbose_name = "homepage"
class EventSpeaker(Orderable): event = ParentalKey("Event", related_name="speaker") speaker = ForeignKey("people.Person", on_delete=CASCADE, related_name="+") panels = [PageChooserPanel("speaker")]
class RelatedStudentPage(Orderable): source_page = ParentalKey(Page, related_name="related_student_pages") page = models.ForeignKey("people.StudentPage", on_delete=models.CASCADE) panels = [PageChooserPanel("page")]
def test_target_models_malformed_type(self): result = PageChooserPanel('page', 'snowman').bind_to_model(PageChooserModel) self.assertRaises(ImproperlyConfigured, result.target_models)
class HomePage(Page): """Home page model/ landing page""" template = "home/home_page.html" max_count = 1 banner_title = models.CharField(max_length=50, blank=True, null=True) banner_subtitle = models.CharField(max_length=200, blank=True, null=True) banner_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) about_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) about_title = models.CharField(max_length=100, blank=True, null=True) about_subtitle = models.CharField(max_length=100, blank=True, null=True) about_text = RichTextField(features=["bold", "italic"], blank=True, null=True) about_cta = models.ForeignKey( "wagtailcore.page", null=True, blank=True, related_name="+", on_delete=models.SET_NULL, ) featured_blog_post = models.ForeignKey( "wagtailcore.page", null=True, blank=True, related_name="+", on_delete=models.SET_NULL, ) content_panels = Page.content_panels + [ MultiFieldPanel( [ FieldPanel("banner_title"), FieldPanel("banner_subtitle"), ImageChooserPanel("banner_image"), ], heading="Banner Options", ), MultiFieldPanel( [ FieldPanel("about_title"), FieldPanel("about_subtitle"), ImageChooserPanel("about_image"), FieldPanel("about_text"), PageChooserPanel("about_cta"), ], heading="About me box", ), PageChooserPanel("featured_blog_post"), ] def get_context(self, request, *args, **kwargs): """Getting blog posts into context""" context = super().get_context(request) posts = (BlogDetailPage.objects.live().public().order_by( "-first_published_at")[:2]) context["posts"] = posts return context
class UserMayBookInstrumentRelation(AbstractRelatedInstrument): user = ParentalKey(RUBIONUser, related_name='may_book') panels = [PageChooserPanel('page', ['instruments.InstrumentPage'])]
class MainMenu(ClusterableModel): """ MainMenu class for header links. Contains Orderable MenuItem class. """ admin_title = models.CharField( max_length=100, blank=False, null=True ) title = models.CharField(max_length=100) language = models.CharField( max_length=100, choices=settings.LANGUAGES ) button_text = models.CharField( max_length=100, blank=False, null=False, default="Menu" ) button_aria_label = models.CharField( max_length=100, default="Show or hide Top Level Navigation", help_text=_('Description for navigation button aria label'), ) navigation_aria_label = models.CharField( max_length=100, default="Top Level Navigation", help_text=_('Description for navigation aria label'), ) phase_banner_description = RichTextField( blank=True, default="", help_text=_('Text area for phase banner description'), ) cookie_banner_title = models.CharField( max_length=150, blank=False, null=True ) cookie_banner_description = RichTextField( blank=True, default="", help_text=_('Text area for cookie banner description'), ) cookie_banner_button_text = models.CharField( max_length=150, blank=False, null=True, help_text=_('Text for cookie accept button'), ) cookie_page = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, related_name="+", on_delete=models.CASCADE ) cookie_banner_preferences_link_text = models.CharField( max_length=150, blank=False, null=True ) content_panel = [ FieldPanel("title"), FieldPanel("language"), FieldPanel("button_text"), FieldPanel("button_aria_label"), FieldPanel("navigation_aria_label"), FieldPanel("phase_banner_description"), InlinePanel("menu_items", label="Menu Item") ] cookie_panel = [ FieldPanel("cookie_banner_title"), FieldPanel("cookie_banner_description"), FieldPanel("cookie_banner_button_text"), PageChooserPanel("cookie_page"), FieldPanel("cookie_banner_preferences_link_text"), ] edit_handler = TabbedInterface([ ObjectList(content_panel, heading='Content'), ObjectList(cookie_panel, heading='Cookie Banner'), ]) def __str__(self): language = dict(settings.LANGUAGES) return f"{self.title} - {language[self.language]}" def save(self, *args, **kwards): try: clear_mainmenu_cache(self.language) except Exception: logging.error('Error deleting menu cache') pass return super().save(*args, **kwards)
class LinkFields(models.Model): """ Adds fields for internal and external links with some methods to simplify the rendering: <a href="{{ obj.get_link_url }}">{{ obj.get_link_text }}</a> """ link_page = models.ForeignKey('wagtailcore.Page', blank=True, null=True, on_delete=models.SET_NULL) link_url = models.URLField(blank=True) link_text = models.CharField(blank=True, max_length=255) class Meta: abstract = True def clean(self): if not self.link_page and not self.link_url: raise ValidationError({ 'link_url': ValidationError("You must specify link page or link url."), 'link_page': ValidationError("You must specify link page or link url."), }) if self.link_page and self.link_url: raise ValidationError({ 'link_url': ValidationError( "You must specify link page or link url. You can't use both." ), 'link_page': ValidationError( "You must specify link page or link url. You can't use both." ), }) if not self.link_page and not self.link_text: raise ValidationError({ 'link_text': ValidationError( "You must specify link text, if you use the link url field." ), }) def get_link_text(self): if self.link_text: return self.link_text if self.link_page: return self.link_page.title return '' def get_link_url(self): if self.link_page: return self.link_page.get_url return self.link_url panels = [ MultiFieldPanel([ PageChooserPanel('link_page'), FieldPanel('link_url'), FieldPanel('link_text'), ], 'Link'), ]
class HomePage(Page): # Hero section of HomePage image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Homepage image') hero_text = models.CharField( max_length=255, help_text='Write an introduction for the bakery') # Body section of the HomePage body = StreamField(BaseStreamBlock(), verbose_name="Home content block", blank=True) bottom = StreamField(BaseStreamBlock(), verbose_name="Home content block", blank=True) # Promo section of the HomePage promo_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Promo image') promo_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') promo_text = RichTextField(null=True, blank=True, help_text='Write some promotional copy') featured_section_1_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_1 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='First featured section for the homepage. Will display up to ' 'three child items.', verbose_name='Featured section 1') featured_section_2_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_2 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Second featured section for the homepage. Will display up to ' 'three child items.', verbose_name='Featured section 2') featured_section_3_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_3 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Third featured section for the homepage. Will display up to ' 'six child items.', verbose_name='Featured section 3') content_panels = Page.content_panels + [ MultiFieldPanel([ ImageChooserPanel('image'), FieldPanel('hero_text', classname="full"), ], heading="Hero section"), MultiFieldPanel([ ImageChooserPanel('promo_image'), FieldPanel('promo_title'), FieldPanel('promo_text'), ], heading="Promo section"), StreamFieldPanel('body'), MultiFieldPanel([ MultiFieldPanel([ FieldPanel('featured_section_1_title'), PageChooserPanel('featured_section_1'), ]), MultiFieldPanel([ FieldPanel('featured_section_2_title'), PageChooserPanel('featured_section_2'), ]), MultiFieldPanel([ FieldPanel('featured_section_3_title'), PageChooserPanel('featured_section_3'), ]) ], heading="Featured homepage sections", classname="collapsible"), StreamFieldPanel('bottom') ] def __str__(self): return self.title class Meta: verbose_name = "homepage"
class ImportantPages(BaseSetting): terms_of_use = models.ForeignKey( 'wagtailcore.Page', related_name='important_page_terms_of_use', null=True, blank=True, on_delete=models.SET_NULL) imprint = models.ForeignKey('wagtailcore.Page', related_name='important_page_imprint', null=True, blank=True, on_delete=models.SET_NULL) data_protection_policy = models.ForeignKey( 'wagtailcore.Page', related_name='important_page_data_protection_policy', null=True, blank=True, on_delete=models.SET_NULL) netiquette = models.ForeignKey('wagtailcore.Page', related_name='important_page_netiquette', null=True, blank=True, on_delete=models.SET_NULL) contact = models.ForeignKey('wagtailcore.Page', related_name='important_page_contact', null=True, blank=True, on_delete=models.SET_NULL) donate_link = models.URLField(blank=True) manual_link = models.URLField(blank=True) github_repo_link = models.URLField(blank=True) open_content_link = models.URLField(blank=True) panels = [ PageChooserPanel('terms_of_use', [ 'a4_candy_cms_pages.SimplePage', 'a4_candy_cms_contacts.FormPage', 'a4_candy_cms_news.NewsIndexPage', 'a4_candy_cms_news.NewsPage', 'a4_candy_cms_use_cases.UseCaseIndexPage', 'a4_candy_cms_use_cases.UseCasePage' ]), PageChooserPanel('imprint', [ 'a4_candy_cms_pages.SimplePage', 'a4_candy_cms_contacts.FormPage', 'a4_candy_cms_news.NewsIndexPage', 'a4_candy_cms_news.NewsPage', 'a4_candy_cms_use_cases.UseCaseIndexPage', 'a4_candy_cms_use_cases.UseCasePage' ]), PageChooserPanel('data_protection_policy', [ 'a4_candy_cms_pages.SimplePage', 'a4_candy_cms_contacts.FormPage', 'a4_candy_cms_news.NewsIndexPage', 'a4_candy_cms_news.NewsPage', 'a4_candy_cms_use_cases.UseCaseIndexPage', 'a4_candy_cms_use_cases.UseCasePage' ]), PageChooserPanel('netiquette', [ 'a4_candy_cms_pages.SimplePage', 'a4_candy_cms_contacts.FormPage', 'a4_candy_cms_news.NewsIndexPage', 'a4_candy_cms_news.NewsPage', 'a4_candy_cms_use_cases.UseCaseIndexPage', 'a4_candy_cms_use_cases.UseCasePage' ]), PageChooserPanel('contact', [ 'a4_candy_cms_pages.SimplePage', 'a4_candy_cms_contacts.FormPage', 'a4_candy_cms_news.NewsIndexPage', 'a4_candy_cms_news.NewsPage', 'a4_candy_cms_use_cases.UseCaseIndexPage', 'a4_candy_cms_use_cases.UseCasePage' ]), FieldPanel('donate_link'), FieldPanel('manual_link'), FieldPanel('github_repo_link'), FieldPanel('open_content_link') ]
class ServicePage(Page): template = 'services/service_page.html' parent_page_types = ["services.ServiceListingPage"] subpage_types = [] description = models.TextField( blank=True, max_length=500, ) internal_page = models.ForeignKey( 'wagtailcore.Page', blank=True, null=True, related_name='+', help_text='Select an internal page', on_delete=models.SET_NULL, ) external_page = models.URLField(blank=True, ) button_text = models.CharField( blank=True, max_length=50, ) service_image = models.ForeignKey( 'wagtailimages.Image', null=True, blank=False, on_delete=models.SET_NULL, help_text= 'This image will be used on the Service Listing Page and will be cropped 570x370', related_name='+', ) content_panels = Page.content_panels + [ FieldPanel('description'), PageChooserPanel('internal_page'), FieldPanel('external_page'), FieldPanel('button_text'), ImageChooserPanel('service_image'), ] def clean(self): super().clean() # Page validation if self.internal_page and self.external_page: # Both link fields must be filled out or else error raise ValidationError({ 'internal_page': ValidationError( "Please only select a page OR enter an external URL"), 'external_page': ValidationError( "Please only select a page OR enter an external URL"), }) if not self.internal_page and self.external_page: raise ValidationError({ 'internal_page': ValidationError( "You must select a page OR enter an external URL"), 'external_page': ValidationError( "You must select a page OR enter an external URL"), })
class ServicePage(Page): parent_page_types = ["services.ServiceListingPage"] subpage_types = [] template = "services/service_page.html" description = models.TextField( blank=True, max_length=500, ) internal_page = models.ForeignKey( 'wagtailcore.Page', blank=True, null=True, related_name='+', help_text='Select an internal Wagtail page', on_delete=models.SET_NULL, ) external_page = models.URLField(blank=True) button_text = models.CharField(blank=True, max_length=50) service_image = models.ForeignKey( 'wagtailimages.Image', null=True, blank=False, on_delete=models.SET_NULL, help_text= 'This image will be used on the Service Listing Page and will be cropped to 570px by 370px on this page.', related_name='+', ) body = StreamField( [("title", blocks.TitleBlock()), ("cards", blocks.CardsBlock()), ("image_and_text", blocks.ImageAndTextBlock()), ("cta", blocks.CallToActionBlock()), ("testimonial", SnippetChooserBlock( target_model='testimonials.Testimonial', template="streams/testimonial_block.html", )), ("pricing_table", blocks.PricingTableBlock(table_options=NEW_TABLE_OPTIONS, )), ("richtext", wagtail_blocks.RichTextBlock( template="streams/simple_richtext_block.html", features=["bold", "italic", "ol", "ul", "link"])), ("large_image", ImageChooserBlock( help_text='This image will be cropped to 1200px by 775px', template="streams/large_image_block.html"))], null=True, blank=True) content_panels = Page.content_panels + [ FieldPanel("description"), PageChooserPanel("internal_page"), FieldPanel("external_page"), FieldPanel("button_text"), ImageChooserPanel("service_image"), StreamFieldPanel("body"), ] def clean(self): super().clean() if self.internal_page and self.external_page: # Both fields are filled out raise ValidationError({ 'internal_page': ValidationError( "Please only select a page OR enter an external URL"), 'external_page': ValidationError( "Please only select a page OR enter an external URL"), }) if not self.internal_page and not self.external_page: raise ValidationError({ 'internal_page': ValidationError( "You must always select a page OR enter an external URL"), 'external_page': ValidationError( "You must always select a page OR enter an external URL"), })
*args, **kwargs): """ Renders the landing page OR if a receipt_page_redirect is chosen redirects to this page. """ if self.thank_you_redirect_page: return redirect(self.thank_you_redirect_page.url, permanent=False) return super(FormPageWithRedirect, self).render_landing_page(request, form_submission, *args, **kwargs) FormPageWithRedirect.content_panels = [ FieldPanel('title', classname="full title"), PageChooserPanel('thank_you_redirect_page'), InlinePanel('form_fields', label="Form fields"), MultiFieldPanel([ FieldPanel('to_address', classname="full"), FieldPanel('from_address', classname="full"), FieldPanel('subject', classname="full"), ], "Email") ] # FormPage with a custom FormSubmission class FormPageWithCustomSubmission(AbstractEmailForm): """ This Form page: * Have custom submission model
class HomePage(RoutablePageMixin, Page): # Home page model templates = "home/home_page.html" # the best way to put the type of pages subpage_types = [ 'blog.BlogListingPage', 'contact.FormPage', 'news.NewsPage' ] # to limit the creattion of only one Home page max_count = 1 #it s only on root page parent_page_type = ['wagtailcore.Page'] # we will add 2 fileds body and banner title required but can be null on wordpress banner_title = models.CharField(max_length=100, blank=False, null=True) body = RichTextField(blank=True) banner_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+" #we will keep same name of images ) banner_cta = models.ForeignKey("wagtailcore.Page", null=True, blank=True, on_delete=models.SET_NULL, related_name="+") content_stream = StreamField([("cta", blocks.CtaBlock())], null=True, blank=True) #use oriented object def getBanner(self): return self.banner_title content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('banner_title', classname="full"), FieldPanel('body', classname="full"), ImageChooserPanel('banner_image'), PageChooserPanel('banner_cta'), ], heading="Banner Options"), # we make it outside but it s not clear soo we add MultiFieldPanel # instead of InlinePanel("carousel_images"), ] sidebar_panels = [ MultiFieldPanel([ InlinePanel("carousel_images", max_num=5, min_num=1, label="Image") ], heading="Carousel Images"), StreamFieldPanel("content_stream"), ] api_fields = [ APIField("banner_title"), APIField("banner_image"), APIField("carousel_images"), ] # to hide tabs on admin #promote_panels =[] #settings_panels=[] #add tab edit_handler = TabbedInterface([ ObjectList(content_panels, heading='Content Home Page'), #will add another tab ObjectList(sidebar_panels, heading='Carousel Section'), ObjectList(Page.promote_panels, heading='Promotional Stuff'), ObjectList(Page.settings_panels, heading='Settings Stuff'), ]) class Meta: verbose_name = "HOME PAGE" verbose_name_plural = "HOME PAGES" #render a page we create new link and put our template @route(r'^subscribers/$') def the_subscribe_page(self, request, *args, **kwargs): context = self.get_context(request, *args, **kwargs) context['a_special_test'] = "hello world simple varibale passed" return render(request, 'home/subscribe.html', context)
def test_target_models(self): result = PageChooserPanel('page', 'wagtailcore.site').bind_to_model( PageChooserModel).target_models() self.assertEqual(result, [Site])
class HomePage(BasePage): features = settings.HOMEPAGE_RICHTEXT_FEATURES introduction = RichTextField(features=features) sections = StreamField( blocks.StreamBlock( [ ( "section", blocks.StructBlock( [ ("title", blocks.CharBlock()), ("page", blocks.PageChooserBlock(can_choose_root=False)), ("description", blocks.RichTextBlock(features=features)), ], icon="doc-full-inverse", ), ), ], block_counts={ "section": settings.HOMEPAGE_SECTION_BLOCK_COUNTS, }, ) ) featured_biography = models.ForeignKey( BiographyPage, # default=BiographyPage.objects.order_by("-modified").first(), blank=True, null=True, on_delete=models.SET_NULL, related_name="+", ) featured_resource = models.ForeignKey( Resource, blank=True, null=True, on_delete=models.SET_NULL, related_name="+" ) featured_blog_post = models.ForeignKey( BlogPost, blank=True, null=True, on_delete=models.SET_NULL, related_name="+" ) subpage_types = [ "kdl_wagtail_zotero.BibliographyIndexPage", "BlogIndexPage", "kdl_wagtail_core.ContactUsPage", "EventIndexPage", "kdl_wagtail_core.IndexPage", "kdl_wagtail_people.PeopleIndexPage", "kdl_wagtail_core.RichTextPage", "kdl_wagtail_core.SitemapPage", "kdl_wagtail_core.StreamPage", ] content_panels = Page.content_panels + [ FieldPanel("introduction", classname="full"), StreamFieldPanel("sections"), PageChooserPanel("featured_biography"), SnippetChooserPanel("featured_resource"), PageChooserPanel("featured_blog_post"), ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not self.id: self.featured_biography = ( BiographyPage.objects.live().order_by("-last_published_at").first() ) self.featured_resource = Resource.objects.order_by("-modified").first() self.featured_blog_post = ( BlogPost.objects.live().order_by("-last_published_at").first() ) def get_context(self, request): context = super().get_context(request) context["events"] = Event.objects.filter(classification__label="comparative") return context
def test_target_models_nonexistent_type(self): result = PageChooserPanel( 'page', 'snowman.lorry').bind_to_model(PageChooserModel) self.assertRaises(ImproperlyConfigured, result.target_models)
class AbstractMenuItem(models.Model, MenuItem): """A model class that defines a base set of fields and methods for all 'menu item' models.""" link_page = models.ForeignKey( Page, verbose_name=_('link to an internal page'), blank=True, null=True, on_delete=models.CASCADE, ) link_url = models.CharField( verbose_name=_('link to a custom URL'), max_length=255, blank=True, null=True, ) url_append = models.CharField( verbose_name=_("append to URL"), max_length=255, blank=True, help_text=_( "Use this to optionally append a #hash or querystring to the " "above page's URL." ) ) handle = models.CharField( verbose_name=_('handle'), max_length=100, blank=True, help_text=_( "Use this field to optionally specify an additional value for " "each menu item, which you can then reference in custom menu " "templates." ) ) link_text = models.CharField( verbose_name=_('link text'), max_length=255, blank=True, help_text=_( "Provide the text to use for a custom URL, or set on an internal " "page link to use instead of the page's title." ), ) objects = MenuItemManager() class Meta: abstract = True verbose_name = _("menu item") verbose_name_plural = _("menu items") ordering = ('sort_order',) @property def menu_text(self): if self.link_text: return self.link_text if not self.link_page: return '' return getattr( self.link_page, app_settings.PAGE_FIELD_FOR_MENU_ITEM_TEXT, self.link_page.title ) def relative_url(self, site=None): if self.link_page: try: return self.link_page.relative_url(site) + self.url_append except TypeError: return '' return self.link_url + self.url_append def get_full_url(self, request=None): if self.link_page: try: # Try for 'get_full_url' method (added in Wagtail 1.11) or fall # back to 'full_url' property if hasattr(self.link_page, 'get_full_url'): full_url = self.link_page.get_full_url(request=request) else: full_url = self.link_page.full_url return full_url + self.url_append except TypeError: return '' return self.link_url + self.url_append def clean(self, *args, **kwargs): if not self.link_url and not self.link_page: msg = _("Please choose an internal page or provide a custom URL") raise ValidationError({'link_url': msg}) if self.link_url and self.link_page: msg = _("Linking to both a page and custom URL is not permitted") raise ValidationError({'link_page': msg, 'link_url': msg}) if self.link_url and not self.link_text: msg = _("This field is required when linking to a custom URL") raise ValidationError({'link_text': msg}) super().clean(*args, **kwargs) def get_active_class_for_request(self, request=None): # Returns the 'active_class' for a custom link item. if app_settings.CUSTOM_URL_SMART_ACTIVE_CLASSES: # new behaviour parsed_url = urlparse(self.link_url) if parsed_url.netloc: return '' if request.path == parsed_url.path: return app_settings.ACTIVE_CLASS if ( request.path.startswith(parsed_url.path) and parsed_url.path != '/' ): return app_settings.ACTIVE_ANCESTOR_CLASS if self.link_url == request.path: # previous behaviour return app_settings.ACTIVE_CLASS return '' def __str__(self): return self.menu_text panels = [ PageChooserPanel('link_page'), FieldPanel('link_url'), FieldPanel('url_append'), FieldPanel('link_text'), FieldPanel('handle'), FieldPanel('allow_subnav'), ]
class EventTopic(Orderable): event = ParentalKey("Event", related_name="topics") topic = ForeignKey("topics.Topic", on_delete=CASCADE, related_name="+") panels = [PageChooserPanel("topic")]
class UserProfilesSettings(BaseSetting): show_mobile_number_field = models.BooleanField( default=False, editable=True, verbose_name=_("Add mobile number field to registration"), ) mobile_number_required = models.BooleanField( default=False, editable=True, verbose_name=_("Mobile number required"), ) country_code = models.CharField( max_length=4, null=True, blank=True, verbose_name=_( "The country code that should be added to a user's number for " "this site"), help_text=_("For example: +27 for South Africa, +44 for England")) prevent_phone_number_in_username = models.BooleanField( default=False, editable=True, verbose_name=_("Prevent phone number in username / display name"), ) show_email_field = models.BooleanField( default=False, editable=True, verbose_name=_("Add email field to registration")) email_required = models.BooleanField(default=False, editable=True, verbose_name=_("Email required")) prevent_email_in_username = models.BooleanField( default=False, editable=True, verbose_name=_("Prevent email in username / display name"), ) show_security_question_fields = models.BooleanField( default=False, editable=True, verbose_name=_("Add security question fields to registration")) security_questions_required = models.BooleanField( default=False, editable=True, verbose_name=_("Security questions required")) num_security_questions = models.PositiveSmallIntegerField( default=1, verbose_name=_("Number of security questions asked for " "password recovery")) password_recovery_retries = models.PositiveSmallIntegerField( default=5, verbose_name=_("Max number of password recovery retries before " "lockout")) terms_and_conditions = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text=_('Choose a footer page')) activate_display_name = models.BooleanField( default=True, editable=True, verbose_name=_("Activate Display Name"), ) capture_display_name_on_reg = models.BooleanField( default=False, editable=True, verbose_name=_("Capture On Registration"), help_text=_("If Display Name is activated, " "and Capture On Registration is not activated, " "The display name field will be captured on done page."), ) display_name_required = models.BooleanField( default=False, editable=True, verbose_name=_("Display Name Required"), ) activate_gender = models.BooleanField( default=False, editable=True, verbose_name=_("Activate Gender"), ) capture_gender_on_reg = models.BooleanField( default=False, editable=True, verbose_name=_("Capture On Registration"), help_text=_("If Gender is activated, " "and Capture On Registration is not activated, " "The Gender field will be captured on done page."), ) gender_required = models.BooleanField( default=False, editable=True, verbose_name=_("Gender Required"), ) activate_dob = models.BooleanField( default=True, editable=True, verbose_name=_("Activate Date Of Birth"), ) capture_dob_on_reg = models.BooleanField( default=False, editable=True, verbose_name=_("Capture On Registration"), help_text=_("If Date Of Birth is activated, " "and Capture On Registration is not activated, " "The Date Of Birth field will be captured on done page."), ) dob_required = models.BooleanField( default=False, editable=True, verbose_name=_("Date Of Birth Required"), ) activate_location = models.BooleanField( default=False, editable=True, verbose_name=_("Activate Location"), ) capture_location_on_reg = models.BooleanField( default=False, editable=True, verbose_name=_("Capture On Registration"), help_text=_("If Location is activated, " "and Capture On Registration is not activated, " "The Location field will be captured on done page."), ) location_required = models.BooleanField( default=False, editable=True, verbose_name=_("Location Required"), ) activate_education_level = models.BooleanField( default=False, editable=True, verbose_name=_("Activate Education Level"), ) capture_education_level_on_reg = models.BooleanField( default=False, editable=True, verbose_name=_("Capture On Registration"), help_text=_("If Education Level is activated, " "and Capture On Registration is not activated, " "The Education Level field will be captured " "on done page."), ) activate_education_level_required = models.BooleanField( default=False, editable=True, verbose_name=_("Education Level Required"), ) panels = [ MultiFieldPanel( [ FieldPanel('show_mobile_number_field'), FieldPanel('mobile_number_required'), FieldPanel('country_code'), FieldPanel('prevent_phone_number_in_username'), ], heading="Mobile Number Settings", ), MultiFieldPanel( [ FieldPanel('show_email_field'), FieldPanel('email_required'), FieldPanel('prevent_email_in_username'), ], heading="Email Settings", ), MultiFieldPanel( [ FieldPanel("show_security_question_fields"), FieldPanel("security_questions_required"), FieldPanel("num_security_questions"), FieldPanel("password_recovery_retries"), ], heading="Security Question Settings", ), MultiFieldPanel( [ PageChooserPanel('terms_and_conditions'), ], heading="Terms and Conditions on registration", ), MultiFieldPanel( [ FieldPanel('activate_display_name'), FieldPanel('capture_display_name_on_reg'), FieldPanel('display_name_required'), ], heading="Display Name", ), MultiFieldPanel( [ FieldPanel('activate_gender'), FieldPanel('capture_gender_on_reg'), FieldPanel('gender_required'), ], heading="Gender", ), MultiFieldPanel( [ FieldPanel('activate_dob'), FieldPanel('capture_dob_on_reg'), FieldPanel('dob_required'), ], heading="Date Of Birth", ), MultiFieldPanel( [ FieldPanel('activate_location'), FieldPanel('capture_location_on_reg'), FieldPanel('location_required'), ], heading="Location", ), MultiFieldPanel( [ FieldPanel('activate_education_level'), FieldPanel('capture_education_level_on_reg'), FieldPanel('activate_education_level_required'), ], heading="Education Level", ) ]
class VideoTopic(Orderable): video = ParentalKey("Video", related_name="topics") topic = ForeignKey("topics.Topic", on_delete=CASCADE, related_name="+") panels = [PageChooserPanel("topic")]
class HomePage(Page): parent_page_types = ["wagtailcore.Page"] subpage_types = [ "flex.FlexPage", "services.ServiceListingPage", "contact.ContactPage" ] max_count = 1 lead_text = models.CharField( max_length=140, blank=True, help_text="Subheading text under the banner title", ) button = models.ForeignKey( "wagtailcore.Page", blank=True, null=True, related_name="+", on_delete=models.SET_NULL, ) button_text = models.CharField( max_length=50, default="Read More", blank=False, help_text="Button text", ) banner_background_image = models.ForeignKey( "wagtailimages.Image", blank=False, null=True, related_name="+", help_text="The banner background Image", on_delete=models.SET_NULL, ) body = StreamField( [ ("title", blocks.TitleBlock()), ("cards", blocks.CardsBlock()), ("image_and_text", blocks.ImageAndTextBlock()), ("cta", blocks.CallToActionBlock()), ( "testimonial", SnippetChooserBlock( target_model="testimonials.Testimonial", template="streams/testimonial_block.html", ), ), ( "pricing_table", blocks.PricingTableBlock(table_options=NEW_TABLE_OPTIONS), ), ], null=True, blank=True, ) content_panels = Page.content_panels + [ FieldPanel("lead_text"), PageChooserPanel("button"), FieldPanel("button_text"), ImageChooserPanel("banner_background_image"), StreamFieldPanel("body"), ] def save(self, *args, **kwargs): key = make_template_fragment_key( "home_page_streams", [self.id], ) cache.delete(key) return super().save(*args, **kwargs)
class StudentPage(PerUserPageMixin, BasePage): base_form_class = StudentPageAdminForm template = "patterns/pages/student/student_detail.html" parent_page_types = ["people.StudentIndexPage"] student_title = models.CharField(max_length=255, help_text=_("E.G Dr, Professor"), blank=True) first_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255) profile_image = models.ForeignKey( get_image_model_string(), null=True, blank=True, related_name="+", on_delete=models.SET_NULL, ) email = models.EmailField(blank=True) degree_status = models.ForeignKey( DegreeStatus, on_delete=models.SET_NULL, related_name="related_student", null=True, blank=True, ) degree_start_date = models.DateField(blank=True, null=True) degree_end_date = models.DateField(blank=True, null=True) degree_award = models.CharField( max_length=1, choices=(("1", "MPhil"), ("2", "PhD")), blank=True, ) introduction = models.TextField(blank=True, verbose_name="Project title") bio = RichTextField( blank=True, help_text="Add a detail summary", verbose_name="Abstract", ) programme = models.ForeignKey( "programmes.ProgrammePage", on_delete=models.SET_NULL, null=True, blank=True, ) biography = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) degrees = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) experience = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) awards = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) funding = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) exhibitions = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) publications = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) research_outputs = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) conferences = RichTextField(blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) additional_information_title = models.TextField(blank=True) addition_information_content = RichTextField( blank=True, features=STUDENT_PAGE_RICH_TEXT_FEATURES) link_to_final_thesis = models.URLField(blank=True) student_funding = RichTextField(blank=True, features=["link"]) student_user_account = models.OneToOneField( User, on_delete=models.SET_NULL, null=True, blank=True, limit_choices_to={"groups__name": "Students"}, unique=True, ) student_user_image_collection = models.OneToOneField( Collection, on_delete=models.SET_NULL, null=True, blank=True, unique=True, help_text="This should link to this students image collection", ) search_fields = BasePage.search_fields + [ index.SearchField("introduction"), index.SearchField("first_name"), index.SearchField("last_name"), index.SearchField("bio"), ] basic_key_details_panels = [ InlinePanel("related_area_of_expertise", label="Areas of Expertise"), InlinePanel("personal_links", label="Personal links", max_num=5), FieldPanel("student_funding"), ] key_details_panels = [ InlinePanel("related_area_of_expertise", label="Areas of Expertise"), InlinePanel("related_research_centre_pages", label=_("Related Research Centres ")), InlinePanel("related_schools", label=_("Related Schools")), InlinePanel("personal_links", label="Personal links", max_num=5), FieldPanel("student_funding"), ] basic_content_panels = [ MultiFieldPanel([ImageChooserPanel("profile_image")], heading="Details"), FieldPanel("link_to_final_thesis"), InlinePanel("related_supervisor", label="Supervisor information"), MultiFieldPanel([FieldPanel("email")], heading="Contact information"), FieldPanel("introduction"), FieldPanel("bio"), InlinePanel("gallery_slides", label="Gallery slide", max_num=5), MultiFieldPanel( [ FieldPanel("biography"), FieldPanel("degrees"), FieldPanel("experience"), FieldPanel("awards"), FieldPanel("funding"), FieldPanel("exhibitions"), FieldPanel("publications"), FieldPanel("research_outputs"), FieldPanel("conferences"), ], heading="More information", ), MultiFieldPanel( [ FieldPanel("additional_information_title"), FieldPanel("addition_information_content"), ], heading="Additional information", ), InlinePanel("relatedlinks", label="External links", max_num=5), ] basic_promote_panels = [ FieldPanel("slug"), ] superuser_basic_promote_panels = [ *BasePage.promote_panels, ] superuser_content_panels = [ *BasePage.content_panels, FieldPanel("student_user_account"), FieldPanel("student_user_image_collection"), MultiFieldPanel( [ FieldPanel("student_title"), FieldPanel("first_name"), FieldPanel("last_name"), ImageChooserPanel("profile_image"), ], heading="Details", ), MultiFieldPanel([FieldPanel("email")], heading="Contact information"), PageChooserPanel("programme"), FieldPanel("degree_start_date"), FieldPanel("degree_end_date"), FieldPanel("degree_status"), FieldPanel("link_to_final_thesis"), InlinePanel("related_supervisor", label="Supervisor information"), FieldPanel("introduction"), FieldPanel("bio"), MultiFieldPanel( [ InlinePanel("related_project_pages", label=_("Project pages"), max_num=5), ], heading=_("Research highlights gallery"), ), InlinePanel("gallery_slides", label="Gallery slide", max_num=5), MultiFieldPanel( [ FieldPanel("biography"), FieldPanel("degrees"), FieldPanel("experience"), FieldPanel("awards"), FieldPanel("funding"), FieldPanel("exhibitions"), FieldPanel("publications"), FieldPanel("research_outputs"), FieldPanel("conferences"), ], heading="More information", ), MultiFieldPanel( [ FieldPanel("additional_information_title"), FieldPanel("addition_information_content"), ], heading="Additional information", ), InlinePanel("relatedlinks", label="External links", max_num=5), ] @property def name(self): parts = (self.student_title, self.first_name, self.last_name) return " ".join(p for p in parts if p) @property def supervisors(self): supervisors = [] for item in self.related_supervisor.all(): if item.supervisor_page: supervisors.append({ "title": item.supervisor_page.title, "link": item.supervisor_page.url, }) else: supervisors.append({ "title": f"{item.title} {item.first_name} {item.surname}", "link": item.link, }) return supervisors def student_information(self): # Method for preparing student data into an accordion friendly format data = [] if self.biography: data.append( {"value": { "heading": "Biography", "body": self.biography }}) if self.degrees: data.append( {"value": { "heading": "Degrees", "body": self.degrees }}) if self.experience: data.append( {"value": { "heading": "Experience", "body": self.experience }}) if self.awards: data.append({"value": {"heading": "Awards", "body": self.awards}}) if self.funding: data.append( {"value": { "heading": "Funding", "body": self.funding }}) if self.exhibitions: data.append({ "value": { "heading": "Exhibitions", "body": self.exhibitions } }) if self.publications: data.append({ "value": { "heading": "Publications", "body": self.publications } }) if self.research_outputs: data.append({ "value": { "heading": "Research outputs", "body": self.research_outputs, } }) if self.conferences: data.append({ "value": { "heading": "Conferences", "body": self.conferences } }) if self.addition_information_content: data.append({ "value": { "heading": self.additional_information_title or "Additional information", "body": self.addition_information_content, } }) return data @property def student_gallery(self): # Format related model to a nice dict data = [] for item in self.gallery_slides.all(): data.append({ "value": { "title": item.title, "author": item.author, "image": item.image, } }) return data @property def student_related_links(self): return [{ "value": { "title": item.link_title, "url": item.url } } for item in self.relatedlinks.all()] def save(self, *args, **kwargs): """On saving the student page, make sure the student_user_account has a group created with the necessary permissions """ super(StudentPage, self).save() if self.student_user_image_collection and self.student_user_account: # Check if a group configuration exsists already for this user. group = Group.objects.filter( name=self.student_user_account.student_group_name) if group: # If we find a group already, we don't need to create one. return # Create a specific group for this student so they have edit access to their page # and their image collection specific_student_group = Group.objects.create( name=self.student_user_account.student_group_name) # Create new add GroupPagePermission GroupPagePermission.objects.create(group=specific_student_group, page=self, permission_type="edit") # Create new GroupCollectionPermission for Profile Images collection GroupCollectionPermission.objects.create( group=specific_student_group, collection=Collection.objects.get( name=self.student_user_image_collection), permission=Permission.objects.get(codename="add_image"), ) GroupCollectionPermission.objects.create( group=specific_student_group, collection=Collection.objects.get( name=self.student_user_image_collection), permission=Permission.objects.get(codename="choose_image"), ) # Add the new specific student group to the user self.student_user_account.groups.add(specific_student_group) self.student_user_account.save() def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) research_pages = get_student_research_projects(self) context["areas"] = get_area_linked_filters(page=self) context["research_highlights"] = format_research_highlights( research_pages) context["related_schools"] = self.related_schools.all() context["research_centres"] = self.related_research_centre_pages.all() context["student_information"] = self.student_information() return context
class HomePage(Page): """ The Home Page. This looks slightly more complicated than it is. You can see if you visit your site and edit the homepage that it is split between a: - Hero area - Body area - A promotional area - Moveable featured site sections """ # Hero section of HomePage image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Homepage image') hero_text = models.CharField( max_length=255, help_text='Write an introduction for the bakery') hero_cta = models.CharField(verbose_name='Hero CTA', max_length=255, help_text='Text to display on Call to Action') hero_cta_link = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', verbose_name='Hero CTA link', help_text='Choose a page to link to for the Call to Action') # Body section of the HomePage body = StreamField(BaseStreamBlock(), verbose_name="Home content block", blank=True) # Promo section of the HomePage promo_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Promo image') promo_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') promo_text = RichTextField(null=True, blank=True, help_text='Write some promotional copy') # Featured sections on the HomePage # You will see on templates/base/home_page.html that these are treated # in different ways, and displayed in different areas of the page. # Each list their children items that we access via the children function # that we define on the individual Page models e.g. BlogIndexPage featured_section_1_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_1 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='First featured section for the homepage. Will display up to ' 'three child items.', verbose_name='Featured section 1') featured_section_2_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_2 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Second featured section for the homepage. Will display up to ' 'three child items.', verbose_name='Featured section 2') featured_section_3_title = models.CharField( null=True, blank=True, max_length=255, help_text='Title to display above the promo copy') featured_section_3 = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', help_text='Third featured section for the homepage. Will display up to ' 'six child items.', verbose_name='Featured section 3') content_panels = Page.content_panels + [ MultiFieldPanel([ ImageChooserPanel('image'), FieldPanel('hero_text', classname="full"), MultiFieldPanel([ FieldPanel('hero_cta'), PageChooserPanel('hero_cta_link'), ]), ], heading="Hero section"), MultiFieldPanel([ ImageChooserPanel('promo_image'), FieldPanel('promo_title'), FieldPanel('promo_text'), ], heading="Promo section"), StreamFieldPanel('body'), MultiFieldPanel([ MultiFieldPanel([ FieldPanel('featured_section_1_title'), PageChooserPanel('featured_section_1'), ]), MultiFieldPanel([ FieldPanel('featured_section_2_title'), PageChooserPanel('featured_section_2'), ]), MultiFieldPanel([ FieldPanel('featured_section_3_title'), PageChooserPanel('featured_section_3'), ]), ], heading="Featured homepage sections", classname="collapsible") ] def __str__(self): return self.title
class ProgrammePageRelatedSchoolsAndResearchPage(RelatedPage): source_page = ParentalKey( "ProgrammePage", related_name="related_schools_and_research_pages") panels = [PageChooserPanel("page", "schools.SchoolsAndResearchPage")] api_fields = [APIField("page")]
class PersonTopic(Orderable): person = ParentalKey("Person", related_name="topics") topic = ForeignKey("topics.Topic", on_delete=CASCADE, related_name="+") panels = [PageChooserPanel("topic")]
class FacultyResources(models.Model): resource = models.ForeignKey( FacultyResource, null=True, help_text="Manage resources through snippets.", related_name='+', on_delete=models.SET_NULL) def get_resource_heading(self): return self.resource.heading resource_heading = property(get_resource_heading) def get_resource_description(self): return self.resource.description resource_description = property(get_resource_description) def get_resource_unlocked(self): return self.resource.unlocked_resource resource_unlocked = property(get_resource_unlocked) def get_resource_creator_fest_resource(self): return self.resource.creator_fest_resource creator_fest_resource = property(get_resource_creator_fest_resource) link_external = models.URLField( "External link", blank=True, help_text= "Provide an external URL starting with https:// (or fill out either one of the following two)." ) link_page = models.ForeignKey( 'wagtailcore.Page', null=True, blank=True, related_name='+', on_delete=models.SET_NULL, help_text="Or select an existing page to attach.") link_document = models.ForeignKey( 'wagtaildocs.Document', null=True, blank=True, related_name='+', on_delete=models.SET_NULL, help_text="Or select a document for viewers to download.") def get_link_document(self): return build_document_url(self.link_document.url) link_document_url = property(get_link_document) def get_document_title(self): return self.link_document.title link_document_title = property(get_document_title) link_text = models.CharField(max_length=255, help_text="Call to Action Text") coming_soon_text = models.CharField( max_length=255, null=True, blank=True, help_text= "If there is text in this field a coming soon banner will be added with this description." ) video_reference_number = models.IntegerField(blank=True, null=True) updated = models.DateTimeField(blank=True, null=True, help_text='Late date resource was updated') featured = models.BooleanField( default=False, help_text="Add to featured bar on resource page") k12 = models.BooleanField(default=False, help_text="Add K12 banner to resource") print_link = models.URLField( blank=True, null=True, help_text="Link for Buy Print link on resource") api_fields = [ APIField('resource_heading'), APIField('resource_description'), APIField('resource_unlocked'), APIField('creator_fest_resource'), APIField('link_external'), APIField('link_page'), APIField('link_document_url'), APIField('link_document_title'), APIField('link_text'), APIField('coming_soon_text'), APIField('video_reference_number'), APIField('updated'), APIField('featured'), APIField('k12'), APIField('print_link') ] panels = [ SnippetChooserPanel('resource'), FieldPanel('link_external'), PageChooserPanel('link_page'), DocumentChooserPanel('link_document'), FieldPanel('link_text'), FieldPanel('coming_soon_text'), FieldPanel('video_reference_number'), FieldPanel('updated'), FieldPanel('featured'), FieldPanel('k12'), FieldPanel('print_link') ]
class RecordPage(ContentPage): formatted_title = models.CharField( max_length=255, null=True, blank=True, default='', help_text= "Use if you need italics in the title. e.g. <em>Italicized words</em>") date = models.DateField(default=datetime.date.today) category = models.CharField( max_length=255, choices=constants.record_page_categories.items()) read_next = models.ForeignKey('RecordPage', blank=True, null=True, default=get_previous_record_page, on_delete=models.SET_NULL) related_section_title = models.CharField( max_length=255, blank=True, default='Explore campaign finance data') related_section_url = models.CharField(max_length=255, blank=True, default='/data/') monthly_issue = models.CharField(max_length=255, blank=True, default='') monthly_issue_url = models.CharField(max_length=255, blank=True, default='') keywords = ClusterTaggableManager(through=RecordPageTag, blank=True) homepage_pin = models.BooleanField(default=False) homepage_pin_expiration = models.DateField(blank=True, null=True) homepage_pin_start = models.DateField(blank=True, null=True) homepage_hide = models.BooleanField(default=False) template = 'home/updates/record_page.html' content_panels = ContentPage.content_panels + [ FieldPanel('formatted_title'), FieldPanel('date'), FieldPanel('monthly_issue'), FieldPanel('category'), FieldPanel('keywords'), InlinePanel('authors', label='Authors'), PageChooserPanel('read_next'), FieldPanel('related_section_title'), FieldPanel('related_section_url') ] promote_panels = Page.promote_panels + [ MultiFieldPanel([ FieldPanel('homepage_pin'), FieldPanel('homepage_pin_start'), FieldPanel('homepage_pin_expiration'), FieldPanel('homepage_hide') ], heading="Home page feed") ] search_fields = ContentPage.search_fields + [ index.FilterField('category'), index.FilterField('date') ] @property def content_section(self): return '' @property def get_update_type(self): return constants.update_types['fec-record'] @property def get_author_office(self): return 'Information Division'