예제 #1
0
class Queue(BaseModel):
    job_type = CharField(null=False, max_length=16, index=True)
    is_control = BooleanField(null=False, default=False, index=True)
    priority = IntegerField(default=9, index=True)
    data_string = TextField(null=True)
    data_integer = IntegerField(null=True, index=True)
    date_touched = DateTimeField(default=datetime.datetime.now)
    blog = ForeignKeyField(Blog, index=True, null=False)
    site = ForeignKeyField(Site, index=True, null=False)
예제 #2
0
class Media(BaseModel):
    filename = CharField(null=False)
    path = EnforcedCharField(unique=True)
    local_path = EnforcedCharField(unique=True, null=True)  # deprecated?
    # should eventually be used to calculate where on the local filesystem
    # the file is when we are running in desktop mode, but I think we may
    # be able to deduce that from other things

    url = EnforcedCharField(unique=True, null=True)
    type = CharField(max_length=32, index=True)
    created_date = DateTimeField(default=datetime.datetime.now)
    modified_date = DateTimeField(default=datetime.datetime.now)
    friendly_name = TextField(null=True)
    tag_text = TextField(null=True)
    user = ForeignKeyField(User, null=False)
    blog = ForeignKeyField(Blog, null=True)
    site = ForeignKeyField(Site, null=True)

    @property
    def name(self):
        return self.friendly_name

    @property
    def link_format(self):
        return "{}/blog/{}/media/{}/edit".format(BASE_URL, str(self.blog.id),
                                                 self.id)

    @property
    def preview_url(self):
        '''
        In desktop mode, returns a preview_url
        otherwise, returns the mapped URL to the media
        as if it were being accessed through the site in question
        (assuming it can be found there)
        '''
        if DESKTOP_MODE:
            return BASE_URL + "/media/" + str(self.id)
        else:
            return self.url

    @property
    def associated_with(self):
        '''
        Returns a listing of all pages this media is associated with.
        '''
        associated_with = MediaAssociation.select().where(
            MediaAssociation.media == self)

        return associated_with

    @property
    def preview_for_listing(self):
        return '''
<a href="media/{}/edit"><img style="max-height:50px" src="{}"></a>'''.format(
            self.id, self.preview_url)
예제 #3
0
class PageCategory(BaseModel):

    page = ForeignKeyField(Page, null=False, index=True)
    category = ForeignKeyField(Category, null=False, index=True)
    primary = BooleanField(default=True)

    @property
    def next_in_category(self):

        pass

    @property
    def previous_in_category(self):

        pass
예제 #4
0
class KeyValue(BaseModel):

    object = CharField(max_length=64, null=False, index=True)  # table name
    objectid = IntegerField(null=True, index=True)
    key = EnforcedCharField(null=False, default="Key", index=True)
    value = TextField(null=True)
    parent = ForeignKeyField('self', null=True, index=True)
    is_schema = BooleanField(default=False)
    is_unique = BooleanField(default=False)
    value_type = CharField(max_length=64)

    def children(self, field=None, value=None):
        if self.is_schema is False:
            return None
        else:
            children = self.select().where(KeyValue.parent == self)

        if field is not None:
            children = children.select().where(
                getattr(KeyValue, field) == value)

        return children

    def siblings(self, field=None, value=None):
        if self.parent is None:
            return None
        else:
            siblings = self.select().where(KeyValue.parent == self.parent)

        if field is not None:
            siblings = siblings.select().where(
                getattr(KeyValue, field) == value)

        return siblings
예제 #5
0
class Tag(BaseModel):
    tag = TextField()
    blog = ForeignKeyField(Blog, null=False, index=True)
    is_hidden = BooleanField(default=False, index=True)

    @property
    def in_pages(self):

        tagged_pages = TagAssociation.select(
            TagAssociation.page).where(TagAssociation.tag == self).tuples()

        in_pages = Page.select().where(Page.id << tagged_pages)

        return in_pages

    @property
    def for_listing(self):

        template = tag_link_template.format(id=self.id,
                                            url=BASE_URL + "/blog/" +
                                            str(self.blog.id) + "/tag/" +
                                            str(self.id),
                                            tag=html_escape(self.tag))

        return template

    @property
    def for_display(self):

        btn_type = 'warning' if self.tag[0] == "@" else 'info'

        template = tag_template.format(
            id=self.id,
            btn_type=btn_type,
            new='',
            tag=tag_link_template.format(id=self.id,
                                         url=BASE_URL + "/blog/" +
                                         str(self.blog.id) + "/tag/" +
                                         str(self.id),
                                         tag=html_escape(self.tag)))

        return template

    @property
    def new_tag_for_display(self):

        btn_type = 'warning' if self.tag[0] == "@" else 'info'

        template = tag_template.format(
            id=0,
            tag=new_tag_template.format(tag=html_escape(self.tag)),
            btn_type=btn_type,
            new='data-new-tag="{}" '.format(html_escape(self.tag)))

        return template
