Browse Source

Got rid of the TopicQuery class and refactored the way how you can get the forum and the topics.

sh4nks 11 years ago
parent
commit
65f3333f8e
4 changed files with 51 additions and 187 deletions
  1. 36 8
      flaskbb/forum/models.py
  2. 5 27
      flaskbb/forum/views.py
  3. 10 10
      flaskbb/templates/forum/forum.html
  4. 0 142
      flaskbb/utils/query.py

+ 36 - 8
flaskbb/forum/models.py

@@ -261,8 +261,6 @@ class Topic(db.Model):
     __tablename__ = "topics"
     __tablename__ = "topics"
     __searchable__ = ['title', 'username']
     __searchable__ = ['title', 'username']
 
 
-    query_class = TopicQuery
-
     id = db.Column(db.Integer, primary_key=True)
     id = db.Column(db.Integer, primary_key=True)
     forum_id = db.Column(db.Integer,
     forum_id = db.Column(db.Integer,
                          db.ForeignKey("forums.id",
                          db.ForeignKey("forums.id",
@@ -746,16 +744,29 @@ class Forum(db.Model):
     # Classmethods
     # Classmethods
     @classmethod
     @classmethod
     def get_forum(cls, forum_id, user):
     def get_forum(cls, forum_id, user):
-        """Returns the forum with the forumsread object for the user.
+        """Returns the forum and forumsread object as a tuple for the user.
 
 
         :param forum_id: The forum id
         :param forum_id: The forum id
 
 
         :param user: The user object
         :param user: The user object
         """
         """
-        pass
+        if user.is_authenticated():
+            forum, forumsread = Forum.query.\
+                filter(Forum.id == forum_id).\
+                options(db.joinedload("category")).\
+                outerjoin(ForumsRead,
+                          db.and_(ForumsRead.forum_id == Forum.id,
+                                  ForumsRead.user_id == user.id)).\
+                add_entity(ForumsRead).\
+                first_or_404()
+        else:
+            forum = Forum.query.filter(Forum.id == forum_id).first_or_404()
+            forumsread = None
+
+        return forum, forumsread
 
 
     @classmethod
     @classmethod
-    def get_topics(cls, forum_id, user, per_page=20):
+    def get_topics(cls, forum_id, user, page=1, per_page=20):
         """Get the topics for the forum. If the user is logged in,
         """Get the topics for the forum. If the user is logged in,
         it will perform an outerjoin for the topics with the topicsread and
         it will perform an outerjoin for the topics with the topicsread and
         forumsread relation to check if it is read or unread.
         forumsread relation to check if it is read or unread.
@@ -764,9 +775,24 @@ class Forum(db.Model):
 
 
         :param user: The user object
         :param user: The user object
         """
         """
-        # Do pagination stuff here, so that we can get rid of the TopicQuery
-        # class
-        pass
+        if user.is_authenticated():
+            topics = Topic.query.filter_by(forum_id=forum_id).\
+                filter(Post.topic_id == Topic.id).\
+                outerjoin(TopicsRead,
+                          db.and_(TopicsRead.topic_id == Topic.id,
+                                  TopicsRead.user_id == user.id)).\
+                add_entity(TopicsRead).\
+                order_by(Post.id.desc()).\
+                paginate(page, per_page, True)
+        else:
+            topics = Topic.query.filter_by(forum_id=forum_id).\
+                filter(Post.topic_id == Topic.id).\
+                order_by(Post.id.desc()).\
+                paginate(page, per_page, True)
+
+            topics.items = [(topic, None) for topic in topics.items]
+
+        return topics
 
 
 
 
 class Category(db.Model):
 class Category(db.Model):
@@ -848,12 +874,14 @@ class Category(db.Model):
                                   ForumsRead.user_id == user.id)).\
                                   ForumsRead.user_id == user.id)).\
                 add_entity(Forum).\
                 add_entity(Forum).\
                 add_entity(ForumsRead).\
                 add_entity(ForumsRead).\
+                order_by(Category.id, Category.position, Forum.position).\
                 all()
                 all()
         else:
         else:
             # Get all the forums
             # Get all the forums
             forums = cls.query.\
             forums = cls.query.\
                 join(Forum, cls.id == Forum.category_id).\
                 join(Forum, cls.id == Forum.category_id).\
                 add_entity(Forum).\
                 add_entity(Forum).\
+                order_by(Category.id, Category.position, Forum.position).\
                 all()
                 all()
 
 
         return get_categories_and_forums(forums, user)
         return get_categories_and_forums(forums, user)

+ 5 - 27
flaskbb/forum/views.py

@@ -78,34 +78,12 @@ def view_category(category_id, slug=None):
 def view_forum(forum_id, slug=None):
 def view_forum(forum_id, slug=None):
     page = request.args.get('page', 1, type=int)
     page = request.args.get('page', 1, type=int)
 
 
