Flask实战开发——问答平台(六)发布问答

一、创建问题模型

models.py

class QuestionModel(db.Model):
    __tablename__ = "question"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)

    # 外键
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    author = db.relationship(UserModel, backref="questions")

迁移更新数据库 

flask db migrate

flask db upgrade

详情见:Flask(Mysql)——ORM模型外键与表的关系及用flask_migrate迁移ORM模型-CSDN博客

二、路由请求

qa.py

from flask import Blueprint, request, render_template, g, redirect, url_for
from .forms import QuestionForm
from models import QuestionModel
from exts import db
@bp.route("/qa/public", methods=['GET', 'POST'])
@login_required
def public_question():
    if request.method == 'GET':
        return render_template("public_question.html")
    else:
        form = QuestionForm(request.form)
        if form.validate():
            title = form.title.data
            content = form.content.data
            question = QuestionModel(title=title, content=content, author=g.user)
            db.session.add(question)
            db.session.commit()
            # todo: 跳转到这篇问答的详情页
            return redirect("/")
        else:
            print(form.errors)
            return redirect(url_for("qa.public_question"))

三、问题表单验证

froms.py

class QuestionForm(wtforms.Form):
    title = wtforms.StringField(validators=[Length(min=3, max=100, message="标题格式错误!")])
    content = wtforms.StringField(validators=[Length(min=3,message="内容格式错误!")])

四、登录装饰器

防止用户没有登录也能发布问答

新建decorators.py文件

from functools import wraps
from flask import g, redirect, url_for

def login_required(func):
    # 保留func的信息
    @wraps(func)
    # func(a,b,c)
    # func(1,2,c=3)
    def inner(*args, **kwargs):
        if g.user:
            return func(*args, **kwargs)
        else:
            return redirect(url_for("auth.login"))
    return inner

检查全局变量g中的user属性是否存在。如果存在,说明用户已经登录,可以访问被修饰的视图函数;如果不存在,说明用户未登录,将被重定向到登录页面。

五、问答列表详情

新建问题详情跳转路由

qa.py

@bp.route("/qa/detail/<qa_id>")

def qa_detail(qa_id):

        question = QuestionModel.query.get(qa_id)

        return render_template("detail.html", question=question)

index.html

<div class="question-title"><a href="{
   
   { url_for('qa.qa_detail', qa_id=question.id) }}">{
   
   { question.title }}</a></div>

六、创建答案模型

models.py

class AnswerModel(db.Model):
    __tablename__ = "answer"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)

    # 外键
    question_id = db.Column(db.Integer, db.ForeignKey("question.id"))
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

    # 关系
    question = db.relationship(QuestionModel, backref=db.backref("answers", order_by=create_time.desc()))
    author = db.relationship(UserModel, backref="answers")

迁移更新数据库 

flask db migrate

flask db upgrade

七、答案表单验证

forms.py

from wtforms.validators import Email, Length, EqualTo, InputRequired
class AnswerForm(wtforms.Form):
    content = wtforms.StringField(validators=[Length(min=3, message="内容格式错误!")])
    question_id = wtforms.IntegerField(validators=[InputRequired(message="必须要传入问题id!")])

qa.py

from .forms import QuestionForm, AnswerForm
from models import QuestionModel, AnswerModel
# @bp.route("/answer/public", methods=['POST'])
@bp.post("/answer/public")
@login_required
def public_answer():
    form = AnswerForm(request.form)
    if form.validate():
        content = form.content.data
        question_id = form.question_id.data
        answer = AnswerModel(content=content, question_id=question_id, author_id=g.user.id)
        db.session.add(answer)
        db.session.commit()
        return redirect(url_for("qa.qa_detail", qa_id=question_id))
    else:
        print(form.errors)
        return redirect(url_for("qa.qa_detail", qa_id=request.form.get("question_id")))

detail.html 前端详情页面表单

<form action="{
   
   { url_for('qa.public_answer') }}" method="post">
  <div class="form-group">
    <input type="text" placeholder="请填写评论" name="content" class="form-control">
    <input type="hidden" name="question_id" value="{
   
   { question.id }}">
  </div>
  <div class="form-group" style="text-align: right;">
    <button class="btn btn-primary">评论</button>
  </div>
</form>

八、搜索功能实现

1、qa.py 创建搜索路由

@bp.route("/search")
def search():
    # /search?q=flask
    # /search/<q>
    # post, request.form
    q = request.args.get("q")
    questions = QuestionModel.query.filter(QuestionModel.title.contains(q)).all()
    return render_template("index.html", questions=questions)

2、base.html

<li class="nav-item ml-2">
    <form class="form-inline my-2 my-lg-0" method="GET" action="{
   
   { url_for('qa.search') }}">
        <input class="form-control mr-sm-2" type="search" placeholder="关键字" aria-label="Search" name="q">
        <button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
    </form>
</li>

项目完结........


上一篇章Flask实战开发——问答平台(五)用户注册与登录-CSDN博客

猜你喜欢

转载自blog.csdn.net/weixin_57467129/article/details/140514016