摘要:我们现在开始设计发布问答的界面与功能现在点击它还是没有反应的,我们要设计一个问答界面的,然后把发布问答链接过去。
我们现在开始设计发布问答的界面与功能:
现在点击它还是没有反应的,我们要设计一个问答界面的html,然后把发布问答链接过去。
首先编写一个视图函数如下:
@app.route("/question/") def question(): return render_template("question.html")
在base.html中为发布问答添加链接:
问答页面的html首先也要继承导航条,然后主要界面设计如下:
这里还是利用css加Bootstrap样式完成的,问题描述区域是一个textarea,就不演示代码了,我个人的经验是,对于html的排版,要理解盒子模型,借助border来查看元素的边框,去看看margin和padding的宽度,排版好了之后把边框去掉。
接下来是内容的提交,为视图函数提交POST方法,并把提交的内容写入数据库,修改question视图函数,如下:
@app.route("/question/", methods=["GET", "POST"]) def question(): if request.method == "GET": return render_template("question.html") else: question_title = request.form.get("question_title") question_desc = request.form.get("question_desc") author_id = Users.query.filter(Users.username == session.get("username")).first().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"))
这里其实与用户注册的原理是一致的,此时已经能把填写的问题内容保存到数据库了。需要注意的就是,新建一个question对象时,不仅需要title和content,还需要带上question对应的author_id,因为当初创建模型时这就是个非空字段。
代码中我们直接用session中的username去Users模型中检索,来得到author_id,看着很麻烦,而且在很多视图函数中,我们都需要用到当前登录用户的信息,因此可以使用@app.before_request这个钩子函数,看其名字就很好理解,是在request之前会自动运行的,我们在每次请求之前(或者说每次运行视图函数之前),都通过钩子函数来得到当期登录用户的User对象(而不是仅仅是session中的username),然后在需要的地方使用它,代码如下:
@app.before_request def my_before_request(): username = session.get("username") if username: g.user = Users.query.filter(Users.username == username).first()
这个钩子函数,从session中获取当前登陆的username,如果获取到了,再去检索Users模型,把返回的user对象存入到g对象中,在视图函数中我们就可以直接使用这个user对象的id/register_time等字段了。此时前面的视图函数中的
author_id = Users.query.filter(Users.username == session.get("username")).first().id
可以修改成
author_id = g.user.id
此外,发布问题也需要用户先登录才可以,如果用户未登录,@app.before_request无法获取到session中的username,此时g对象就没有user这个属性,因此我们再次把question视图修改如下:
@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"))
如果提交的时候未登录,则跳转到登陆页面,并且flash"请先登录"的提示。其实也可以直接在get方法的时候就直接跳转,避免用户写完了内容,又发现未登录,页面跳转导致内容丢失。我们先把框架搭起来,以后再逐步完善细节。
再注意到我们之前写的@app.context_processor上下文管理器,也是从session中取对象的,此时我们可以直接借用钩子函数中的数据里,因此将其改写如下:
@app.context_processor def my_context_processor(): if hasattr(g, "user"): return {"login_user": g.user} return {}
我们之前说过因为g对象不能跨请求使用,因此在上下文管理器中用的是session,为什么这里又用了g对象呢?原因是现在有了钩子函数,每次请求都会执行钩子函数,向g对象中写入user,所以上下文管理器一直都能从g对象中取到user,不管这个g对象是属于哪次请求的。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/41259.html
摘要:什么是请求钩子说白了,就是在执行视图函数前后你可以进行一些处理,使用装饰器为我们提供了注册通用函数的功能。 什么是请求钩子?说白了,就是在执行视图函数前后你可以进行一些处理,Flask使用装饰器为我们提供了注册通用函数的功能。 before_first_request:在处理第一个请求前执行 before_request:在每次请求前执行 after_request:每次请求之后调用...
摘要:每天的内容跑起来模板引擎表单文件上传邮件发送一框架的简介模型负责数据的操作视图负责数据的展示控制器控制你的的操作以及视图模板的渲染在中叫做模型负责数据的操作控制你的的操作以及视图模板的渲染业务逻辑的操作模板负责数据的展示二架构三概念是 flask 每天的内容 flask跑起来 模板引擎 flask表单 文件上传邮件发送 flask-sqlalchemy 一、web框架的简介 M ...
摘要:开发实战笔记安装和使用虚拟环境虚拟环境是解释器的一个私有副本,在这个环境中你可以安装私有的包,而且不会影响系统中安装的全局的解释器。处理和函数之间关系的程序称为路由。例如在请求开始时,我们需要创建数据库连接或认证发起请求的用户。 几天前和同事一起喝酒,大家谈到为什么开始读书这件事。这里所说的读书不是专业的书籍,而是一些闲书。结果发现原来我们开始读书的原因很功利。都是因为生活中遇到了困...
阅读 3053·2021-11-18 10:02
阅读 3320·2021-11-02 14:48
阅读 3386·2019-08-30 13:52
阅读 534·2019-08-29 17:10
阅读 2075·2019-08-29 12:53
阅读 1396·2019-08-29 12:53
阅读 1021·2019-08-29 12:25
阅读 2159·2019-08-29 12:17