-    if current_user.is_authenticated():
-        forum = Forum.query.\
-            filter(Forum.id == forum_id).\
-            options(db.joinedload("category")).\
-            outerjoin(ForumsRead,
-                      db.and_(ForumsRead.forum_id == Forum.id,
-                              ForumsRead.user_id == current_user.id)).\
-            add_entity(ForumsRead).\
-            first_or_404()
-
-        topics = Topic.query.filter_by(forum_id=forum[0].id).\
-            filter(Post.topic_id == Topic.id).\
-            outerjoin(TopicsRead,
-                      db.and_(TopicsRead.topic_id == Topic.id,
-                              TopicsRead.user_id == current_user.id)).\
-            add_entity(TopicsRead).\
-            order_by(Post.id.desc()).\
-            paginate(page, current_app.config['TOPICS_PER_PAGE'], True)
-    else:
-        forum = Forum.query.filter(Forum.id == forum_id).first_or_404()
-        forum = (forum, None)
-
-        topics = Topic.query.filter_by(forum_id=forum[0].id).\
-            filter(Post.topic_id == Topic.id).\
-            order_by(Post.id.desc()).\
-            paginate(page, current_app.config['TOPICS_PER_PAGE'], True, True)
+    forum, forumsread = Forum.get_forum(forum_id=forum_id, user=current_user)
+    topics = Forum.get_topics(forum_id=forum.id, user=current_user, page=page,
+                              per_page=current_app.config["TOPICS_PER_PAGE"])
 
 
-    return render_template("forum/forum.html", forum=forum, topics=topics)
+    return render_template("forum/forum.html", forum=forum, topics=topics,
+                           forumsread=forumsread,)
 
 
 
 
 @forum.route("/topic/<int:topic_id>", methods=["POST", "GET"])
 @forum.route("/topic/<int:topic_id>", methods=["POST", "GET"])

+ 10 - 10
flaskbb/templates/forum/forum.html

@@ -1,4 +1,4 @@
-{% set page_title = forum[0].title %}
+{% set page_title = forum.title %}
 {% set active_forum_nav=True %}
 {% set active_forum_nav=True %}
 
 
 {% extends theme("layout.html") %}
 {% extends theme("layout.html") %}
@@ -7,27 +7,27 @@
 
 
 <ol class="breadcrumb">
 <ol class="breadcrumb">
     <li><a href="{{ url_for('forum.index') }}">Forum</a></li>
     <li><a href="{{ url_for('forum.index') }}">Forum</a></li>
-    <li><a href="{{ forum[0].category.url }}">{{ forum[0].category.title }}</a></li>
-    <li class="active">{{ forum[0].title }}</li>
+    <li><a href="{{ forum.category.url }}">{{ forum.category.title }}</a></li>
+    <li class="active">{{ forum.title }}</li>
 </ol>
 </ol>
 
 
 <div class="pull-left" style="padding-bottom: 10px">
 <div class="pull-left" style="padding-bottom: 10px">
-    {{ render_pagination(topics, forum[0].url) }}
+    {{ render_pagination(topics, forum.url) }}
 </div> <!-- end span pagination -->
 </div> <!-- end span pagination -->
 
 
-{% if current_user|post_topic(forum[0]) %}
+{% if current_user|post_topic(forum) %}
 <div class="pull-right" style="padding-bottom: 10px">
 <div class="pull-right" style="padding-bottom: 10px">
     <div class="btn-group">
     <div class="btn-group">
-        <a href="{{ url_for('forum.markread', forum_id=forum[0].id, slug=forum[0].slug) }}" class="btn btn-default">
+        <a href="{{ url_for('forum.markread', forum_id=forum.id, slug=forum.slug) }}" class="btn btn-default">
             <span class="fa fa-check"></span> Mark as Read
             <span class="fa fa-check"></span> Mark as Read
         </a>
         </a>
 
 
-        {% if forum[0].locked %}
+        {% if forum.locked %}
         <span class="btn btn-primary">
         <span class="btn btn-primary">
             <span class="fa fa-lock"></span> Locked
             <span class="fa fa-lock"></span> Locked
         </span>
         </span>
         {% else %}
         {% else %}
-        <a href="{{ url_for('forum.new_topic', forum_id=forum[0].id, slug=forum[0].slug) }}" class="btn btn-primary">
+        <a href="{{ url_for('forum.new_topic', forum_id=forum.id, slug=forum.slug) }}" class="btn btn-primary">
             <span class="fa fa-pencil"></span> New Topic
             <span class="fa fa-pencil"></span> New Topic
         </a>
         </a>
         {% endif %}
         {% endif %}
@@ -40,7 +40,7 @@
     <thead>
     <thead>
         <tr>
         <tr>
             <th colspan="5">
             <th colspan="5">
-                {{ forum[0].title }}
+                {{ forum.title }}
             </th>
             </th>
         </tr>
         </tr>
     </thead>
     </thead>
@@ -62,7 +62,7 @@
             {% if topic.locked %}
             {% if topic.locked %}
                 <span class="fa fa-locked" style="font-size: 2em"></span>
                 <span class="fa fa-locked" style="font-size: 2em"></span>
             {% else %}
             {% else %}
