Example #1
0
class BlogPost(BaseRichTextPage):
    date = models.DateField('Post Date', default=date.today)
    tags = ClusterTaggableManager(through=BlogPostTag, blank=True)
    featured = models.BooleanField(default=False,
                                   help_text="Feature this post")

    subpage_types = []

    search_name = 'Blog post'

    search_fields = BaseRichTextPage.search_fields + (
        index.FilterField('date'),
        index.FilterField('featured'),
    )

    @property
    def blog_index(self):
        # Find blog index in ancestors
        for ancestor in reversed(self.get_ancestors()):
            if isinstance(ancestor.specific, BlogIndexPage):
                return ancestor

        # No ancestors are blog indexes,
        # just return first blog index in database
        return BlogIndexPage.objects.first()
Example #2
0
class StaticPage(Page):
    # TODO: Keep it simple for now.
    content = RichTextField(blank=True)
    language = models.CharField(max_length=7, choices=settings.LANGUAGES)

    def __str__(self):
        return self.title

    content_panels = Page.content_panels + [
        FieldPanel('content'),
        FieldPanel('language'),
    ]

    search_fields = Page.search_fields + [
        index.SearchField('title', partial_match=True,
                          boost=SearchBoost.TITLE),
        index.SearchField('language'),
        index.FilterField('get_search_type'),
        index.FilterField('language')
    ]

    def get_search_type(self):
        return self.__class__.__name__.lower()

    def get_absolute_url(self):
        return reverse("static_page", kwargs={"slug": self.slug})
Example #3
0
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
Example #4
0
class Resource(Page):
    date = models.DateField(blank=True, null=True)
    content = StreamField([
        ("authors", blocks.RichTextBlock(blank=True)),
        ("copyright", blocks.RichTextBlock(blank=True)),
        ("focus", blocks.RichTextBlock(blank=True)),
        ("factoids", blocks.RichTextBlock(blank=True)),
    ])
    embed_url = models.URLField()
    embed_thumbnail = models.TextField(blank=True, null=True)
    categories = M2MField("category.Category",
                          related_name="resources_by_category")
    language = models.CharField(max_length=7, choices=settings.LANGUAGES)

    search_fields = Page.search_fields + [
        index.SearchField('title', partial_match=True,
                          boost=SearchBoost.TITLE),
        index.SearchField('language'),
        index.SearchField(
            'content', partial_match=True, boost=SearchBoost.CONTENT),
        index.FilterField('date'),
        index.FilterField('categories'),
        index.FilterField('language'),
        index.FilterField('get_search_type'),
    ]

    def get_search_type(self):
        return self.__class__.__name__.lower()

    def get_absolute_url(self):
        return reverse("resource-detail", kwargs={"slug": self.slug})

    def get_template(self, request, *args, **kwargs):
        self.template = "resources/resource_detail.html"
        return super(Resource, self).get_template(request, *args, **kwargs)

    def get_context(self, request, *args, **kwargs):
        return {'resource': self, 'request': request}

    content_panels = Page.content_panels + [
        FieldPanel('language'),
        FieldPanel('embed_url'),
        FieldPanel('embed_thumbnail'),
        StreamFieldPanel('content'),
        FieldPanel('categories'),
        FieldPanel('date'),
    ]

    @property
    def featured_image(self):
        return None

    def __str__(self):
        return self.title
Example #5
0
class GoogleFormPage(Page):
    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')

    # TODO: Limit to one form!
    form_en = StreamField([('google_form', GoogleFormBlock())])
    form_sv = StreamField([('google_form', GoogleFormBlock())])
    form = TranslatedField('form_en', 'form_sv')

    deadline = models.DateField(verbose_name=_('Form deadline'))

    results_en = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES,
        blank=True,
    )
    results_sv = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES,
        blank=True,
    )
    results = TranslatedField('results_en', 'results_sv')

    @property
    def is_past_due(self) -> bool:
        return date.today() > self.deadline

    # Editor panels configuration
    content_panels = Page.content_panels + [
        FieldPanel('title_sv', classname="full title"),
        FieldPanel('deadline'),
        StreamFieldPanel('form_en'),
        StreamFieldPanel('form_sv'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading=_('Common')),
        ObjectList([StreamFieldPanel('results_en')], heading=_('English')),
        ObjectList([StreamFieldPanel('results_sv')], heading=_('Swedish')),
        ObjectList(Page.promote_panels + Page.settings_panels,
                   heading=_('Settings')),
    ])

    # Search index configuration
    search_fields = Page.search_fields + [
        index.SearchField('title_sv'),
        index.FilterField('results_en'),
        index.FilterField('results_sv'),
        index.FilterField('deadline'),
    ]

    # Parent page / subpage type rules
    parent_page_types = ['google.GoogleFormIndex']
    subpage_types = []
