当前位置:   article > 正文

使用Flask搭建一个校园论坛-2_基于flask的摄影交流平台

基于flask的摄影交流平台

简介

基于Flask、Bootstrap4开发一个校园bbs论坛系列教程,该篇博客属于系列教程第二节,内容主要是对前端页面通用部分的实现。


在上一节中,我们介绍了整个项目的起因、功能设计等,这节开始,我们就是真正开始写(chao)代码了~~

1. 储备物资

在阅读这个系列教程之前,我们需要在我们的脑海中储备以下知识:

  1. Python编程语言的基本语法
  2. Flask框架的基本用法
  3. Jinja2模板引擎基本使用
  4. Python ORM框架
  5. HTML JS CSS 简单的了解

有了以上的基础知识,我们就可以很顺利的阅读这个系列的教程啦~

2. 开始耕地

很多人都称我们程序员为码农码农,那我们就开始种地吧~

2.1 服务入口

相信阅读过flask文档的朋友都知道flask包含有以下两种启动方式

  • 通过python脚本的方式运行
    1. from flask import Flask
    2. app = Flask(__name__)
    3. @app.route('/')
    4. def index():
    5. return 'Hello, flask!'
    6. if __name__ == '__main__':
    7. app.run()
  • 通过命令行的方式
    使用该方式启动flask应用的时候,我们需要先在命令行窗口中输入如下命令:
    export FLASK_APP=app

    然后通过flask run 命令来启动应用。

    注意:Windows 用户请将export替换成set

在此教程中,我们采用第二种方式来进行应用启动,因为我们项目内容相对比较多,都是CURD:),应用的不同功能都分布在不同的模块中,使用flask的Blueprint来分割每个功能模块。

在bbs目录下新建__init__.py文件,该模块为我们的应用启动入口,在里面嵌入如下代码

  1. from flask import Flask
  2. def create_app():
  3. app = Flask('bbs')
  4. @app.route('/')
  5. def index():
  6. return 'Hello, university bbs'
  7. return app

然后在控制台中输入2.1节的命令,访问 http://127.0.0.1:5000,我们就可以看到如下页面了,说明我们的flask应用已经成功启动了。

2-1

上面的代码,我们创建了一个名为create_app 的函数,在该函数中我们实例化了一个Flask对象,然后通过装饰器的方式注册了一个路由'/',最后将这个Flask对象返回。当我们使用命令启动flask应用的时候,这个函数就是我们的入口函数,这种方式我们称作为工厂模式。

2.2 开启debug

我们在开发过程中,肯定是修改代码之后就要立即调试,flask提供了debug模式,当我们开启debug的时候,我们修改完了代码,会auto reload 我们的应用,这样我们就不用每次修改了代码之后,手动去重新启动服务了,我们只需要在命令行中输入如下命令即可

export FLASK_ENV=development

2.3 通用部分

我们的网站大概长成下面这个样子

页面布局

其中,页眉和页脚在我们每个页面中都会出现,这样我们就可以将其抽取出来变为一个公共部分,又jinja2提供模板继承的功能,我们可以在其他页面中继承这些通用部分的内容。
在bbs/templates文件中我们新建一个frontend文件夹,然后新建一个名为base.html的文件,在该文件中嵌入以下内容:

