Beispiel #1
0
class Vote(db.Model, SerializableObject):
    """Users are able to vote for the entries in the forum they like.
    Additionally to the score (-1 or +1) users are able to mark the
    entry as one of their favorites."""
    __tablename__ = 'forum_vote'
    __table_args__ = (db.UniqueConstraint('entry_id', 'user_id'), {})

    query = db.session.query_property(VoteQuery)

    #: Serializer attributes
    object_type = 'forum.vote'
    public_fields = ('id', 'entry_id', 'user', 'score', 'favorite')

    id = db.Column(db.Integer, primary_key=True)
    entry_id = db.Column(db.Integer,
                         db.ForeignKey('forum_entry.entry_id'),
                         nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
    score = db.ColumnProperty(db.Column(db.Integer, nullable=False, default=0),
                              extension=VoteScoreExtension())
    favorite = db.Column(db.Boolean, nullable=False, default=False)

    user = db.relationship(User,
                           backref='votes',
                           lazy='joined',
                           innerjoin=True)
Beispiel #2
0
class Answer(ForumEntry):
    __tablename__ = 'forum_answer'
    __mapper_args__ = {
        'extension': SearchIndexMapperExtension('portal', 'answer'),
        'polymorphic_identity': u'answer'
    }

    #: Serializer attributes
    object_type = 'forum.answer'
    public_fields = ('entry_id', 'discriminator', 'author', 'date_created',
                     'date_active', 'score', 'text', 'votes', 'question')

    id = db.Column(db.Integer,
                   db.ForeignKey(ForumEntry.entry_id),
                   primary_key=True)
    question_id = db.Column(db.Integer, db.ForeignKey(Question.id))

    question = db.relationship(Question,
                               backref=db.backref(
                                   'answers',
                                   extension=QuestionAnswersExtension()),
                               primaryjoin=(question_id == Question.id))

    def get_url_values(self, **kwargs):
        """Generates an URL for this answer."""
        kwargs.update({'entry_id': self.id})
        return 'forum/answer', kwargs
Beispiel #3
0
class TestSubscriptionCategory(db.Model):
    __tablename__ = '_test_subscription_category'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30))
Beispiel #4
0
class Other(db.Model):
    __tablename__ = '_test_subscription_other'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    wrapper_id = db.Column(db.ForeignKey(Wrapper.id))
    wrapper = db.relationship(Wrapper)
Beispiel #5
0
class TestSubscriptionComment(db.Model):
    __tablename__ = '_test_subscription_comment'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    entry_id = db.Column(db.ForeignKey(TestSubscriptionEntry.id),
                         nullable=False)
    entry = db.relationship(TestSubscriptionEntry)
Beispiel #6
0
class TestSubscriptionEntry(db.Model):
    __tablename__ = '_test_subscription_entry'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    category_id = db.Column(db.ForeignKey(TestSubscriptionCategory.id))
    category = db.relationship(TestSubscriptionCategory)
    title = db.Column(db.String(30))
Beispiel #7
0
class Event(db.Model, SerializableObject, TextRendererMixin):
    __tablename__ = 'event_event'
    __mapper_args__ = {'extension': db.SlugGenerator('slug', 'title')}
    # To order all queries by default, something like
    # __mapper_args__ = {'order_by':Event.start_date.asc()
    # has to be added to this class. No idea how to do that, now

    query = db.session.query_property(EventQuery)

    # serializer properties
    object_type = 'event.event'
    public_fields = ('id', 'title', 'slug', 'text', 'author', 'start', 'end',
                     'tags', 'discussion_question_id', 'info_question_id')

    #: Model columns
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.Unicode(100), nullable=False)
    slug = db.Column(db.Unicode(100), unique=True, index=True)
    text = db.Column(db.Text, nullable=False)
    author_id = db.Column(db.ForeignKey(User.id), nullable=False)
    start_date = db.Column(db.DateTime, nullable=False)
    end_date = db.Column(db.DateTime, nullable=False)
    tags = db.relationship(Tag,
                           secondary=event_tag,
                           backref=db.backref('events', lazy='dynamic'),
                           lazy='joined',
                           extension=TagCounterExtension())
    discussion_question_id = db.Column(db.ForeignKey(Question.id),
                                       nullable=True)
    info_question_id = db.Column(db.ForeignKey(Question.id), nullable=True)

    author = db.relationship(User, lazy='joined')

    discussion_question = db.relationship(
        Question,
        primaryjoin=Question.id == discussion_question_id,
        backref=db.backref('eventd'))

    info_question = db.relationship(
        Question,
        primaryjoin=Question.id == info_question_id,
        backref=db.backref('eventi'))

    def get_url_values(self, action='view'):
        values = {
            'view': 'event/view',
            'browse': 'event/browse',
            'calendar': 'event/calendar',
            'edit': 'admin/event/edit',
        }
        return values[action], {'id': self.id}

    def __unicode__(self):
        return self.title
