【问题标题】:Routing Individual Post with Pagination - Flask使用分页路由单个帖子 - Flask
【发布时间】:2014-06-08 22:21:16
【问题描述】:

目标:路由到单个文章/博客文章并包含分页(使用 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 处理分页的方式一样。

【问题讨论】:

    标签: python pagination flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

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

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

    其次,你在一个帖子里,想要前进和后退。

    听起来你想做第二种。

    我所做的是在我的 POST 模型中编写两个静态方法来计算上一篇和下一篇文章...然后我通过我的视图函数将值传递给模板。

    POST 模型静态方法

    型号

    @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 值,这样如果没有找到任何先前的内容,模板逻辑就可以工作。此外,如果没有分配 None 并且您尝试传递视图,则会出现错误。
    3. 在 prev_post 的情况下,在每个循环中,从 pid 中减去 1 并检查 db 中是否存在条目。
    4. 循环遍历,每次减 1。
    5. 第一次找到匹配项时,中断循环并将 prev_post none 值替换为 post.id。

    当然,下一个函数完全一样,只是你 +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 %}
    

    模板仅在存在下一篇或上一篇文章时显示链接。

    【讨论】:

    • 我喜欢这个策略;但是我正在对其进行一些更改/升级,使其更像flask-sqlalchemy中的分页功能!很快就会发布!
    • 酷。请查看 **if db.session.query(Post).get(pid) is not None: ** 行。他们可能会得到改进。同时,如果您认为问题得到了适当的回答,请关闭该问题。您可以稍后更新您的回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2021-04-26
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    相关资源
    最近更新 更多