Example #6
0
class NewsPage(Page):
    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')

    body_en = RichTextField()
    body_sv = RichTextField()
    body = TranslatedField('body_en', 'body_sv')

    created = models.DateTimeField(
        verbose_name=_('Created at'),
        auto_now_add=True,
    )
    modified = models.DateTimeField(
        verbose_name=_('Modified at'),
        auto_now=True,
    )

    feed_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    # Search index configuration
    search_fields = Page.search_fields + [
        index.SearchField('title_sv'),
        index.SearchField('body_en'),
        index.SearchField('body_sv'),
        index.FilterField('created'),
        index.FilterField('modified'),
    ]

    # Editor panels configuration
    content_panels = Page.content_panels + [
        FieldPanel('body_en', classname="full"),
    ]
    content_panels_sv = [
        FieldPanel('title_sv', classname="full title"),
        FieldPanel('body_sv', classname="full"),
    ]
    promote_panels = [ImageChooserPanel('feed_image')] + Page.promote_panels

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading=_('English')),
        ObjectList(content_panels_sv, heading=_('Swedish')),
        ObjectList(promote_panels, heading=_('Promote')),
        ObjectList(Page.settings_panels, heading=_('Settings')),
    ])

    # Parent page / sub-page type rules
    parent_page_types = ['news.NewsIndexPage']
    subpage_types = []