Beispiel #8
0
class TestSubscriptionTag(db.Model):
    __tablename__ = '_test_subscription_tag'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    entries = db.relationship(TestSubscriptionEntry,
                              secondary=_entry_tag,
                              backref='tags',
                              lazy='joined')
Beispiel #9
0
class Question(ForumEntry):
    """A :class:`Question` is an :class:`ForumEntry` with a title, a slug and
    several tags."""
    __tablename__ = 'forum_question'
    __mapper_args__ = {
        'extension': (db.SlugGenerator('slug', 'title'),
                      SearchIndexMapperExtension('portal', 'question')),
        'polymorphic_identity':
        u'question'
    }
    query = db.session.query_property(QuestionQuery)

    #: Serializer attributes
    object_type = 'forum.question'
    public_fields = ('entry_id', 'discriminator', 'author', 'date_created',
                     'date_active', 'score', 'text', 'votes', 'tags', 'id',
                     'title', 'slug')

    id = db.Column(db.Integer,
                   db.ForeignKey(ForumEntry.entry_id),
                   primary_key=True)
    title = db.Column(db.Unicode(160), nullable=False)
    slug = db.Column(db.Unicode(160), nullable=False, index=True)
    answer_count = db.Column(db.Integer, default=0)

    tags = db.relationship(Tag,
                           secondary=question_tag,
                           lazy='subquery',
                           backref=db.backref('questions', lazy='dynamic'),
                           extension=TagCounterExtension())

    def get_url_values(self, **kwargs):
        """Generates an URL for this question."""
        action = kwargs.get('action')
        if action == 'vote-up':
            return 'forum/vote', {'entry_id': self.id, 'action': 'up'}
        elif action == 'vote-down':
            return 'forum/vote', {'entry_id': self.id, 'action': 'down'}
        kwargs.update({'slug': self.slug})
        return 'forum/question', kwargs

    def __unicode__(self):
        return self.title
Beispiel #10
0
class ForumEntry(db.Model, SerializableObject, TextRendererMixin):
    """The base class of a :class:`Question` or :class:`Answer`, which contains
    some general information about the author and the creation date, as well as
    the actual text and the votings."""

    __tablename__ = 'forum_entry'
    query = db.session.query_property(ForumEntryQuery)

    #: Serializer attributes
    object_type = 'forum.entry'
    public_fields = ('entry_id', 'discriminator', 'author', 'date_created',
                     'date_active', 'score', 'text', 'votes')

    entry_id = db.Column(db.Integer, primary_key=True)
    discriminator = db.Column('type', db.Unicode(12))
    author_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             default=datetime.utcnow)
    date_active = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)
    score = db.Column(db.Integer, nullable=False, default=0)
    text = db.Column(db.Text, nullable=False)
    view_count = db.Column(db.Integer, default=0, nullable=False)

    author = db.relationship(User, lazy='joined', innerjoin=True)
    votes = db.relationship('Vote',
                            backref='entry',
                            extension=ForumEntryVotesExtension())

    __mapper_args__ = {'polymorphic_on': discriminator}

    def touch(self):
        db.atomic_add(self, 'view_count', 1)

    def get_vote(self, user):
        return Vote.query.filter_by(user=user, entry=self).first()
