问答模块的实现
后端
提问
定义数据库
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")
逻辑部分
from flask import Blueprint, request, render_template, g, redirect, url_for
from .froms import QuestionForm
from models import QuestionModel
from exts import db
from decorators import login_requested
bp = Blueprint("qa", __name__, url_prefix="/")
@bp.route("/")
def index():
# 将问答中的所有文件查询出来
questions = QuestionModel.query.order_by(QuestionModel.create_time.desc()).all()
return render_template('index.html', questions=questions)
@bp.route("/qa/public", methods=['GET', "POST"])
@login_requested
def public_question():
# 判断如果没有登录的话跳转至登录页面
# if not g.user:
# return redirect('/auth/login')
# 下面使用装饰器来实现
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()
# 之后跳转到这篇问答的详情页面,现在先跳转到首页
# return 'hello world!'
return redirect('/')
else:
print(form.errors)
return redirect(url_for("qa.public_question"))
回答部分
定义数据库
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"))
# 关系
# backref 反向应用
question = db.relationship(QuestionModel, backref=db.backref("answers", order_by=create_time.desc()))
author = db.relationship(QuestionModel, backref="answers")
逻辑实现
@bp.route("/qa/detail/<qa_id>")
def qa_detail(qa_id):
question =QuestionModel.query.get(qa_id)
# 把查询到的内容返回到模板中
return render_template("detail.html", question=question)
# @bp.route("/answer/public", methods=['POST'])
@bp.post("/answer/public")
@login_requested
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")))
# 搜索功能
@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)
前端
public_question.html
{% extends "base.html" %}
{% block title %}
菜鸡学安全-发布问答
{% endblock %}
{% block head %}{% endblock %}
{% block body %}
<div class="row" style="margin-top: 20px;">
<div class="col"></div>
<div class="col-10">
<h1 style="text-align: center;">发布问答</h1>
<form action="#" method="post">
<div class="form-group">
<input type="text" name="title" class="form-control" placeholder="请输入标题">
</div>
<div class="form-group">
<textarea name="content" class="form-control" rows="10" placeholder="请输入内容"></textarea>
</div>
<div class="form-group" style="text-align: right;">
<button class="btn btn-primary">发布</button>
</div>
</form>
</div>
<div class="col"></div>
</div>
{% endblock %}
detail.html
{% extends "base.html" %}
{% block title %}{{ question.title }}{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/detail.css') }}">
{% endblock %}
{% block body %}
<div class="row" style="margin-top: 20px;">
<div class="col"></div>
<div class="col-10" style="background-color: #fff;padding: 20px;">
<h3 class="page-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>
<h4 class="comment-group-title">评论({{ question.answers|length }}):</h4>
<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>
<ul class="comment-group">
{% for answer in question.answers %}
<li>
<div class="user-info">
<img class="avatar" src="{{ url_for('static', filename='images/avatar.jpg') }}" alt="">
<span class="username">{{ answer.author.username }}</span>
<span class="create-time">{{ answer.create_time }}</span>
</div>
<p class="comment-content">{{ answer.content }}</p>
</li>
{% endfor %}
</ul>
</div>
<div class="col"></div>
</div>
{% endblock %}
实现图
参考文章
https://www.bilibili.com/video/BV17r4y1y7jJ/
https://github.com/MATINYAO/flask_demo_zhihu