Example #7
0
class SearchTest(index.Indexed, models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    live = models.BooleanField(default=False)
    published_date = models.DateField(null=True)
    tags = TaggableManager()

    search_fields = [
        index.SearchField('title', partial_match=True),
        index.RelatedFields('tags', [
            index.SearchField('name', partial_match=True),
            index.FilterField('slug'),
        ]),
        index.RelatedFields('subobjects', [
            index.SearchField('name', partial_match=True),
        ]),
        index.SearchField('content', boost=2),
        index.SearchField('callable_indexed_field'),
        index.FilterField('title'),
        index.FilterField('live'),
        index.FilterField('published_date'),
    ]

    def callable_indexed_field(self):
        return "Callable"

    @classmethod
    def get_indexed_objects(cls):
        indexed_objects = super(SearchTest, cls).get_indexed_objects()

        # Exclude SearchTests that have a SearchTestChild to stop update_index creating duplicates
        if cls is SearchTest:
            indexed_objects = indexed_objects.exclude(
                id__in=SearchTestChild.objects.all().values_list(
                    'searchtest_ptr_id', flat=True))

        # Exclude SearchTests that have the title "Don't index me!"
        indexed_objects = indexed_objects.exclude(title="Don't index me!")

        return indexed_objects

    def get_indexed_instance(self):
        # Check if there is a SearchTestChild that descends from this
        child = SearchTestChild.objects.filter(
            searchtest_ptr_id=self.id).first()

        # Return the child if there is one, otherwise return self
        return child or self

    def __str__(self):
        return self.title
Example #8
0
class Book(index.Indexed, models.Model):
    title = models.CharField(max_length=255)
    authors = models.ManyToManyField(Author, related_name='books')
    publication_date = models.DateField()
    number_of_pages = models.IntegerField()
    tags = TaggableManager()

    search_fields = [
        index.SearchField('title', partial_match=True, boost=2.0),
        index.FilterField('title'),
        index.RelatedFields('authors', Author.search_fields),
        index.FilterField('publication_date'),
        index.FilterField('number_of_pages'),
        index.RelatedFields('tags', [
            index.SearchField('name'),
            index.FilterField('slug'),
        ]),
    ]

    @classmethod
    def get_indexed_objects(cls):
        indexed_objects = super(Book, cls).get_indexed_objects()

        # Don't index books using Book class that they have a more specific type
        if cls is Book:
            indexed_objects = indexed_objects.exclude(
                id__in=Novel.objects.values_list('book_ptr_id', flat=True))

            indexed_objects = indexed_objects.exclude(
                id__in=ProgrammingGuide.objects.values_list('book_ptr_id',
                                                            flat=True))

        # Exclude Books that have the title "Don't index me!"
        indexed_objects = indexed_objects.exclude(title="Don't index me!")

        return indexed_objects

    def get_indexed_instance(self):
        # Check if this object is a Novel or ProgrammingGuide and return the specific object
        novel = Novel.objects.filter(book_ptr_id=self.id).first()
        programming_guide = ProgrammingGuide.objects.filter(
            book_ptr_id=self.id).first()

        # Return the novel/programming guide object if there is one, otherwise return self
        return novel or programming_guide or self

    def __str__(self):
        return self.title
Example #9
0
class Lesson(Page):
    parent_page_types = ['lessons.LessonIndex']

    date = models.DateField("Post date")
    body = StreamField([
        ('heading',
         blocks.CharBlock(classname="full title",
                          template='blocks/heading.html')),
        ('paragraph', blocks.RichTextBlock()),
        ('code', CodeBlock()),
        ('image', ImageChooserBlock()),
        ('video', EmbedBlock()),
    ])

    search_fields = Page.search_fields + [
        index.SearchField('body'),
        index.FilterField('date'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        StreamFieldPanel('body'),
        InlinePanel('techs', label="Mentioned technologies"),
        InlinePanel('books', label="Mentioned books"),
        InlinePanel('related_article_links', label="Related links"),
    ]
Example #10
0
class Content(Page):
    body = StreamField([
        ('heading', blocks.CharBlock(classname="full title")),
        ('rich_text', blocks.RichTextBlock()),
        ('raw', blocks.RawHTMLBlock()),
        ('include_content', blocks.CharBlock()),
        ('content_list', blocks.CharBlock()),
    ],
                       null=True,
                       blank=True)
    date = models.DateField("Content updated date", default=timezone.now)

    promote_panels = Page.promote_panels + [
        FieldPanel('date'),
    ]

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
    ]

    search_fields = Page.search_fields + (
        index.SearchField('body'),
        index.FilterField('url_path'),
    )

    def serve(self, request):
        if "draft" in request.GET:
            return HttpResponseRedirect("/admin/pages/{}/view_draft/".format(
                self.pk))
        return super(Content, self).serve(request)

    class Meta:
        ordering = ("date", )
Example #11
0
class Entry(index.Indexed, models.Model):
    title = models.CharField('Title', max_length=255, unique=True)
    slug = AutoSlugField(populate_from='title')
    description = models.TextField('Description', )
    acronym = models.BooleanField(
        'Is an acronym',
        default=False,
    )

    class Meta:
        verbose_name = 'Entry'
        verbose_name_plural = 'Entries'
        ordering = ['title']

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('glossary:detail', args=[self.slug])

    panels = [
        FieldPanel('title'),
        # FieldPanel('slug'),
        FieldPanel('description'),
        FieldPanel('acronym'),
    ]

    search_fields = [
        index.SearchField('title'),
        index.SearchField('description'),
        index.FilterField('acronym'),
    ]
Example #12
0
class StandardPage(Page):
    body = RichTextUploadingField(blank=True)

    sidebar_image = models.ForeignKey('wagtailimages.Image',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL,
                                      related_name='+')

    sidebar_caption = models.CharField(max_length=250, blank=True)

    search_fields = Page.search_fields + (  # Inherit search_fields from Page
        index.SearchField('body'),
        index.FilterField('sidebar_caption'),
    )

    content_panels = Page.content_panels + [
        FieldPanel('body', classname="full"),
        ImageChooserPanel('sidebar_image'),
        FieldPanel('sidebar_caption'),
    ]

    def get_template(self, request, *args, **kwargs):
        parent = self.get_parent()
        print parent
        if parent is None:
            return "pagecontent/home_page.html"
        elif parent.content_type.model == 'standardpage':
            return "pagecontent/standard_subpage.html"
        else:
            return super(StandardPage,
                         self).get_template(request, *args, **kwargs)
Example #13
0
class AbstractEmbedVideo(CollectionMember, index.Indexed, models.Model):
    title = models.CharField(max_length=255, verbose_name=_('Title'))
    url = EmbedVideoField()
    thumbnail = models.ForeignKey(image_model_name,
                                  verbose_name=_('Thumbnail'),
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    created_at = models.DateTimeField(auto_now_add=True,
                                      verbose_name=_('Created'))
    uploaded_by_user = models.ForeignKey(settings.AUTH_USER_MODEL,
                                         null=True,
                                         blank=True,
                                         editable=False,
                                         verbose_name=_('Uploader'))

    tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))

    def get_usage(self):
        return get_object_usage(self)

    @property
    def usage_url(self):
        return reverse('wagtail_embed_videos:video_usage', args=(self.id, ))

    search_fields = CollectionMember.search_fields + [
        index.SearchField('title', partial_match=True, boost=10),
        index.RelatedFields('tags', [
            index.SearchField('name', partial_match=True, boost=10),
        ]),
        index.FilterField('uploaded_by_user'),
    ]

    def __str__(self):
        return self.title

    def __init__(self, *args, **kwargs):

        super(AbstractEmbedVideo, self).__init__(*args, **kwargs)
        if args:
            if args[3] is None:
                create_thumbnail(self)

    def save(self, *args, **kwargs):
        super(AbstractEmbedVideo, self).save(*args, **kwargs)
        if not self.thumbnail:
            create_thumbnail(self)

    @property
    def default_alt_text(self):
        return self.title

    def is_editable_by_user(self, user):
        from .permissions import permission_policy
        return permission_policy.user_has_permission_for_instance(
            user, 'change', self)

    class Meta:
        abstract = True