예제 #6
0
class Category(BaseModel):
    blog = ForeignKeyField(Blog, null=False, index=True)
    title = TextField()
    parent_category = IntegerField(default=None, null=True, index=True)
    default = BooleanField(default=False)

    @property
    def next_category(self):
        pass

    @property
    def previous_category(self):
        pass
예제 #7
0
class Page(BaseModel):

    title = TextField()
    type = IntegerField(
        default=0, index=True)  # 0 = regular blog post; 1 = standalone page
    path = EnforcedCharField(
        unique=True, null=True)  # only used if this is a standalone page
    external_path = EnforcedCharField(
        null=True, index=True)  # used for linking in an external file
    basename = TextField()
    user = ForeignKeyField(User, null=False, index=True)
    text = TextField()
    excerpt = TextField(null=True)
    blog = ForeignKeyField(Blog, null=False, index=True)
    created_date = DateTimeField(default=datetime.datetime.now)
    modified_date = DateTimeField(null=True)
    publication_date = DateTimeField(null=True, index=True)
    status = CharField(max_length=32,
                       index=True,
                       default=page_status.unpublished)
    tag_text = TextField(null=True)
    currently_edited_by = IntegerField(null=True)
    author = user

    @property
    def status_id(self):
        return page_status.id[self.status]

    @property
    def link_format(self):
        return '{}/page/{}/edit'.format(BASE_URL, self.id)

    @property
    def listing_id(self):
        return 'page_title_{}'.format(self.id)

    @property
    def paginated_text(self):
        paginated_text = self.text.split('<!-- pagebreak -->')
        return paginated_text

    @property
    def tags(self):
        tag_list = Tag.select().where(Tag.id << TagAssociation.select(
            TagAssociation.tag).where(TagAssociation.page == self)).order_by(
                Tag.tag)

        return tag_list

    @property
    def author(self):
        return self.user

    @property
    def revisions(self):
        revisions = PageRevision.select().where(
            PageRevision.page_id == self.id).order_by(
                PageRevision.modified_date.desc())

        return revisions

    @property
    def templates(self):
        '''
        Returns all page templates for this page.
        '''
        page_templates = Template.select().where(
            Template.blog == self.blog.id,
            Template.template_type == template_type.page)

        return page_templates

    @property
    def default_template(self):
        '''
        Returns the default page template used by this blog.
        '''
        default_template = self.templates.select().where(
            Template.default_type == archive_type.page).get()

        return default_template

    @property
    def archives(self):
        '''
        Returns all date-based archives for this page.
        '''
        page_templates = Template.select().where(
            Template.blog == self.blog.id,
            Template.template_type == template_type.archive)

        return page_templates

    @property
    def archive_mappings(self):
        '''
        Returns mappings for all date-based archives for this page.
        '''
        archive_mappings = TemplateMapping.select().where(
            TemplateMapping.template << self.archives.select(
                Template.id).tuples())

        return archive_mappings

    @property
    def template_mappings(self):
        '''
        Returns all template mappings associated with page for this blog.
        '''

        template_mappings = TemplateMapping.select().where(
            TemplateMapping.template << self.templates.select(
                Template.id).tuples())

        return template_mappings

    @property
    def default_template_mapping(self):
        '''
        Returns the default template mapping associated with this page.
        '''

        t = TemplateMapping.get(
            TemplateMapping.is_default == True,
            TemplateMapping.template << self.templates.select(
                Template.id).where(Template.default_type == "P").tuples())

        default_template_mapping = self.publication_date.date().strftime(
            t.path_string)

        return default_template_mapping

    @property
    def fileinfos(self):
        '''
        Returns any fileinfo objects associated with this page.
        '''

        fileinfos = FileInfo.select().where(FileInfo.page == self)

        return fileinfos

    @property
    def default_fileinfo(self):
        '''
        Returns the default fileinfo associated with the page.
        Useful if you have pages that have multiple mappings.
        '''

        default_fileinfo = FileInfo.get(
            FileInfo.page == self,
            FileInfo.template_mapping == self.default_template.default_mapping)

        return default_fileinfo

    @property
    def permalink(self):

        if self.id is not None:
            f_info = self.default_fileinfo
            permalink = self.blog.url + "/" + f_info.file_path
        else:
            permalink = ""

        return permalink

    @property
    def preview_permalink(self):
        '''
        TODO: the behavior of this function is wrong
        in both local and remote mode,
        it should specify a link to a temporary file
        generated from the current draft for the sake of a preview.
        '''

        if self.status_id == page_status.published:

            if DESKTOP_MODE is True:

                tags = template_tags(page_id=self.id)

                preview_permalink = tpl(
                    BASE_URL_ROOT + '/' + self.default_template_mapping + "." +
                    self.blog.base_extension + "?_=" + str(self.blog.id),
                    **tags.__dict__)
            else:
                preview_permalink = self.permalink

        else:
            preview_permalink = BASE_URL + "/page/" + str(self.id) + "/preview"

        return preview_permalink

    @property
    def categories(self):

        categories = PageCategory.select().where(PageCategory.page == self)

        return categories

    @property
    def primary_category(self):

        primary = self.categories.select().where(
            PageCategory.primary == True).get()

        return primary.category

    @property
    def media(self):
        '''
        Returns iterable of all Media types associated with an entry.
        '''

        media_association = MediaAssociation.select(MediaAssociation.id).where(
            MediaAssociation.page == self.id).tuples()

        media = Media.select().where(Media.id << media_association)

        return media

    @property
    def next_page(self):
        '''
        Returns the next published page in the blog, in ascending chronological order.
        '''

        try:

            next_page = self.blog.published_pages().select().where(
                Page.blog == self.blog,
                Page.publication_date > self.publication_date).order_by(
                    Page.publication_date.asc(), Page.id.asc()).get()

        except Page.DoesNotExist:

            next_page = None

        return next_page

    @property
    def previous_page(self):
        '''
        Returns the previous published page in the blog, in descending chronological order.
        '''

        try:

            previous_page = self.blog.published_pages().select().where(
                Page.blog == self.blog,
                Page.publication_date < self.publication_date).order_by(
                    Page.publication_date.desc(), Page.id.desc()).get()

        except Page.DoesNotExist:

            previous_page = None

        return previous_page

    @property
    def next_in_category(self):
        '''
        This returns a dictionary of categories associated with the current entry
        along with the next entry in that category
        This way we can say self.next_in_category[category_id], etc.
        '''
        pass

    @property
    def previous_in_category(self):
        pass

    def save(self,
             user,
             no_revision=False,
             backup_only=False,
             change_note=None):
        '''
        Wrapper for the model's .save() action, which also updates the
        PageRevision table to include a copy of the current revision of
        the page BEFORE the save is committed.
        '''
        from core.log import logger

        revision_save_result = None

        if no_revision == False and self.id is not None:
            page_revision = PageRevision.copy(self)
            revision_save_result = page_revision.save(user, self, False,
                                                      change_note)

        page_save_result = Model.save(self) if backup_only is False else None

        if revision_save_result is not None:
            logger.info("Page {} edited by user {}.".format(
                self.for_log, user.for_log))

        else:
            logger.info(
                "Page {} edited by user {} but without changes.".format(
                    self.for_log, user.for_log))

        return (page_save_result, revision_save_result)

    revision_fields = {'id': 'page_id'}
