Flask 项目中使用 bootstrap

flask 的插件中有一个 flask-bootstrap 项目, 但是用起来不怎么方便, 如果大家感兴趣的话, 还是直接在项目中引入 bootstrap.

flask 项目的目录结构

项目名称/
    app/
        static/ # 静态文件夹
            css/ # 项目中引入的 css 样式表
            js/ # 项目中引入的 js
            fonts/ # 项目中需要的字体,一般是 bootstrap 所依赖的字体
            images/ # 项目中的图片文件夹
        templates/ # html 模板文件夹
            common/ # 通用打模板文件
            ...
        views.py
        __init__.py
    env/ # python 虚拟环境
    run.py # 启动文件

引入 bootstrap

下载 bootstrap

将 bootstrap 的 dist 文件夹下的 css,js,fonts 三个文件夹拷贝到项目的 static 文件夹下.在以后的学习过程中,你会发现,其实不需要完全拷贝的,你可以精简一些无用的文件
当然,由于 bootstrap 是基于 jquery 的,所以从网上下载 jquery.js 并拷贝至 js 文件夹下.具体下载的步骤,不再赘述.

制作基础模板

在 templates/common 文件夹下建立一个 base.html 文件.内容如下:

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
        <meta name="description" content="藕丝空间">
        <meta name="author" content="东方鹗">
        <link rel="icon" href="{{ url_for('static', filename='images/favicon.ico') }}"><!--引入项目的图标,将需要的 ico 文件放到 static/images 文件夹下.-->

        <title>{% block title %}我的第一个前端页面{% endblock %}</title>
        <!--设置网页的标题,通过这样的设置,你可以利用 jinja2 的一些特性,将每个网页的标题进行不通的设置.-->

        {% block css %} <!--css模块区域-->
        <!-- Bootstrap core CSS -->
        <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
        <!-- 可选的Bootstrap主题文件(一般不用引入) -->
        <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-theme.min.css') }}">
        <!-- Custom styles for this template -->
        <link href="{{ url_for('static', filename='css/offcanvas.css') }}" rel="stylesheet">
        {% endblock %}
    </head>

    <body>
        {% include "common/header.html" %}<!--引入网页的头部模板-->
        <div class="container">
            <div class="row row-offcanvas row-offcanvas-right">
                {% block content %}<!--自定义模板区域-->

                {% endblock %}
                {% include "common/sidebar.html" %}<!--引入网页的侧边模板-->
            </div><!--/row-->
            {% include "common/footer.html" %}<!--引入网页的底部模板-->
        </div>

        {% block js %}<!--js模块区域-->
        <!-- Bootstrap core JavaScript
        ================================================== -->
        <!-- Placed at the end of the document so the pages load faster -->
        <script src="{{ url_for('static', filename='js/jquery.js') }}"></script>
        <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
        <script src="{{ url_for('static', filename='js/offcanvas.js') }}"></script>
        {% endblock %}
    </body>
</html>

此模板是基于 bootstrap 的项目实例- offcanvas 制作的,你可以在 bootstrap 的源码中找到该实例.

具体的解释请看代码的注释部分.此时,你的基础模板上是有错误存在的.因为还没有制作头部,底部和侧边模板.

制作头部模板

头部模板被放置在 templates/common 文件夹下,命名为 header.html.

<nav class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Home</a></li>
                <li><a href="#about">About</a></li>
                <li class="dropdown">
                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                  <ul class="dropdown-menu">
                    <li><a href="#">Action</a></li>
                    <li><a href="#">Another action</a></li>
                    <li><a href="#">Something else here</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="#">Separated link</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="#">One more separated link</a></li>
                  </ul>
                </li>
            </ul>
        </div><!-- /.nav-collapse -->
    </div><!-- /.container -->
</nav><!-- /.navbar -->

制作底部模板

底部模板被放置在 templates/common 文件夹下,命名为 footer.html.

<hr>