Example #14
0
class Episode(Page):
    podcast = models.CharField(max_length=10, default="")
    main_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')
    epID = models.CharField(max_length=10, default=0)
    description = RichTextField(blank=True)
    summary = RichTextField(blank=True)
    published_date = models.CharField(max_length=50, default="")
    image_URL = models.CharField(max_length=300, default="")
    quote = models.CharField(max_length=300, default="", blank=True)
    #others = (Page.objects.all()[3].get_children()[1])

    content_panels = Page.content_panels + [
        FieldPanel('podcast'),
        FieldPanel('epID'),
        FieldPanel('summary'),
        FieldPanel('description'),
        FieldPanel('quote'),
        FieldPanel('image_URL'),
        ImageChooserPanel('main_image'),
        FieldPanel('published_date'),
        InlinePanel('related_links', label="Related links")
    ]

    search_fields = Page.search_fields + [  # Inherit search_fields from Page
        index.FilterField('podcast'),
    ]
Example #15
0
class DigestPage(ContentPage):
    date = models.DateField(default=datetime.date.today)
    read_next = models.ForeignKey('DigestPage', blank=True, null=True,
                                  default=get_previous_digest_page,
                                  on_delete=models.SET_NULL)

    content_panels = ContentPage.content_panels + [
        FieldPanel('date'),
        InlinePanel('authors', label="Authors"),
        PageChooserPanel('read_next'),
    ]

    template = 'home/updates/digest_page.html'

    search_fields =  ContentPage.search_fields + [
        index.FilterField('date')
    ]

    @property
    def content_section(self):
        return ''

    @property
    def get_update_type(self):
        return constants.update_types['weekly-digest']

    @property
    def get_author_office(self):
        return 'Press Office'