예제 #8
0
class Blog(SiteBase):
    site = ForeignKeyField(Site, null=False, index=True)
    theme = ForeignKeyField(Theme, null=True, index=True)

    @property
    def link_format(self):
        return "{}/blog/{}".format(BASE_URL, self.id)

    @property
    def media_path_(self, media_object=None):

        tags = template_tags(media=media_object, blog=self)

        template = tpl(self.media_path, **tags)

        # TODO: strip all newlines for a multi-line template?

        return template

    @property
    def users(self):

        blog_user_list = Permission.select(fn.Distinct(Permission.user)).where(
            Permission.site << [self.site, 0],
            Permission.blog << [self.id, 0]).tuples()

        blog_users = User.select().where(User.id << blog_user_list)

        return blog_users

    @property
    def max_revisions(self):
        return int(self.kv('MaxPageRevisions').value)

    @property
    def categories(self):
        '''
        Lists all categories for this blog in their proper hierarchical order.
        '''
        pass

    @property
    def permalink(self):
        return self.url

    def module(self, module_name):
        '''
        Returns a module from the current blog that matches this name.
        If no module of the name is found, it will attempt to also import a template.
        '''
        pass

    def pages(self, page_list=None):

        pages = Page.select(
            Page,
            PageCategory).where(Page.blog == self.id).join(PageCategory).where(
                PageCategory.primary == True).order_by(
                    Page.publication_date.desc(), Page.id.desc())

        if page_list is not None:
            pages = pages.select().where(Page.id << page_list)

        return pages

    def published_pages(self):

        published_pages = self.pages().select().where(
            Page.status == page_status.published)

        return published_pages

    def last_n_pages(self, count=0):
        '''
        Returns the most recent pages posted in a blog, ordered by publication date.
        Set count to zero to retrieve all published pages.
        '''

        last_n_pages = self.published_pages().select().order_by(
            Page.publication_date.desc())

        if count > 0:
            last_n_pages = last_n_pages.select().limit(count)

        return last_n_pages

    def last_n_edited_pages(self, count=5):

        last_n_edited_pages = self.pages().select().order_by(
            Page.modified_date.desc()).limit(count)

        return last_n_edited_pages

    @property
    def index_file(self):
        return self.base_index + "." + self.base_extension

    @property
    def media(self):
        '''
        Returns all Media types associated with a given blog.
        '''
        media = Media.select().where(Media.blog == self)

        return media

    @property
    def templates(self):
        '''
        Returns all templates associated with a given blog.
        '''
        templates_in_blog = Template.select().where(Template.blog == self)

        return templates_in_blog

    def template(self, template_id):

        template_in_blog = Template.select().where(Template.blog == self,
                                                   Template.id == template_id)

        return template_in_blog

    @property
    def index_templates(self):

        index_templates_in_blog = self.templates.select().where(
            Template.template_type == template_type.index)

        return index_templates_in_blog

    @property
    def archive(self, name):
        '''
        Gets the entry link for the named archive template.
        '''
        archive = self.templates.select().where(
            Template.title == name,
            Template.template_type == template_type.archive)
        archive.default_mapping.fileinfos

    @property
    def archive_templates(self):

        archive_templates_in_blog = self.templates.select().where(
            Template.template_type == template_type.archive)

        return archive_templates_in_blog

    @property
    def template_mappings(self):
        '''
        Returns all template mappings associated with a given blog.
        '''

        template_mappings_in_blog = TemplateMapping.select().where(
            TemplateMapping.id << self.templates.select(Template.id))

        return template_mappings_in_blog

    @property
    def fileinfos(self):
        '''
        Returns all fileinfos associated with a given blog.
        '''

        fileinfos_for_blog = FileInfo.select().where(
            FileInfo.template_mapping << self.template_mappings.select(
                TemplateMapping.id))

        return fileinfos_for_blog
