使用分页路由单个帖子 - 烧瓶

时间:2014-04-23 21:10:03

标签: python pagination flask sqlalchemy flask-sqlalchemy

目标:路由到单个文章/博客帖子并包含分页(使用SQL-Alchemy),以便用户可以轻松导航到之前和之后的帖子。

目前,我有以下内容:

@app.route('/articles/ind/<int:id>', endpoint='article')
def indarticle(id = 1):
    posts= Post.query.paginate(id, 1, False)
    return render_template('article.html',
        title = "Article",
        posts = posts)

可以看出,我每页显示一篇文章,因此假设文章从ID = 1开始,ID和页码匹配。但是,如果它们不匹配(或从数据库中删除文章),则路由和呈现的页面不匹配。我可以轻松地遍历表格的行,找到哪个页码对应正确的文章ID;然而,这看起来并不高效或实用。

解决这个问题的最佳方法是什么?

更新: 迭代下面的答案,我创建了以下内容:

models.py

class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(100))
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

def get_count(self):
    return db.session.query(Post).count()

def prev_post(self):
    count = self.get_count()
    pid = self.id
    while (count > 0):
        prev_post = None
        pid = pid - 1
        if db.session.query(Post).get(pid) is not None:
            prev_post = db.session.query(Post).get(pid)
            break
        else:
            count = count - 1

    return prev_post

def next_post(self):
    count = self.get_count()
    pid = self.id
    while (count > 0):
        next_post = None
        pid = pid + 1
        if db.session.query(Post).get(pid) is not None:
            next_post = db.session.query(Post).get(pid)
            break
        else:
            count = count - 1

    return next_post

def has_prev(self):
    return True if self.prev_post() is not None else False

def has_next(self):
    return True if self.next_post() is not None else False

通过这种方式,我可以获得下一篇文章,上一篇文章,以及轻松检查它们是否存在,就像flask-sqlalchemy如何处理分页一样。

1 个答案:

答案 0 :(得分:1)

为了确保我们谈论同样的事情,有两种类型的分页....

首先,Flask支持的那种....调用所有文章并在每页显示X个帖子......

其次,你是一个职位,想要前进和后退。

听起来你想要做第二种。

我所做的是在我的POST模型中编写两个静态方法,找出上一个和下一个帖子......然后我通过我的视图函数将值传递给模板。

POST模型staticmethods

<强> MODEL

@staticmethod
def prev_post(pid):
    count = Post.get_count()
    while (count > 0):
        prev_post = None
        pid = pid - 1
        if db.session.query(Post).get(pid) is not None:
            prev_post = db.session.query(Post).get(pid)
            break
        else:
            count = count - 1
    return prev_post

@staticmethod
def next_post(pid):
    count = Post.get_count()
    while (count > 0):
        next_post = None
        pid = pid + 1
        if db.session.query(Post).get(pid) is not None:
            next_post = db.session.query(Post).get(pid)
            break
        else:
            count = count - 1
    return next_post

prev_post功能的工作原理。

  1. 使用帖子计数来设置我的while循环的范围。
  2. 在prev_post的情况下,指定None值,以便在找不到previous时模板逻辑工作。此外,如果未指定“无”并且您尝试传入视图,则会收到错误。
  3. 在prev_post的情况下,在每个循环中从pid中减去1并检查数据库中是否存在条目。
  4. 遍历循环,每次减1。
  5. 第一次找到匹配项时,打破循环并用post.id替换prev_post none值。
  6. 当然,下一个函数完全相同,除了你+1 pid而不是-1。

    这解决了删除帖子和显示错误号码的问题。另外,请注意我不必返回所有帖子并循环播放它们。我只是得到一个计数,并检查pid是否一次存在一个。在我获得命中之前,我很少经历超过2或3个循环,因为循环始终相对于当前帖子开始。简而言之,此过程使用相对少量的内存。

    现在我可以在我看来调用这些函数......

    查看

    @app.route('/<path:url>', methods=['GET', 'POST']) def
    display_post(url):
        post = Post.get_post(url)
        next_post = Post.next_post(post.id)
        prev_post = Post.prev_post(post.id)
        return render_template('post.html',
                               next=next_post, prev=prev_post, post=post)
    

    这是模板。

    <强>模板

    {% extends "base.html" %}
    {% block title %}{{ post.title }}{% endblock %}
    {% block content %}
    <H2>{{ post.title }}</H2>
    <b>Posted {{ post.pub_date|dts }} in <a href="{{ url_for('display_topic', url=post.topic.url) }}">{{post.topic}}</a></b>
    {{post.body|markdown}}
    {% if prev.url is defined %}
    <a href="{{ url_for('display_post', url=prev.url) }}"><<< {{prev.title}}</a>
    {% endif %}
    {% if prev.url is not defined and next.url is not defined %}{% else %} | {% endif %}
    {% if next.url is defined %}
    <a href="{{ url_for('display_post', url=next.url) }}">{{next.title}} >>></a>
    {% endif %}
    {% if current_user.is_authenticated() %}
    <p><a href="{{ url_for('edit_post', url=post.url) }}">edit</a></p>
    <p><a href="{{ url_for('delete_post', url=post.url) }}">delete</a></p>
    {% endif %}
    {% endblock %}
    

    如果存在next或prev帖子,模板仅显示链接。