Beispiel #11
0
class Forum(db.Model, SerializableObject):
    __tablename__ = 'forum_forum'
    __mapper_args__ = {'extension': db.SlugGenerator('slug', 'name')}
    query = db.session.query_property(ForumQuery)

    #: serializer attributes
    object_type = 'forum.forum'
    public_fields = ('id', 'name', 'slug', 'description', 'tags'
                     'position', 'subforums')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(80), nullable=False)
    slug = db.Column(db.Unicode(80), unique=True, index=True)
    description = db.Column(db.Unicode(200), nullable=False, default=u'')
    parent_id = db.Column(db.Integer,
                          db.ForeignKey(id),
                          nullable=True,
                          index=True)
    position = db.Column(db.Integer, nullable=False, default=0, index=True)

    subforums = db.relationship('Forum',
                                backref=db.backref('parent', remote_side=id),
                                lazy='joined')
    tags = db.relationship(Tag,
                           secondary=forum_tag,
                           lazy='dynamic',
                           backref=db.backref('forums', lazy='dynamic'),
                           extension=TagCounterExtension())

    @cached_property
    def all_tags(self):
        """Return all tags for this forum, including those of the subforums."""
        tags = list(self.tags)
        for subforum in self.subforums:
            tags.extend(subforum.tags)
        return tags

    def get_url_values(self, **kwargs):
        kwargs.update({'forum': self.slug})
        return 'forum/questions', kwargs
Beispiel #12
0
class Comment(db.Model, TextRendererMixin):
    __tablename__ = 'news_comment'

    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text, nullable=False)
    pub_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    deleted = db.Column(db.Boolean, nullable=False, default=False)

    author_id = db.Column(db.Integer, db.ForeignKey(User.id))
    author = db.relationship(User,
                             backref=db.backref('comments', lazy='dynamic'))
    article_id = db.Column(db.Integer, db.ForeignKey('news_article.id'))

    def get_url_values(self, action='view'):
        if action in ('hide', 'restore', 'edit'):
            return 'news/edit_comment', {'id': self.id, 'action': action}
        return 'news/detail', {
            'slug': self.article.slug,
            '_anchor': 'comment_%s' % self.id
        }

    def __unicode__(self):
        return _(u'Comment by %s on %s') % (self.author.display_name,
                                            self.article.title)
Beispiel #13
0
class Wrapper(db.Model):
    __tablename__ = '_test_subscription_wrapper'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
Beispiel #14
0
class TestSubscriptionComment(db.Model):
    __tablename__ = '_test_subscription_comment'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    entry_id = db.Column(db.ForeignKey(TestSubscriptionEntry.id),
                         nullable=False)
    entry = db.relationship(TestSubscriptionEntry)


_entry_tag = db.Table(
    '_test_subscription_entry_tag',
    db.metadata,
    db.Column('entry_id', db.Integer, db.ForeignKey(TestSubscriptionEntry.id)),
    db.Column('tag_id', db.Integer,
              db.ForeignKey('_test_subscription_tag.id')),
)
TestResourceManager.register_models(_entry_tag)