class GenericPage(Page):

    # Database fields
    category = StreamField([('cat_title_class',
                             blocks.CharBlock(classname="full")),
                            ('cat_title', blocks.CharBlock(classname="full"))])
    body = StreamField(InfowebStreamBlock())
    date = models.DateField("Post date")
    feed_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    # Search index configuraiton

    search_fields = Page.search_fields + (
        index.SearchField('body'),
        index.FilterField('date'),
    )

    # Editor panels configuration

    content_panels = Page.content_panels + [
        StreamFieldPanel('category'),
        StreamFieldPanel('body'),
        FieldPanel('date'),
    ]

    promote_panels = [
        MultiFieldPanel(Page.promote_panels, "Common page configuration"),
        ImageChooserPanel('feed_image'),
    ]
class AbstractEmbedVideo(models.Model, TagSearchable):
    title = models.CharField(max_length=255, verbose_name=_('Title'))
    url = EmbedVideoField()
    thumbnail = models.ForeignKey('wagtailimages.Image',
                                  verbose_name="Thumbnail",
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    created_at = models.DateTimeField(auto_now_add=True)
    uploaded_by_user = models.ForeignKey(settings.AUTH_USER_MODEL,
                                         null=True,
                                         blank=True,
                                         editable=False)

    tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))

    def get_usage(self):
        return get_object_usage(self)

    @property
    def usage_url(self):
        return reverse('wagtail_embed_videos_video_usage', args=(self.id, ))

    search_fields = TagSearchable.search_fields + (
        index.FilterField('uploaded_by_user'), )

    def __str__(self):
        return self.title

    def __init__(self, *args, **kwargs):

        super(AbstractEmbedVideo, self).__init__(*args, **kwargs)
        if args:
            if args[3] is None:
                create_thumbnail(self)

    def save(self, *args, **kwargs):
        super(AbstractEmbedVideo, self).save(*args, **kwargs)
        if not self.thumbnail:
            create_thumbnail(self)

    @property
    def default_alt_text(self):
        return self.title

    def is_editable_by_user(self, user):
        if user.has_perm('wagtail_embed_videos.change_embedvideo'):
            # user has global permission to change videos
            return True
        elif user.has_perm('wagtail_embed_videos.add_embedvideo'
                           ) and self.uploaded_by_user == user:
            # user has video add permission, which also implicitly provides permission to edit their own videos
            return True
        else:
            return False

    class Meta:
        abstract = True
Example #18
0
class SearchTest(models.Model, index.Indexed):
    title = models.CharField(max_length=255)
    content = models.TextField()
    live = models.BooleanField(default=False)
    published_date = models.DateField(null=True)

    search_fields = [
        index.SearchField('title', partial_match=True),
        index.SearchField('content'),
        index.SearchField('callable_indexed_field'),
        index.FilterField('title'),
        index.FilterField('live'),
        index.FilterField('published_date'),
    ]

    def callable_indexed_field(self):
        return "Callable"
Example #19
0
    def test_basic(self):
        cls = self.make_dummy_type([
            index.SearchField('test', boost=100, partial_match=False),
            index.FilterField('filter_test'),
        ])

        self.assertEqual(len(cls.get_search_fields()), 2)
        self.assertEqual(len(cls.get_searchable_search_fields()), 1)
        self.assertEqual(len(cls.get_filterable_search_fields()), 1)
Example #20
0
    def test_different_field_types_dont_override(self):
        # A search and filter field with the same name should be able to coexist
        cls = self.make_dummy_type([
            index.SearchField('test', boost=100, partial_match=False),
            index.FilterField('test'),
        ])

        self.assertEqual(len(cls.get_search_fields()), 2)
        self.assertEqual(len(cls.get_searchable_search_fields()), 1)
        self.assertEqual(len(cls.get_filterable_search_fields()), 1)