예제 #9
0
class Permission(BaseModel):
    user = ForeignKeyField(User, index=True)
    permission = IntegerField(null=False)
    blog = ForeignKeyField(Blog, index=True, null=True)
    site = ForeignKeyField(Site, index=True, null=True)
예제 #10
0
class FileInfoContext(BaseModel):

    fileinfo = ForeignKeyField(FileInfo, null=False, index=True)
    object = CharField(max_length=1)
    ref = IntegerField(null=True)
예제 #11
0
class FileInfo(BaseModel):

    page = ForeignKeyField(Page, null=True, index=True)
    template_mapping = ForeignKeyField(TemplateMapping, null=False, index=True)
    file_path = EnforcedCharField(null=False)
    sitewide_file_path = EnforcedCharField(index=True, null=False, unique=True)
    url = EnforcedCharField(null=False, index=True, unique=True)
    modified_date = DateTimeField(default=datetime.datetime.now)
    mapping_sort = EnforcedCharField(null=True, default=None, index=True)

    @property
    def xref(self):
        xref = TemplateMapping.select().where(
            TemplateMapping.id == self.template_mapping).get()
        return xref

    @property
    def author(self):

        try:
            author = self.context.select().where(
                FileInfoContext.object == "A").get()
            author = author.ref
        except FileInfoContext.DoesNotExist:
            author = None
        return author

    @property
    def context(self):

        context = FileInfoContext.select().where(
            FileInfoContext.fileinfo == self).order_by(
                FileInfoContext.id.asc())

        return context

    @property
    def year(self):
        try:
            year = self.context.select().where(
                FileInfoContext.object == "Y").get()
            year = year.ref
        except FileInfoContext.DoesNotExist:
            year = None
        return year

    @property
    def month(self):

        try:
            month = self.context.select().where(
                FileInfoContext.object == "M").get()
            month = month.ref
        except FileInfoContext.DoesNotExist:
            month = None
        return month

    @property
    def category(self):

        try:
            category = self.context.select().where(
                FileInfoContext.object == "C").get()
            category = category.ref
        except FileInfoContext.DoesNotExist:
            category = None
        return category