class TestSubscriptionTag(db.Model):
    __tablename__ = '_test_subscription_tag'

    manager = TestResourceManager

    id = db.Column(db.Integer, primary_key=True)
    entries = db.relationship(TestSubscriptionEntry,
                              secondary=_entry_tag,
                              backref='tags',
Beispiel #15
0
class PasteEntry(db.Model, SerializableObject):
    __tablename__ = 'paste_entry'

    # serializer properties
    object_type = 'paste.entry'
    public_fields = ('id', 'text', 'title', 'author', 'pub_date', 'language',
                     'hidden')

    #: Model columns
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text, nullable=False)

    title = db.Column(db.Unicode(50), nullable=True)

    language = db.Column(db.Unicode(30))
    author_id = db.Column(db.ForeignKey(User.id), nullable=False)
    pub_date = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
    hidden = db.Column(db.Boolean, default=False)

    author = db.relationship(User, lazy='joined')

    # revision model implementation
    parent_id = db.Column(db.Integer, db.ForeignKey(id), nullable=True)
    children = db.relationship('PasteEntry',
                               cascade='all',
                               primaryjoin=parent_id == id,
                               backref=db.backref('parent', remote_side=id))

    def get_url_values(self, action='view'):
        if action == 'reply':
            return 'paste/index', {'reply_to': self.id}
        values = {
            'view': 'paste/view',
            'raw': 'paste/raw',
            'show_tree': 'paste/show_tree',
            'edit': 'paste/edit',
        }
        return values[action], {'id': self.id}

    @property
    def display_title(self):
        if self.title:
            return self.title
        return _(u'Paste #%d') % self.id

    @property
    def highlighted_text(self):
        return highlight_text(self.text, self.language)

    @property
    def has_tree(self):
        return bool(self.children) or bool(self.parent_id)

    def compare_to(self, other, column, context_lines=4, template=False):
        """Compare the model with another revision.

        Special version to enable highlighting between files.

        :param other: The other model instance to compare with.
        :param column: A string what column to compare.
        :param context_lines: How many additional lines to show on the udiff.
        :param template: Either or not to prepare the udiff for templates use.
        """
        differ = generate_highlighted_udiff if template else generate_udiff

        generator = partial(differ,
                            old=getattr(self, column, u''),
                            new=getattr(other, column, u''),
                            old_title=unicode(self),
                            new_title=unicode(other),
                            context_lines=context_lines)

        if template:
            udiff = generator(old_lang=self.language, new_lang=other.language)
        else:
            udiff = generator()

        if template:
            diff = prepare_udiff(udiff, True)
            return diff and diff[0] or None
        return udiff

    @classmethod
    def resolve_root(cls, identifier):
        """Find the root for a tree.

        :param identifier: The identifier a model should queried for.
                           We use ``cls.query.get`` to query the identifier.
        :returns: The very root object with no additional parent_id set.
        """
        obj = cls.query.get(identifier)
        if obj is None:
            return
        while obj.parent_id is not None:
            obj = obj.parent
        return obj

    def __unicode__(self):
        return self.display_title

    def __repr__(self):
        if self.title:
            s = repr(self.title)
        else:
            s = '#%s' % self.id if self.id else '[no id]'
        u = self.author.username
        return '<PasteEntry %s by %s>' % (s, u)
Beispiel #16
0
class Article(db.Model, TextRendererMixin):
    __tablename__ = 'news_article'
    __mapper_args__ = {
        'extension':
        (db.SlugGenerator('slug', 'title'),
         SearchIndexMapperExtension('portal',
                                    'news'), db.GuidGenerator('news/article'))
    }
    query = db.session.query_property(ArticleQuery)

    id = db.Column(db.Integer, primary_key=True)
    pub_date = db.Column(db.DateTime, default=datetime.utcnow)
    updated = db.Column(db.DateTime, default=datetime.utcnow)
    title = db.Column(db.Unicode(200))
    slug = db.Column(db.Unicode(100), unique=True)
    intro = db.Column(db.Text)
    text = db.Column(db.Text)
    public = db.Column(db.Boolean, default=False, nullable=False)
    view_count = db.Column(db.Integer, default=0, nullable=False)
    comment_count = db.Column(db.Integer, default=0, nullable=False)
    comments_enabled = db.Column(db.Boolean, default=True, nullable=False)
    guid = db.Column(db.Unicode(80), unique=True)

    tags = db.relationship(Tag,
                           secondary=article_tag,
                           backref=db.backref('articles', lazy='dynamic'),
                           lazy='joined',
                           extension=TagCounterExtension())
    author_id = db.Column(db.ForeignKey(User.id), nullable=False)
    author = db.relationship(User,
                             backref=db.backref('articles', lazy='dynamic'))
    comments = db.relationship(Comment,
                               backref=db.backref('article', lazy='joined'),
                               primaryjoin=id == Comment.article_id,
                               order_by=[db.asc(Comment.pub_date)],
                               lazy='dynamic',
                               cascade='all, delete, delete-orphan',
                               extension=CommentCounterExtension())

    @property
    def hidden(self):
        """
        This returns a boolean whether this article is not visible for normal
        users.
        Article that are not published or whose pub_date is in the future
        aren't shown for a normal user.
        """
        return not self.public or self.pub_date > datetime.utcnow()

    @property
    def was_updated(self):
        return self.updated.replace(microsecond=0) > \
               self.pub_date.replace(microsecond=0)

    def touch(self):
        db.atomic_add(self, 'view_count', 1)

    def get_url_values(self, **kwargs):
        action = kwargs.pop('action', 'view')
        if action in ('subscribe', 'unsubscribe'):
            return 'news/subscribe_comments', {
                'slug': self.slug,
                'action': action,
            }

        values = {
            'view': 'news/detail',
            'edit': 'news/article_edit',
            'delete': 'news/article_delete',
        }
        kwargs.update({'slug': self.slug})
        return values[action], kwargs

    def __unicode__(self):
        return self.title