bbs/templates/frontend/base.html

  1. <!DOCTYPE html>
  2. {% from "macro.html" import nav_item with context %}
  3. <!--suppress ALL -->
  4. <html lang="zh-hans">
  5. {% block head %}
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>{% block title %}{% endblock %}-二狗学院</title>
  9. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  10. <link rel="shortcut icon" href="{{url_for('static', filename='img/favorite.png')}}" type="image/x-icon">
  11. <link rel="icon" href="{{ url_for('static', filename = 'img/favorite.png') }}" type="image/x-icon">
  12. <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
  13. <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
  14. <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  15. <link rel="stylesheet" href="{{ url_for('static', filename='themes/darkly.bootstrap.min.css'}}">
  16. <script src="{{ url_for('static', filename='validator/form-validation.js') }}"></script>
  17. <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
  18. </head>
  19. {% endblock %}
  20. {% block nav %}
  21. <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  22. <div class="container align-self-end">
  23. <a class="navbar-brand" href="/"><i class="fa fa-bbs"></i>狗子学院</a>
  24. <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navHome" aria-controls="navHome" aria-expanded="false" aria-label="Toggle navigation">
  25. <span class="navbar-toggler-icon"></span>
  26. </button>
  27. <div class="collapse navbar-collapse" id="navHome">
  28. <ul class="navbar-nav mr-auto">
  29. <li class="nav-item dropdown mr-5">
  30. <a class="nav-link dropdown-toggle" href="#" id="talk" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-fire mr-1"></i>大食堂</a>
  31. <div class="dropdown-menu" aria-labelledby="talk">
  32. <a class="dropdown-item" href="#">杂谈</a>
  33. <a class="dropdown-item" href="#">趣事</a>
  34. <a class="dropdown-item" href="#">表白</a>
  35. </div>
  36. </li>
  37. <li class="nav-item dropdown mr-5">
  38. <a class="nav-link dropdown-toggle" href="#" id="talk" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-shopping-cart mr-1"></i>便利店</a>
  39. <div class="dropdown-menu" aria-labelledby="talk">
  40. <a class="dropdown-item" href="#">寻物</a>
  41. <a class="dropdown-item" href="#">咸鱼</a>
  42. <a class="dropdown-item" href="#">活动</a>
  43. </div>
  44. </li>
  45. <li class="nav-item dropdown mr-5">
  46. <a class="nav-link dropdown-toggle" href="#" id="talk" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-delicious mr-1"></i>组织</a>
  47. <div class="dropdown-menu" aria-labelledby="talk">
  48. <a class="dropdown-item" href="#">学院</a>
  49. <a class="dropdown-item" href="#">社团</a>
  50. <a class="dropdown-item" href="#">圈子</a>
  51. </div>
  52. </li>
  53. </ul>
  54. <form class="form-inline my-2 my-md-0">
  55. <input class="form-control" type="text" placeholder="请输入关键字" aria-label="Search" required>
  56. </form>
  57. </div>
  58. </div>
  59. </nav>
  60. {% endblock %}
  61. {% block content %}
  62. {% endblock %}
  63. {% block footer %}
  64. <footer class="container-fluid mt-4 py-0 bg-dark">
  65. <div class="card-body text-center px-0 f-14">
  66. <p class="card-text mb-1">Copyright&nbsp;©&nbsp;<span>2020</span>
  67. <a href="http://2dogz.cn/" target="_blank" title="官网">University BBS</a>&nbsp;Design&nbsp;by&nbsp;Flask1.01.
  68. </p>
  69. </div>
  70. </footer>
  71. {% endblock %}
  72. {% block script %}
  73. <script>
  74. $(function () {
  75. $('[data-toggle="tooltip"]').tooltip()
  76. })
  77. </script>
  78. {% endblock %}
  79. </html>

代码释义:

我们在base.html 文件中写了几个block块定义,分别是head、nav、title、content、footer以及script。分别用来定义我们的html文件的引用、导航栏、标题、内容、页脚以及js代码块。通过{% block name %},当我们的子模板继承自base.html模板的时候,我们子模板可以重写这个block的定义,当然也可以使用{{ super() }}函数来继承父模板的定义,然后自己定义新的内容。

  • 在head中引用了项目需要引入的框架,比如jQuery、bootstrap4等;
  • 在nav中我们使用bootstrap的导航栏组件轻松完成了顶部导航栏的构建

2.4 主页

我们写完了页面的通用部分之后,就可以在主页中继承该模板了。在bbs/templates/frontend/文件夹中新建index.html文件,并嵌入下面的代码

bbs/templates/frontend/index.html

  1. {% extends "frontend/base.html" %}
  2. {% from "macro.html" import post_item, render_pagination with context%}
  3. {% block title %}
  4. 主页
  5. {% endblock %}
  6. {% block content %}
  7. <main>
  8. <div class="container mt-2">
  9. </div>
  10. </main>
  11. {% endblock %}