<footer>
    <p>&copy; 2016 Company, Inc.</p>
</footer>

制作侧边模板

侧边模板被放置在 templates/common 文件夹下,命名为 sidebar.html.

<div class="col-xs-6 col-sm-3 sidebar-offcanvas" id="sidebar">
    <div class="list-group">
        <a href="#" class="list-group-item active">
            <button type="button" class="btn btn-block btn-danger" aria-label="Left Align">
                <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
            </button>
        </a>
        <a href="#" class="list-group-item">
            <button type="button" class="btn btn-block btn-info" aria-label="Left Align">
                <span class="glyphicon glyphicon-align-center" aria-hidden="true"></span>
            </button>
        </a>
        <a href="#" class="list-group-item">
            <button type="button" class="btn btn-primary" aria-label="Left Align">
                <span class="glyphicon glyphicon-align-right" aria-hidden="true"></span>
            </button>
        </a>
        <a href="#" class="list-group-item">
            <button type="button" class="btn btn-success" aria-label="Left Align">
                <span class="glyphicon glyphicon-align-justify" aria-hidden="true"></span>
            </button>
        </a>
        <a href="#" class="list-group-item">
            <button type="button" class="btn btn-block btn-warning" aria-label="Left Align">
                <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
            </button>
        </a>
        <a href="#" class="list-group-item">Link</a>
        <a href="#" class="list-group-item">Link</a>
        <a href="#" class="list-group-item">Link</a>
        <a href="#" class="list-group-item">Link</a>
        <a href="#" class="list-group-item">Link</a>
    </div>
</div><!--/.sidebar-offcanvas-->

制作项目的主页

现在需要在项目的主页中引入基础模板,然后自定义自己的部分模板即可.index.html 在 templats 文件夹下,和头部,底部和侧边模板不在一个目录下,而在上级目录里.

{% extends "common/base.html" %}<!--继承基础模板-->
{% block content %}<!--自定义模板区域-->
<div class="col-xs-12 col-sm-9">
  <p class="pull-right visible-xs">
    <button type="button" class="btn btn-primary btn-xs" data-toggle="offcanvas">Toggle nav</button>
  </p>
  <div class="jumbotron">
    <h1>Hello, world!</h1>
    <p>This is an example to show the potential of an offcanvas layout pattern in Bootstrap. Try some responsive-range viewport sizes to see it in action.</p>
  </div>
  <div class="row">
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
    <div class="col-xs-6 col-lg-4">
      <h2>Heading</h2>
      <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
      <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
    </div><!--/.col-xs-6.col-lg-4-->
  </div><!--/row-->
</div><!--/.col-xs-12.col-sm-9-->
{% endblock %}

到此,模板部分已经设置完毕.为了能够看到和测试我们的劳动成果,我们需要把 flask 项目写完整.

完善项目并展示

__init__.py 代码

from flask import Flask

app = Flask(__name__)

from app import views

views.py 代码


from app import app
from flask import render_template


@app.route('/', methods=['GET', 'POST'])
def index():

    return render_template('index.html')

run.py


from app import app

app.run(debug=True)

至此,项目已经能够展示了.

展示

全屏展示
手机展示

点击导航展示

进阶

在模板中使用 jinja2 自定义的过滤器

首先自定义一个函数

def jfloat(s):
    return float(s)

本函数是为了在模板中将字符串,整型等其它类型转换为浮点型.

为了能够在 jinja2 模板中使用该函数.需要在项目的根 __init__.py 文件里的工厂函数 create_app() 中写入如下代码:

...

def create_app(config_name):
    ...
    app.jinja_env.filters['jfloat'] = jfloat

这样,你就可以在模板中使用该过滤器啦.

参考

http://docs.jinkan.org/docs/jinja2/api.html#writing-filters
http://www.tuicool.com/articles/7v6Ffiq

不同的蓝图中使用模板注意事项

http://www.os373.cn/article/58

查看原文

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容