-                {% if topic|topic_is_unread(topicread, current_user, forum[1]) %}
+                {% if topic|topic_is_unread(topicread, current_user, forumsread) %}
                     <span class="fa fa-comment" style="font-size: 2em"></span>
                     <span class="fa fa-comment" style="font-size: 2em"></span>
                 {% else %}
                 {% else %}
                     <span class="fa fa-comment-o" style="font-size: 2em"></span>
                     <span class="fa fa-comment-o" style="font-size: 2em"></span>

+ 0 - 142
flaskbb/utils/query.py

@@ -1,142 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    flaskbb.utils.query
-    ~~~~~~~~~~~~~~~~~~~
-
-    This module holds the query classes that are used by flaskbb
-
-    :copyright: (c) 2014 by the FlaskBB Team.
-    :license: BSD, see LICENSE for more details.
-"""
-from math import ceil
-
-from flask import abort
-from flask.ext.sqlalchemy import BaseQuery
-
-
-class Pagination(object):
-    """Internal helper class returned by :meth:`BaseQuery.paginate`.  You
-    can also construct it from any other SQLAlchemy query object if you are
-    working with other libraries.  Additionally it is possible to pass `None`
-    as query object in which case the :meth:`prev` and :meth:`next` will
-    no longer work.
-    """
-
-    def __init__(self, query, page, per_page, total, items, add_none):
-        #: the unlimited query object that was used to create this
-        #: pagination object.
-        self.query = query
-        #: the current page number (1 indexed)
-        self.page = page
-        #: the number of items to be displayed on a page.
-        self.per_page = per_page
-        #: the total number of items matching the query
-        self.total = total
-        #: the items for the current page
-        if add_none:
-            self.items = [(item, None) for item in items]
-        else:
-            self.items = items
-
-    @property
-    def pages(self):
-        """The total number of pages"""
-        if self.per_page == 0:
-            pages = 0
-        else:
-            pages = int(ceil(self.total / float(self.per_page)))
-        return pages
-
-    def prev(self, error_out=False, add_none=False):
-        """Returns a :class:`Pagination` object for the previous page."""
-        assert self.query is not None, 'a query object is required ' \
-                                       'for this method to work'
-        return self.query.paginate(self.page - 1, self.per_page, error_out,
-                                   self.add_none)
-
-    @property
-    def prev_num(self):
-        """Number of the previous page."""
-        return self.page - 1
-
-    @property
-    def has_prev(self):
-        """True if a previous page exists"""
-        return self.page > 1
-
-    def next(self, error_out=False, add_none=False):
-        """Returns a :class:`Pagination` object for the next page."""
-        assert self.query is not None, 'a query object is required ' \
-                                       'for this method to work'
-        return self.query.paginate(self.page + 1, self.per_page, error_out,
-                                   self.add_none)
-
-    @property
-    def has_next(self):
-        """True if a next page exists."""
-        return self.page < self.pages
-
-    @property
-    def next_num(self):
-        """Number of the next page"""
-        return self.page + 1
-
-    def iter_pages(self, left_edge=2, left_current=2,
-                   right_current=5, right_edge=2):
-        """Iterates over the page numbers in the pagination.  The four
-        parameters control the thresholds how many numbers should be produced
-        from the sides.  Skipped page numbers are represented as `None`.
-        This is how you could render such a pagination in the templates:
-
-        .. sourcecode:: html+jinja
-
-            {% macro render_pagination(pagination, endpoint) %}
-              <div class=pagination>
-              {%- for page in pagination.iter_pages() %}
-                {% if page %}
-                  {% if page != pagination.page %}
-                    <a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
-                  {% else %}
-                    <strong>{{ page }}</strong>
-                  {% endif %}
-                {% else %}
-                  <span class=ellipsis>…</span>
-                {% endif %}
-              {%- endfor %}
-              </div>
-            {% endmacro %}
-        """
-        last = 0
-        for num in xrange(1, self.pages + 1):
-            if num <= left_edge or \
-               (num > self.page - left_current - 1 and
-                num < self.page + right_current) or \
-               num > self.pages - right_edge:
-                if last + 1 != num:
-                    yield None
-                yield num
-                last = num
-
-
-class TopicQuery(BaseQuery):
-    def paginate(self, page, per_page=20, error_out=True, add_none=False):
-        """Returns `per_page` items from page `page`.  By default it will
-        abort with 404 if no items were found and the page was larger than
-        1.  This behavor can be disabled by setting `error_out` to `False`.
-
-        Returns an :class:`Pagination` object.
-        """
-        if error_out and page < 1:
-            abort(404)
-        items = self.limit(per_page).offset((page - 1) * per_page).all()
-        if not items and page != 1 and error_out:
-            abort(404)
-
-        # No need to count if we're on the first page and there are fewer
-        # items than we expected.
-        if page == 1 and len(items) < per_page:
-            total = len(items)
-        else:
-            total = self.order_by(None).count()
-
-        return Pagination(self, page, per_page, total, items, add_none)