现在在首页我们已经可以看到展示的问题了,我们再设计一个问题的详情页,通过点击问题的标题进去,可以给问题添加评论或者回答。


问题的详情页都使用一个名为'details.html'的模板,其网址我们设计成'/details/<question_id>/'的形式,这时候我们可以用到一开始提到过的url传参,编写对应的视图函数如下:

@app.route('/details/<question_id>/')
def details(question_id):
    question_obj = Questions.query.filter(Questions.id == question_id).first()
    return render_template('details.html', question=question_obj)

这部分代码也很简单,将url的参数question_id传递给函数,函数用question_id返回一个question模型的对象,并将其传递给模板,在模板中处理quesiton对象,包括解析其title/content/author以及对应的comments(在模型部分我们已经建立了QuestionsComments的关系和引用)。为首页问题的title添加链接:

<p class="question-title"><a href="{{ url_for('details',question_id=question.id) }}">{{ question.title }}</a></p>

details.html核心代码(其余部分继承base.html)如下:

{% block body_part %}
    <h3 class="question-title">{{ question.title }}</h3>
    <p class="question-info">
        <span>作者:{{ question.author.username }}</span>
        <span>时间:{{ question.create_time }}</span>
    </p>
    <hr>
    <p class="question-content">
        {{ question.content }}
    </p>
    <hr/>
    <div class="comments-list-container">
        <ul>
            <!-- 在模板中排序 -->
            {# {% for comment in question.comments | sort(attribute='create_time',reverse=true) %}  #}

            <!-- 模型相互关联时排序好 -->
            {% for comment in question.comments %}
                <li>
                    <div class="comments-content">
                        {{ comment.content }}
                    </div>
                    <div class="comments-info" style="text-align: right">
                        <span>{{ comment.author.username }}</span>
                        <span>{{ comment.create_time }}</span>
                    </div>
                </li>
                <hr/>
            {% endfor %}
        </ul>
    </div>
{% endblock %}

此时还没有添加评论功能,我手动往数据库写了一条评论,来查看html的效果,如下:

clipboard.png

我们再添加评论(或者说回答)的功能,其实就是加个POST表单,和注册的逻辑是一样的,为html增加下面的代码,放在问题和评论之间:

<h4>评论({{ question.comments | length }}):</h4>
<form method="POST" action="">
    <div class="form-group">
        <textarea class="form-control" rows="2" placeholder="评论详情" name="comment_desc"></textarea>
    </div>
    <div class="form-group" style="text-align: right;">
        <button type="submit" class="btn btn-primary">提交</button>
    </div>
</form>

这里用了一个length过滤器来获取comments的数量。修改detail视图函数,为其增加POST方法如下:

@app.route('/question/', methods=['GET', 'POST'])
def question():
    if request.method == 'GET':
        return render_template('question.html')
    else:
        if hasattr(g, 'user'):
            question_title = request.form.get('question_title')
            question_desc = request.form.get('question_desc')
            author_id = g.user.id
            new_question = Questions(title=question_title, content=question_desc, author_id=author_id)
            db.session.add(new_question)
            db.session.commit()
            return redirect(url_for('home'))
        else:
            flash('请先登录')
            return redirect(url_for('login'))

这部分与前面的文章中发布问答的视图函数也是很像的,无需重复讲解,经测试发布评论功能以及可以使用了。
最后美化界面如下:

clipboard.png


补充:
由于在前文中我们的Comments模型通过以下代码和Users/Questions都建立了关系:

author = db.relationship('Users', backref=db.backref('comments'))
question = db.relationship('Questions', backref=db.backref('comments', order_by=create_time.desc()))

我们在新增comment的时候,这条代码:

comment = Comments(content=content, question_id=question_id, author_id=g.user.id)

就可以改成:

comment = Comments(content=content)
comment.author = g.user
comment.question = Questions.query.filter(Questions.id == question_id).first()

虽然看上去长了,但可能更容易看出模型之间的关系了,anyway,两种方式都是OK的。


Harpsichord1207
538 声望44 粉丝

前路漫漫