Example #21
0
class GuidelinesPage(Page):
    strap = models.TextField(blank=True)
    template = 'core/guidelines.html'
    content = StreamField([
        ("heading_title", blocks.CharBlock()),
        ("heading_content", blocks.RichTextBlock()),
        ("sub_section_with_heading", SubSectionBlock()),
        ("sub_section_without_heading", blocks.RichTextBlock()),
    ],
                          blank=True)
    language = models.CharField(max_length=7,
                                choices=settings.LANGUAGES,
                                default="English")

    content_panels = Page.content_panels + [
        FieldPanel('strap'),
        MultiFieldPanel([StreamFieldPanel('content')],
                        heading="Content",
                        classname="collapsible "),
        FieldPanel('language'),
    ]

    search_fields = Page.search_fields + [
        index.FilterField('content', partial_match=True),
        index.SearchField('content'),
        index.FilterField('language'),
        index.SearchField('language')
    ]

    def get_context(self, request, *args, **kwargs):
        guideline_dict = construct_guidelines(self.content)
        return {
            'page': self,
            'request': request,
            'page_content': guideline_dict,
            "tab": 'about-pari'
        }

    def __str__(self):
        return _("GuidelinesPage")

    def get_absolute_url(self):
        return reverse("static_page", kwargs={"slug": self.slug})
Example #22
0
class Document(models.Model, TagSearchable):
    title = models.CharField(max_length=255, verbose_name=_('Title'))
    file = models.FileField(upload_to='documents', verbose_name=_('File'))
    created_at = models.DateTimeField(verbose_name=_('Created at'),
                                      auto_now_add=True)
    uploaded_by_user = models.ForeignKey(settings.AUTH_USER_MODEL,
                                         verbose_name=_('Uploaded by user'),
                                         null=True,
                                         blank=True,
                                         editable=False)

    tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))

    search_fields = TagSearchable.search_fields + (
        index.FilterField('uploaded_by_user'), )

    def __str__(self):
        return self.title

    @property
    def filename(self):
        return os.path.basename(self.file.name)

    @property
    def file_extension(self):
        parts = self.filename.split('.')
        if len(parts) > 1:
            return parts[-1]
        else:
            return ''

    @property
    def url(self):
        return reverse('wagtaildocs_serve', args=[self.id, self.filename])

    def get_usage(self):
        return get_object_usage(self)

    @property
    def usage_url(self):
        return reverse('wagtaildocs_document_usage', args=(self.id, ))

    def is_editable_by_user(self, user):
        if user.has_perm('wagtaildocs.change_document'):
            # user has global permission to change documents
            return True
        elif user.has_perm(
                'wagtaildocs.add_document') and self.uploaded_by_user == user:
            # user has document add permission, which also implicitly provides permission to edit their own documents
            return True
        else:
            return False

    class Meta:
        verbose_name = _('Document')
Example #23
0
class AbstractDocument(CollectionMember, index.Indexed, models.Model):
    title = models.CharField(max_length=255, verbose_name=_('title'))
    file = models.FileField(upload_to='documents', verbose_name=_('file'))
    created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True)
    uploaded_by_user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name=_('uploaded by user'),
        null=True,
        blank=True,
        editable=False,
        on_delete=models.SET_NULL
    )

    tags = TaggableManager(help_text=None, blank=True, verbose_name=_('tags'))

    objects = DocumentQuerySet.as_manager()

    search_fields = CollectionMember.search_fields + [
        index.SearchField('title', partial_match=True, boost=10),
        index.RelatedFields('tags', [
            index.SearchField('name', partial_match=True, boost=10),
        ]),
        index.FilterField('uploaded_by_user'),
    ]

    def __str__(self):
        return self.title

    @property
    def filename(self):
        return os.path.basename(self.file.name)

    @property
    def file_extension(self):
        return os.path.splitext(self.filename)[1][1:]

    @property
    def url(self):
        return reverse('wagtaildocs_serve', args=[self.id, self.filename])

    def get_usage(self):
        return get_object_usage(self)

    @property
    def usage_url(self):
        return reverse('wagtaildocs:document_usage',
                       args=(self.id,))

    def is_editable_by_user(self, user):
        from wagtail.wagtaildocs.permissions import permission_policy
        return permission_policy.user_has_permission_for_instance(user, 'change', self)

    class Meta:
        abstract = True
        verbose_name = _('document')