Beispiel #17
0
    :copyright: 2010-2011 by the Inyoka Team, see AUTHORS for more details.
    :license: GNU GPL, see LICENSE for more details.
"""
from datetime import datetime
from collections import defaultdict
from werkzeug import cached_property
from inyoka.core.api import _, db, SerializableObject
from inyoka.core.auth.models import User
from inyoka.core.models import Tag, TagCounterExtension
from inyoka.core.mixins import TextRendererMixin
from inyoka.core.search import SearchIndexMapperExtension
from inyoka.portal.api import ITaggableContentProvider

question_tag = db.Table(
    'forum_question_tag', db.metadata,
    db.Column('question_id', db.Integer, db.ForeignKey('forum_question.id')),
    db.Column('tag_id', db.Integer, db.ForeignKey(Tag.id)))

forum_tag = db.Table(
    'forum_forum_tag', db.metadata,
    db.Column('forum_id', db.Integer, db.ForeignKey('forum_forum.id')),
    db.Column('tag_id', db.Integer, db.ForeignKey(Tag.id)),
    db.Column('propose', db.Boolean))


class QuestionsContentProvider(ITaggableContentProvider):
    type = 'forum_questions'
    name = _('Questions')

    def get_taggable_content(self, tag):
        return Question.query.order_by(Question.score, Question.view_count) \
Beispiel #18
0
    :copyright: 2009-2011 by the Inyoka Team, see AUTHORS for more details.
    :license: GNU GPL, see LICENSE for more details.
"""
import calendar
from datetime import datetime, timedelta
from inyoka.core.api import _, db
from inyoka.core.mixins import TextRendererMixin
from inyoka.core.auth.models import User
from inyoka.core.models import Tag, TagCounterExtension
from inyoka.core.serializer import SerializableObject
from inyoka.forum.models import Question

event_tag = db.Table(
    'event_event_tag', db.metadata,
    db.Column('event_id', db.Integer, db.ForeignKey('event_event.id')),
    db.Column('tag_id', db.Integer, db.ForeignKey(Tag.id)))


class EventQuery(db.Query):
    def start_in(self, year, month):
        """Return a query for all events that start in the given year and month

        :param year: The year that the event starts have to match
        :param month: The month that the event starts have to match
        """
        days_in_month = calendar.monthrange(year, month)[1]
        interval_begin = datetime(year, month, 1, 0, 0, 0)
        interval_end = datetime(year, month, days_in_month, 23, 59, 59)
        q = self.filter(
            db.and_(Event.start_date >= interval_begin,
Beispiel #19
0
    Database models for the Inyoka News application.

    :copyright: 2009-2011 by the Inyoka Team, see AUTHORS for more details.
    :license: GNU GPL, see LICENSE for more details.
"""
from datetime import datetime, timedelta
from inyoka.core.api import _, db
from inyoka.core.auth.models import User
from inyoka.core.mixins import TextRendererMixin
from inyoka.core.models import Tag, TagCounterExtension
from inyoka.core.search import SearchIndexMapperExtension
from inyoka.portal.api import ITaggableContentProvider

article_tag = db.Table(
    'news_article_tag', db.metadata,
    db.Column('article_id', db.Integer, db.ForeignKey('news_article.id')),
    db.Column('tag_id', db.Integer, db.ForeignKey(Tag.id)))


class ArticlesContentProvider(ITaggableContentProvider):
    type = 'news_articles'
    name = _('Articles')

    def get_taggable_content(self, tag):
        return tag.articles.order_by('view_count')


class CommentCounterExtension(db.AttributeExtension):
    def append(self, state, value, initiator):
        instance = state.obj()
        instance.comment_count += 1