예제 #12
0
class TagAssociation(BaseModel):
    tag = ForeignKeyField(Tag, null=False, index=True)
    page = ForeignKeyField(Page, null=True, index=True)
    media = ForeignKeyField(Media, null=True, index=True)
예제 #13
0
class MediaAssociation(BaseModel):

    media = ForeignKeyField(Media)
    page = ForeignKeyField(Page, null=True)
    blog = ForeignKeyField(Blog, null=True)
    site = ForeignKeyField(Site, null=True)
예제 #14
0
class TemplateMapping(BaseModel):

    template = ForeignKeyField(Template, null=False, index=True)
    is_default = BooleanField(default=False, null=True)
    path_string = TextField()
    # archive_type = IntegerField()
    # 1 = Index
    # 2 = Page
    # 3 = Date-Based
    # TODO: I believe this was deprecated a long time ago
    archive_xref = CharField(max_length=16, null=True)
    modified_date = DateTimeField(default=datetime.datetime.now)
    '''
    def _build_xrefs(self):

        from core import cms
        cms.purge_fileinfos(self.fileinfos)

        import re
        iterable_tags = (
            (re.compile('%Y'), 'Y'),
            (re.compile('%m'), 'M'),
            (re.compile('%d'), 'D'),
            (re.compile('\{\{page\.categories\}\}'), 'C'),
            (re.compile('\{\{page\.primary_category.?[^\}]*\}\}'), 'C'),  # Not yet implemented
            (re.compile('\{\{page\.user.?[^\}]*\}\}'), 'A')
            (re.compile('\{\{page\.author.?[^\}]*\}\}'), 'A')
            )

        match_pos = []

        for tag, func in iterable_tags:
            match = tag.search(self.path_string)
            if match is not None:
                match_pos.append((func, match.start()))

        sorted_match_list = sorted(match_pos, key=lambda row: row[1])

        context_string = "".join(n for n, m in sorted_match_list)

        self.archive_xref = context_string

        content_type = self.template.template_type
        if content_type == 'Page':
            cms.build_pages_fileinfos(self.template.blog.pages())
        if content_type == 'Archive':
            cms.build_archives_fileinfos(self.template.blog.pages())
        if content_type == 'Index':
            cms.build_indexes_fileinfos(self.template.blog.index_templates())
    '''
    @property
    def fileinfos(self):
        '''
        Returns a list of all fileinfos associated with the selected template mapping.
        '''
        fileinfos = FileInfo.select().where(FileInfo.template_mapping == self)

        return fileinfos

    @property
    def next_in_mapping(self):
        '''
        Stub for the next archive entry for a given template.
        Determines from xref map.
        We should have the template mapping as part of a context as well.
        I don't think we do this yet.

        '''
        pass

    @property
    def previous_in_mapping(self):
        pass

    @property
    def first_in_mapping(self):

        pass

    @property
    def last_in_mapping(self):
        pass
예제 #15
0
class Template(BaseModel):
    title = TextField(default="Untitled Template", null=False)
    theme = ForeignKeyField(Theme, null=False, index=True)
    template_type = CharField(max_length=32, index=True, null=False)
    blog = ForeignKeyField(Blog, null=False, index=True)
    body = TextField(null=True)
    publishing_mode = CharField(max_length=32, index=True, null=False)
    external_path = TextField(
        null=True)  # used for linking in an external file
    modified_date = DateTimeField(default=datetime.datetime.now)
    is_include = BooleanField(default=False, null=True)
    default_type = CharField(max_length=32, default=None, null=True)

    def include(self, include_name):
        include = Template.get(Template.title == include_name,
                               Template.theme == self.theme.id)
        return include.body

    @property
    def includes(self):
        # get most recent fileinfo for page
        # use that to compute includes
        # we may want to make that something we can control the context for
        pass

    @property
    def mappings(self):
        '''
        Returns all file mappings for the template.
        '''
        template_mappings = TemplateMapping.select().where(
            TemplateMapping.template == self)
        return template_mappings

    @property
    def fileinfos(self):
        '''
        Returns a list of all fileinfos associated with the selected template.
        '''
        fileinfos = FileInfo.select().where(
            FileInfo.template_mapping << self.mappings)
        return fileinfos

    @property
    def fileinfos_published(self):
        if self.template_type == "Page":
            return self.fileinfos.select().join(Page).where(
                Page.status == page_status.published)
        else:
            if self.publishing_mode != publishing_mode.do_not_publish:
                return self.fileinfos

    @property
    def default_mapping(self):
        '''
        Returns the default file mapping for the template.
        '''
        default_mapping = TemplateMapping.select().where(
            TemplateMapping.template == self,
            TemplateMapping.is_default == True).get()
        return default_mapping