Example #24
0
class JournalDocument(AbstractDocument, ReferencedObjectMixin):
    '''
    Override the base Document model so we can index the Document contents for search
    and add reference to JournalAboutPage
    '''

    file = models.FileField(
        upload_to='documents',
        verbose_name=_('PDF document'),
        validators=[
            FileTypeValidator(
                allowed_types=settings.ALLOWED_DOCUMENT_TYPES,
                allowed_extensions=settings.ALLOWED_DOCUMENT_FILE_EXTENSIONS)
        ])

    search_fields = AbstractDocument.search_fields + [
        index.SearchField('data', partial_match=False),
        index.FilterField('id'),
    ]

    admin_form_fields = Document.admin_form_fields

    def data(self):
        '''
        Return the contents of the document as base64 encoded
        data used as input to elasticsearch ingest-attachment plugin
        '''
        # converting to base64 is (Size * 8)/6 times bigger than binary file
        # determine the max number of bytes we can read to not exceed the max upload size
        read_max = (settings.MAX_ELASTICSEARCH_UPLOAD_SIZE * 6) / 8
        self.file.open()
        contents = base64.b64encode(self.file.read(
            int(read_max))).decode('ascii')
        self.file.close()
        return contents

    def get_viewer_url(self, base_url):
        '''
        Return full url to document viewer for this document
        '''
        if self.is_pdf():
            return urljoin(
                base_url,
                'static/pdf_js/web/viewer.html?file={document_path}'.format(
                    document_path=self.file.url)  # pylint: disable=no-member
            )
        else:
            return urljoin(base_url, self.file.url)  # pylint: disable=no-member

    def is_pdf(self):
        return mimetypes.MimeTypes().guess_type(
            self.filename)[0] == 'application/pdf'

    def get_object_type(self):
        return "document"
Example #25
0
class Content(Page):
    body = StreamField([
        ('heading', blocks.CharBlock(classname='full title')),
        ('rich_text', blocks.RichTextBlock()),
        ('raw', blocks.RawHTMLBlock()),
        ('include_content', blocks.CharBlock()),
        ('content_list', blocks.CharBlock()),
    ],
                       null=True,
                       blank=True)
    date = models.DateField('Content updated date', default=timezone.now)
    template_filename = models.CharField(max_length=64,
                                         choices=(
                                             ('content.html', 'content.html'),
                                             ('f6-content.html',
                                              'f6-content.html'),
                                             ('f6-vue.html', 'f6-vue.html'),
                                         ),
                                         default='f6-content.html')
    tags = ClusterTaggableManager(through=ContentTag, blank=True)

    def get_template(self, request, *args, **kwargs):
        template_name = request.GET.get('template', self.template_filename)
        return '{}/{}'.format(self.__class__._meta.app_label, template_name)

    promote_panels = Page.promote_panels + [
        FieldPanel('date'), FieldPanel('tags')
    ]

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
    ]

    settings_panels = Page.settings_panels + [FieldPanel('template_filename')]

    search_fields = Page.search_fields + [
        index.SearchField('body'),
        index.FilterField('url_path'),
    ]

    def serve(self, request):
        if 'draft' in request.GET:
            return HttpResponseRedirect('/admin/pages/{}/view_draft/'.format(
                self.pk))
        response = super(Content, self).serve(request)
        if 'embed' in request.GET:
            with open(
                    os.path.join(settings.MEDIA_ROOT, 'images',
                                 self.slug + '.html')) as output:
                output.write(response.content)
        return response

    class Meta:
        ordering = ('date', )
Example #26
0
class EntryPage(Page, Entry):
    # Search
    search_fields = Page.search_fields + (
        index.SearchField('body'),
        index.SearchField('excerpt'),
        index.FilterField('page_ptr_id')
    )

    # Panels
    content_panels = [
        MultiFieldPanel([
            FieldPanel('title', classname="title"),
            ImageChooserPanel('header_image'),
            FieldPanel('body', classname="full"),
            FieldPanel('excerpt', classname="full"),
        ], heading=_("Content")),
        MultiFieldPanel([
            FieldPanel('tags'),
            InlinePanel('entry_categories', label=_("Categories")),
            InlinePanel('related_entrypage_from', label=_("Related Entries")),
        ], heading=_("Metadata")),
    ] + getattr(Entry, 'content_panels', [])

    promote_panels = Page.promote_panels + getattr(Entry, 'promote_panels', [])

    settings_panels = Page.settings_panels + [
        FieldPanel('date'),
        FieldPanel('owner'),
    ] + getattr(Entry, 'settings_panels', [])

    # Parent and child settings
    parent_page_types = ['puput.BlogPage']
    subpage_types = []

    @property
    def blog_page(self):
        return BlogPage.objects.ancestor_of(self).first()

    @property
    def related(self):
        return [related.entrypage_to for related in self.related_entrypage_from.all()]

    @property
    def has_related(self):
        return self.related_entrypage_from.count() > 0

    def get_context(self, request, *args, **kwargs):
        context = super(EntryPage, self).get_context(request, *args, **kwargs)
        context['blog_page'] = self.blog_page
        return context

    class Meta:
        verbose_name = _('Entry')
        verbose_name_plural = _('Entries')