我使用extends关键字继承了基模板base.html,然后在content块中写了我们自己需要定义的内容。

在完成了我们主页模板代码之后,我们就需要通过路由将它渲染出来,并显示在用户的网页中。

在bbs目录下新建一个blueprint包,并新增模块index.py, 在其中嵌入如下代码

bbs/blueprint/index.py

  1. from flask import Blueprint, render_template
  2. index_bp = Blueprint('index_bp', __name__)
  3. @index_bp.route('/')
  4. @index_bp.route('/index/')
  5. def index():
  6. return render_template('frontend/index.html')

首先我们实例化了一个Blueprint对象,然后通过该对象注册了两个路由'/' 、'/index/',并将这两个路由指向视图函数index,在index函数中,我们将我们之前创建的主页文件渲染,然后返回给客户端。

我们在这里注册一个同样的路由,因此我们需要删除__init__.py模块中的index视图函数,同时我们在新建blueprint之后,需要将该蓝图进行注册,__init__.py最新代码如下

  1. from flask import Flask
  2. from bbs.blueprint.index import index_bp
  3. def create_app():
  4. app = Flask('bbs')
  5. register_bp(app)
  6. return app
  7. def register_bp(app: Flask):
  8. app.register_blueprint(index_bp)

此时,我们访问http://127.0.0.1:5000看到的将是如下页面

主页

2.5 错误处理

我们在访问网页的时候,经常会出现404,、500这种错误代码。如果我们使用flask提供的默认错误页面,是下面这种样子,如果用户不小心访问到了,将会一头雾水,不知所措,因此我们需要将特定错误页面进行处理,在用户进入错误页面之后,能对其有效的指引。

404

flask提供了errorhandle装饰器,能让我们很轻松的处理请求错误。在__init__.py模块中添加新的代码

bbs/__init__.py

  1. def create_app(config_name=None):.
  2. ...
  3. register_error_handlers(app)
  4. def register_error_handlers(app: Flask):
  5. @app.errorhandler(400)
  6. def bad_request(e):
  7. return render_template('error/400.html'), 400
  8. @app.errorhandler(403)
  9. def forbidden(e):
  10. return render_template('error/403.html'), 403
  11. @app.errorhandler(404)
  12. def not_found(e):
  13. return render_template('error/404.html'), 404
  14. @app.errorhandler(500)
  15. def server_error(e):
  16. return render_template('error/500.html'), 500

在register_error_handlers函数中,我们分别将对应的错误渲染了对应的错误模板了,因此当用户访问出错的时,页面显示的就是我们自己自定义的错误页面样式了。

在bbs/templates/error/目录中新建对应的模板文件,由于内容一致,这里只展示404页面的代码

bss/templates/error/404.html

  1. {% extends "frontend/base.html" %}
  2. {% block title %}
  3. 页面未找到
  4. {% endblock %}
  5. {% block content %}
  6. <main>
  7. <div class="container mt-2">
  8. <div class="card-body">
  9. <div class="card text-white bg-dark mb-3">
  10. <div class="card-body">
  11. <img src="{{ url_for('static', filename='img/404.png') }}" class="img-fluid d-block mx-auto">
  12. </div>
  13. <div class="card-footer text-right">
  14. <a class="btn btn-outline-danger" href="/">返回主页</a>
  15. </div>
  16. </div>
  17. </div>
  18. </div>
  19. </main>
  20. {% endblock %}

代码跟index.html类似,聪明的你应该看得懂,就不做多余的解释了。
然后我们输入一个未定义的路由,404页面就是下面你这个样子啦~~~

404-2

至此,本节的内容就已经全部做完啦~是不是很简单啊~

教程中的资源文件可以进入我的github仓库下载源代码使用 仓库连接

下一节,我们将开始进行用户注册登录功能的实现啦,尽请期待啦~~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/945795
推荐阅读
相关标签
  

闽ICP备14008679号