Example #27
0
class Author(index.Indexed, models.Model):
    name = models.CharField(max_length=255)
    date_of_birth = models.DateField(null=True)

    search_fields = [
        index.SearchField('name'),
        index.FilterField('date_of_birth'),
    ]

    def __str__(self):
        return self.name
Example #28
0
class ProgrammingGuide(Book):
    programming_language = models.CharField(max_length=255,
                                            choices=[
                                                ('py', "Python"),
                                                ('js', "Javascript"),
                                                ('rs', "Rust"),
                                            ])

    search_fields = Book.search_fields + [
        index.SearchField('get_programming_language_display'),
        index.FilterField('programming_language'),
    ]
Example #29
0
class ContentArticle(Page):
    template = 'articles/article.html'
    date = models.DateField()

    # Each block will show up when adding elements to a page in the CMS
    body = StreamField([
        ('paragraph',
         blocks.RichTextBlock(icon='edit',
                              template='wagtail_blocks/paragraph.html')),
        ('image',
         ImageChooserBlock(icon='image',
                           template='wagtail_blocks/image.html')),
        ('full_width_image',
         ImageChooserBlock(icon='image',
                           template='wagtail_blocks/full_width_image.html')),
    ])

    # We want to be able to tag articles with certain categories
    tags = ClusterTaggableManager(through=ArticleTag, blank=True)

    image = models.ForeignKey("wagtailimages.Image",
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL,
                              related_name="+")
    author = models.CharField(max_length=200, null=True, blank=True)

    search_fields = Page.search_fields + [
        index.FilterField('title'),
        index.FilterField('author'),
        index.SearchField('body'),
        index.FilterField('date'),
    ]
    content_panels = Page.content_panels + [
        FieldPanel('date'),
        FieldPanel('tags'),
        FieldPanel('author'),
        StreamFieldPanel('body'),
        InlinePanel('related_links', label="Related links"),
    ]
Example #30
0
class AbstractGiphy(CollectionMember, index.Indexed, models.Model):
    title = models.CharField(max_length=255, verbose_name=_('title'))
    file = models.FileField(
        verbose_name=_('file'), upload_to=get_upload_to,
    )
    created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True, db_index=True)
    uploaded_by_user = models.ForeignKey(
        settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'),
        null=True, blank=True, editable=False, on_delete=models.SET_NULL
    )

    tags = TaggableManager(help_text=None, blank=True, verbose_name=_('tags'))
    file_size = models.PositiveIntegerField(null=True, editable=False)

    def get_file_size(self):
        if self.file_size is None:
            try:
                self.file_size = self.file.size
            except OSError:
                # File doesn't exist
                return

            self.save(update_fields=['file_size'])

        return self.file_size

    def get_upload_to(self, filename):
        folder_name = 'giphy'
        filename = self.file.field.storage.get_valid_name(filename)

        created_at = self.file.created_at
        return os.path.join(folder_name, '{y}/{m}/{d}/{filename}'.format(**{
            'y': created_at.year,
            'm': created_at.month,
            'd': created_at.day,
            'filename': filename
        }))

    def __str__(self):
        return self.title

    search_fields = CollectionMember.search_fields + [
        index.SearchField('title', partial_match=True, boost=10),
        index.RelatedFields('tags', [
            index.SearchField('name', partial_match=True, boost=10),
        ]),
        index.FilterField('uploaded_by_user'),
    ]

    class Meta:
        abstract = True