《Tango with Django》-第12章 集成 Bootstrap

12.0 Bootstrap前言

本章使用 Twitter Bootstrap 装饰 Rango 应用。Bootstrap 是最为流行的 HTML、CSS 和 JavaScript框架,支持响应式设计,简单易用。现在打开 Bootstrap 的网站,可以看到网站给出了很多示例代码,说明了各组件的用法。此外,Bootstrap 的网站中还有一些布局示例,我们可以参照这些示例设计 Rango 应用。
在众多布局中,笔者觉得这个管理后台比较适合 Rango,有导航栏、侧边栏(用于显示分类列表)和主内容区。打开这个管理后台布局,保存 HTML 源码,存储在 templates/rango 目录里,命名为 base_bootstrap.html。

  • 页面如下:https://v4-alpha.getbootstrap.com/examples/dashboard/
    在这里插入图片描述
  • 页面源码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">

    <title>Dashboard Template for Bootstrap</title>
    <link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">

    <!-- Bootstrap core CSS -->
    <link href="../../dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="dashboard.css" rel="stylesheet">
  </head>

  <body>
    <nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
      <button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <a class="navbar-brand" href="#">Dashboard</a>

      <div class="collapse navbar-collapse" id="navbarsExampleDefault">
        <ul class="navbar-nav mr-auto">
          <li class="nav-item active">
            <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Settings</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Profile</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Help</a>
          </li>
        </ul>
        <form class="form-inline mt-2 mt-md-0">
          <input class="form-control mr-sm-2" type="text" placeholder="Search">
          <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
        </form>
      </div>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <nav class="col-sm-3 col-md-2 hidden-xs-down bg-faded sidebar">
          <ul class="nav nav-pills flex-column">
            <li class="nav-item">
              <a class="nav-link active" href="#">Overview <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Reports</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Analytics</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Export</a>
            </li>
          </ul>

          <ul class="nav nav-pills flex-column">
            <li class="nav-item">
              <a class="nav-link" href="#">Nav item</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Nav item again</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">One more nav</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Another nav item</a>
            </li>
          </ul>

          <ul class="nav nav-pills flex-column">
            <li class="nav-item">
              <a class="nav-link" href="#">Nav item again</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">One more nav</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Another nav item</a>
            </li>
          </ul>
        </nav>

        <main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
          <h1>Dashboard</h1>

          <section class="row text-center placeholders">
            <div class="col-6 col-sm-3 placeholder">
              <img src="data:image/gif;base64,R0lGODlhAQABAIABAAJ12AAAACwAAAAAAQABAAACAkQBADs=" width="200" height="200" class="img-fluid rounded-circle" alt="Generic placeholder thumbnail">
              <h4>Label</h4>
              <div class="text-muted">Something else</div>
            </div>
            <div class="col-6 col-sm-3 placeholder">
              <img src="data:image/gif;base64,R0lGODlhAQABAIABAADcgwAAACwAAAAAAQABAAACAkQBADs=" width="200" height="200" class="img-fluid rounded-circle" alt="Generic placeholder thumbnail">
              <h4>Label</h4>
              <span class="text-muted">Something else</span>
            </div>
            <div class="col-6 col-sm-3 placeholder">
              <img src="data:image/gif;base64,R0lGODlhAQABAIABAAJ12AAAACwAAAAAAQABAAACAkQBADs=" width="200" height="200" class="img-fluid rounded-circle" alt="Generic placeholder thumbnail">
              <h4>Label</h4>
              <span class="text-muted">Something else</span>
            </div>
            <div class="col-6 col-sm-3 placeholder">
              <img src="data:image/gif;base64,R0lGODlhAQABAIABAADcgwAAACwAAAAAAQABAAACAkQBADs=" width="200" height="200" class="img-fluid rounded-circle" alt="Generic placeholder thumbnail">
              <h4>Label</h4>
              <span class="text-muted">Something else</span>
            </div>
          </section>

          <h2>Section title</h2>
          <div class="table-responsive">
            <table class="table table-striped">
              <thead>
                <tr>
                  <th>#</th>
                  <th>Header</th>
                  <th>Header</th>
                  <th>Header</th>
                  <th>Header</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>1,001</td>
                  <td>Lorem</td>
                  <td>ipsum</td>
                  <td>dolor</td>
                  <td>sit</td>
                </tr>
                <tr>
                  <td>1,002</td>
                  <td>amet</td>
                  <td>consectetur</td>
                  <td>adipiscing</td>
                  <td>elit</td>
                </tr>
                <tr>
                  <td>1,003</td>
                  <td>Integer</td>
                  <td>nec</td>
                  <td>odio</td>
                  <td>Praesent</td>
                </tr>
                <tr>
                  <td>1,003</td>
                  <td>libero</td>
                  <td>Sed</td>
                  <td>cursus</td>
                  <td>ante</td>
                </tr>
                <tr>
                  <td>1,004</td>
                  <td>dapibus</td>
                  <td>diam</td>
                  <td>Sed</td>
                  <td>nisi</td>
                </tr>
                <tr>
                  <td>1,005</td>
                  <td>Nulla</td>
                  <td>quis</td>
                  <td>sem</td>
                  <td>at</td>
                </tr>
                <tr>
                  <td>1,006</td>
                  <td>nibh</td>
                  <td>elementum</td>
                  <td>imperdiet</td>
                  <td>Duis</td>
                </tr>
                <tr>
                  <td>1,007</td>
                  <td>sagittis</td>
                  <td>ipsum</td>
                  <td>Praesent</td>
                  <td>mauris</td>
                </tr>
                <tr>
                  <td>1,008</td>
                  <td>Fusce</td>
                  <td>nec</td>
                  <td>tellus</td>
                  <td>sed</td>
                </tr>
                <tr>
                  <td>1,009</td>
                  <td>augue</td>
                  <td>semper</td>
                  <td>porta</td>
                  <td>Mauris</td>
                </tr>
                <tr>
                  <td>1,010</td>
                  <td>massa</td>
                  <td>Vestibulum</td>
                  <td>lacinia</td>
                  <td>arcu</td>
                </tr>
                <tr>
                  <td>1,011</td>
                  <td>eget</td>
                  <td>nulla</td>
                  <td>Class</td>
                  <td>aptent</td>
                </tr>
                <tr>
                  <td>1,012</td>
                  <td>taciti</td>
                  <td>sociosqu</td>
                  <td>ad</td>
                  <td>litora</td>
                </tr>
                <tr>
                  <td>1,013</td>
                  <td>torquent</td>
                  <td>per</td>
                  <td>conubia</td>
                  <td>nostra</td>
                </tr>
                <tr>
                  <td>1,014</td>
                  <td>per</td>
                  <td>inceptos</td>
                  <td>himenaeos</td>
                  <td>Curabitur</td>
                </tr>
                <tr>
                  <td>1,015</td>
                  <td>sodales</td>
                  <td>ligula</td>
                  <td>in</td>
                  <td>libero</td>
                </tr>
              </tbody>
            </table>
          </div>
        </main>
      </div>
    </div>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
    <script src="../../dist/js/bootstrap.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>

为了在 Rango 应用中使用,还要做些修改:
❏ 把所有 …/…/ 路径替换为 http://v4-alpha.getbootstrap.com/。
❏ 把 dashboard.css 的路径替换为绝对地址:http://v4-alpha.getbootstrap.com/examples/dashboard/dashboard.css。
❏ 把导航栏中的搜索框删除。
❏ 把页面中不相关的内容都删掉,替换为 {% block body_block %}{% endblock %}。
❏ 把页面的标题元素改为 < title> Rango - {% block title %}How to Tango with Django!{%endblock %} 。
❏ 把网站名称(“Dashboard”)改为“Rango”。 ❏ 在导航栏中添加首页、登录和注册等页面的链接。
❏ 添加侧边栏区块:{% block sidebar_block %}{% endblock %}。
❏ 在 DOCTYPE 下面添加 {% load staticfiles %}。

12.1 模板

  • base_bootstrap.html 和 base.html
<!DOCTYPE html>
<html lang="en">
{
    
    % load static %}

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- 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="{% static 'images/favicon.ico' %}">

      <title>Rango - {
    
    % block title %}How to Tango with Django!{
    
    % endblock %}</title>
      <!-- Bootstrap core CSS -->
    <link href="http://v4-alpha.getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="http://v4-alpha.getbootstrap.com/examples/dashboard/dashboard.css" rel="stylesheet">

  </head>

  <body>

    <nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
      <button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <a class="navbar-brand" href="{% url 'index' %}">Rango</a>

      <div class="collapse navbar-collapse" id="navbar">
        <ul class="navbar-nav mr-auto">
          <li class="nav-item active">
            <a class="nav-link" href="{% url 'index' %}">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'about' %}">About</a>
          </li>
        {
    
    % if user.is_authenticated %}
            <li class="nav-item">
              <a class="nav-link" href="{% url 'add_category' %}">Add a New Category</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'profile' user.username %}">Profile</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'list_profiles' %}">List Profiles</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'auth_logout' %}?next=/rango/">Logout</a>
            </li>
        {
    
    % else %}
            <li class="nav-item">
              <a class="nav-link" href="{% url 'register' %}">Register Here</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'login' %}">Login</a>
            </li>
        {
    
    % endif %}
        </ul>
      </div>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
          {
    
    % block sidebar_block %}
          {
    
    % endblock %}
        </div>
        <div class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 main">
         {
    
    % block body_block %}{
    
    % endblock %}


        </div>
      </div>
    </div>

     <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js" integrity="sha384-THPy051/pYDQGanwU6poAc/hOdQxjnOEXzbT+OuUAFqNqFjL+4IGLBgCJC3ZOShY" crossorigin="anonymous"></script>
 <!--
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
 -->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js" integrity="sha384-Plbmg8JY28KFelvJVai01l8WyZzrYWG825m+cZ0eDDS1f7d/js6ikvy1+X+guPIB" crossorigin="anonymous"></script>
    <script src="http://v4-alpha.getbootstrap.com/dist/js/bootstrap.min.js"></script>
    <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
    <!--
    <script src="http://v4-alpha.getbootstrap.com/assets/js/vendor/holder.min.js"></script>
    -->

    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="http://v4-alpha.getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>

创建好这个模板之后,下载 favicon,保存到 static/images/ 目录中。
仔细看一下上述 HTML 源码,你会发现里面有好多使用 < div> 标签创建的结构。整个页面基本上分为两部分:< nav> 标签里的顶部导航栏和 < div class=“container-fluid”> 标签里的主内容区。主内容区里还有两个 < div> 标签,分别放置 sidebar_block 和 body_block 区块。注意,这个 HTML 模板从外部网站引用 CSS 和 JavaScript 文件。因此,为了正确加载那些文件,需要联网。

12.2 调整模板

接下来还要做些调整,把 base.html 模板中的代码替换为 base_bootstrap.html 中的代码。为此,可以先把 base.html 中现有的代码注释掉,然后复制粘贴 base_bootstrap.html 中的代码。
然后刷新网页,你会发现页面变得精美多了。以关于页面为例,修改前后的对比如图 12-1 和图12-2 所示。
浏览一下其他页面,因为都继承自基模板,所以看起来应该都不错,但也有不足之处。接下来我们逐一修改各页面的模板,使用 Bootstrap 提供的 CSS 类改进外观。

  • 图 12-1
    在这里插入图片描述
  • 图12-2
    在这里插入图片描述
  • 我的图长这样
    在这里插入图片描述

首页

首页中最受欢迎的分类和网页最好分两栏显示。浏览 Bootstrap 的示例后我们发现,Narrow Jumbotron 中的两栏就符合我们的要求。查看网页源码,找到实现分栏的 HTML 代码:

  • Narrow Jumbotron网页源码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">

    <title>Narrow Jumbotron Template for Bootstrap</title>
    <link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/">

    <!-- Bootstrap core CSS -->
    <link href="../../dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="narrow-jumbotron.css" rel="stylesheet">
  </head>

  <body>

    <div class="container">
      <div class="header clearfix">
        <nav>
          <ul class="nav nav-pills float-right">
            <li class="nav-item">
              <a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">About</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Contact</a>
            </li>
          </ul>
        </nav>
        <h3 class="text-muted">Project name</h3>
      </div>

      <div class="jumbotron">
        <h1 class="display-3">Jumbotron heading</h1>
        <p class="lead">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
        <p><a class="btn btn-lg btn-success" href="#" role="button">Sign up today</a></p>
      </div>

      <div class="row marketing">
        <div class="col-lg-6">
          <h4>Subheading</h4>
          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>

          <h4>Subheading</h4>
          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>

          <h4>Subheading</h4>
          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
        </div>

        <div class="col-lg-6">
          <h4>Subheading</h4>
          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>

          <h4>Subheading</h4>
          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>

          <h4>Subheading</h4>
          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
        </div>
      </div>

      <footer class="footer">
        <p>&copy; Company 2017</p>
      </footer>

    </div> <!-- /container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>
  • Narrow Jumbotron 中的两栏的网页源码
      <div class="row marketing">
        <div class="col-lg-6">
          <h4>Subheading</h4>
          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>

          <h4>Subheading</h4>
          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>

          <h4>Subheading</h4>
          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
        </div>

        <div class="col-lg-6">
          <h4>Subheading</h4>
          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>

          <h4>Subheading</h4>
          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>

          <h4>Subheading</h4>
          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
        </div>
      </div>

< div class=“row marketing”> 中有两个类为 col-lg-6 的 < div> 元素。Bootstrap 采用栅格布局,一个容器分成 12 份。col-lg-6 类表明所在的分栏占 6 份,即容器(< div class=“row marketing”>)宽度的一半。参照上述代码,修改 index.html 模板。

  • index.html
{
    
    % extends 'rango/base.html' %}
{
    
    % load static %}

{
    
    % block title_block %}
    Index
{
    
    % endblock %}

{
    
    % block body_block %}
    <div class="jumbotron">
        <h1>Rango says...</h1>
            {
    
    % if user.is_authenticated %}
                <h1>hey there {
    
    {
    
     user.username }}!</h1>
            {
    
    % else %}
                <h1>hey there partner! </h1>
            {
    
    % endif %}
            <br />
    </div>

    <div class="row marketing">
        <div class="col-lg-6">
        <h4>Most Liked Categories</h4>
        <p>
        {
    
    % if categories %}
        <ul class="list-group">
            {
    
    % for category in categories %}
                <li class="list-group-item">
                    <!--a href="/rango/category/{
    
    {category.slug}}">{
    
    {
    
    category.name}}</a--> 
                    <a href="{% url 'show_category' category.slug %}">{
    
    {
    
    category.name}}</a>   
                </li>
            {
    
    % endfor %}
        </ul>
        {
    
    % else %}
            <strong>There are no categories present.</strong>>
        {
    
    % endif %}
        </p>
        </div>


	<div class="col-lg-6">
            <h4>Most Viewed Pages</h4>
            <p>
            {
    
    % if pages %}
            <ul class="list-group">
                {
    
    % for page in pages %}
                <li class="list-group-item"><a href="{
    
    { page.url }}">{
    
    {
    
     page.title }}</a></li>
                {
    
    % endfor %}
            </ul>
            {
    
    % else %}
                <strong>There are no categories present.</strong>
            {
    
    % endif %}
            </p>
    </div>
    </div>
    
        <div>
            <img src="{% static 'images/rango.jpg'%}" alt="Picture of Rango"/><!--新增-->>
        </div>

        <p>visits: {
    
    {
    
     visits }}</p>

{
    
    % endblock %}

我们把页面的标题放在 < div class=“jumbotron”> 中,以此突出显示。现在刷新页面,看起来好多了,不过列表项目还是丑。下面使用 Bootstrap 提供的列表组样式美化一下。修改方法很简单,把 < ul> 元素改成 < ul class=“list-group”>,把 < li> 元素改成 < li class=“list-group-item”> 即可。再次刷新页面,现在好点了吧?
在这里插入图片描述

  • 我的图
    在这里插入图片描述

登录页面

接下来修改登录页面。Bootstrap 网站中有个不错的登录表单。查看网页源码,你会发现我们要在现有的表单中添加几个类才能实现演示的效果。参照下述代码更新 login.html 模板中的body_block 区块。
在这里插入图片描述

  • Signin Template for Bootstrap.html源码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">

    <title>Signin Template for Bootstrap</title>
    <link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/signin/">

    <!-- Bootstrap core CSS -->
    <link href="../../dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="signin.css" rel="stylesheet">
  </head>

  <body>

    <div class="container">

      <form class="form-signin">
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="inputEmail" class="sr-only">Email address</label>
        <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
        <div class="checkbox">
          <label>
            <input type="checkbox" value="remember-me"> Remember me
          </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      </form>

    </div> <!-- /container -->


    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>
  • login.html模板
{
    
    % extends 'rango/base.html' %}
{
    
    % load static %}

{
    
    % block title_block %}
    Login
{
    
    % endblock %}

{
    
    % block body_block %}
<link href="http://v4-alpha.getbootstrap.com/examples/signin/signin.css" rel="stylesheet">
<div class="jumbotron">
    <h1 class="display-3">Login</h1>
</div>

<form class="form-signin" role="form" method="post" action=".">
    {
    
    % csrf_token %}
    <h2 class="form-signin-heading">Please sign in</h2>
    <label for="inputUsername" class="sr-only">Username</label>
    <input type="text" name="username" id="id_username" class="form-control" placeholder="Username" required autofocus>
    <label for="inputPassword" class="sr-only">Password</label>
    <input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
    <button class="btn btn-lg btn-primary btn-block" type="submit" value="Submit" />Sign in</button>
</form>

{
    
    % endblock %}
  • base.html之body更改如下:
  <body>

    <nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
      <button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <a class="navbar-brand" href="{% url 'index' %}">Rango</a>

      <div class="collapse navbar-collapse" id="navbar">
        <ul class="navbar-nav mr-auto">
          <li class="nav-item active">
            <a class="nav-link" href="{% url 'index' %}">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'about' %}">About</a>
          </li>
        {
    
    % if user.is_authenticated %}
            <li class="nav-item">
              <a class="nav-link" href="{% url 'add_category' %}">Add a New Category</a>
            </li>
            <li class="nav-item">
            </li>
            <li class="nav-item">
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'logout' %}?next=/rango/">Logout</a>
            </li>
        {
    
    % else %}
            <li class="nav-item">
              <a class="nav-link" href="{% url 'register' %}">Register Here</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'login' %}">Login</a>
            </li>
        {
    
    % endif %}
        </ul>
      </div>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
          {
    
    % block sidebar_block %}
          {
    
    % endblock %}
        </div>
        <div class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 main">
         {
    
    % block body_block %}{
    
    % endblock %}


        </div>
      </div>
    </div>

     <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js" integrity="sha384-THPy051/pYDQGanwU6poAc/hOdQxjnOEXzbT+OuUAFqNqFjL+4IGLBgCJC3ZOShY" crossorigin="anonymous"></script>
 <!--
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
 -->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js" integrity="sha384-Plbmg8JY28KFelvJVai01l8WyZzrYWG825m+cZ0eDDS1f7d/js6ikvy1+X+guPIB" crossorigin="anonymous"></script>
    <script src="http://v4-alpha.getbootstrap.com/dist/js/bootstrap.min.js"></script>
    <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
    <!--
    <script src="http://v4-alpha.getbootstrap.com/assets/js/vendor/holder.min.js"></script>
    -->

    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="http://v4-alpha.getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
  • 书的图
    - 我的图:登录前
    在这里插入图片描述

  • 我的图:登录后
    在这里插入图片描述

其他有表单的模板

参照登录页面修改add_category.html和add_page.html模板。
在这里插入图片描述
修改后的add_page.html模板如下:

  • add_page.html
{
    
    % extends 'rango/base.html' %}
{
    
    % load static %}
    
{
    
    % block title_block %}
    Add Page
{
    
    % endblock %}


{
    
    % block body_block %}
        {
    
    % if category %}
        <form role="form" id="page_form" method="post" action="/rango/category/{
    
    { category.slug }}/add_page/">
            <h2 class="form-signin-heading"> Add a Page to
                <a href="/rango/category/{
    
    {category.slug}}/">{
    
    {
    
     category.name }}</a>
            </h2>
            {
    
    % csrf_token %}
            {
    
    % for hidden in form.hidden_fields %}
                {
    
    {
    
     hidden }}
            {
    
    % endfor %}

            {
    
    % for field in form.visible_fields %}
                {
    
    {
    
     field.errors }}
                {
    
    {
    
     field.help_text }}<br/>
                {
    
    {
    
     field }}<br/>
            {
    
    % endfor %}
            <br/>
            <button class="btn btn-primary" type="submit" name="submit" />Add Page</button>
        </form>
        
        {
    
    % else %}
            <p>This is category does not exist.</p>
        {
    
    % endif%}
        
{
    
    % endblock %}

在这里插入图片描述

修改前的add_category
在这里插入图片描述

修改后的add_category.html模板如下:

  • add_category.html
{
    
    % extends 'rango/base.html' %}
{
    
    % load static %}

{
    
    % block title_block %}
    <h2>Add a Category</h2>
{
    
    % endblock %}

{
    
    % block body_block %}
    <form role="form" id="category_form" method="post" action="{% url 'add_category' %}">
            {
    
    % csrf_token %}
            {
    
    % for hidden in form.hidden_fields %}
                {
    
    {
    
     hidden }}
            {
    
    % endfor %}
            {
    
    % for field in form.visible_fields %}
                {
    
    {
    
     field.errors }}
                {
    
    {
    
     field.help_text }}<br/>
                {
    
    {
    
     field }}<br/>
            {
    
    % endfor %}
            <br/>
            <button class="btn btn-primary" type="submit" name="submit" />Create Category</button>
    </form>
{
    
    % endblock %}

在这里插入图片描述

注册页面(我没完成registration_form.html)

  • 修改前
    在这里插入图片描述

registration_form.html模板中的表单可以像下面这样修改:

{
    
    % extends "rango/base.html" %}
{
    
    % block body_block %}

<h2 class="form-signin-heading">Sign Up Here</h2>

<form role="form"  method="post" action=".">
    {
    
    % csrf_token %}
    <div class="form-group" >
    <p class="required"><label class="required" for="id_username">Username:</label>
        <input class="form-control" id="id_username" maxlength="30" name="username" type="text" />
        <span class="helptext">Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.</span>
    </p>
        <p class="required"><label class="required" for="id_email">E-mail:</label>
            <input class="form-control" id="id_email" name="email" type="email" />
        </p>
    <p class="required"><label class="required" for="id_password1">Password:</label>
        <input class="form-control" id="id_password1" name="password1" type="password" />
    </p>
    <p class="required"><label class="required" for="id_password2">Password confirmation:</label>
        <input class="form-control" id="id_password2" name="password2" type="password" />
        <span class="helptext">Enter the same password as before, for verification.</span>
    </p>

</div>
    <button type="submit" class="btn btn-default">Submit</button>
</form>
{
    
    % endblock %}

同样,我们删掉了{ { form.as_p }}的模板标签,各表单元素及其CSS类都是自己动手编写的。

12.3 使用 Django-Bootstrap-Toolkit(django版本问题,运行失败)

除了自己动手集成之外,还可以使用 django-bootstrap-toolkit 这样的包。先使用 pip安装:$ pip install django-bootstrap-toolkit
然后打开 settings.py 模块,把 bootstrap_toolkit 添加到 INSTALLED_APPS 中。
为了在模板中使用这个包,首先要使用 load 模板标签加载它{% load bootstrap_toolkit %},然后调用一个函数,更新生成的 HTML,即 { { form|as_bootstrap }}。按照下列代码更新add_category.html 模板。

{
    
    % extends 'rango/base.html' %}
{
    
    % load static %}
{
    
    % load bootstrap_toolkit %}

{
    
    % block title_block %}
    Add Category
{
    
    % endblock %}

{
    
    % block body_block %}
    <!--form id="category_form" method="post" action="/rango/add_category/"-->
    <!--form id="category_form" method="post" action="{% url 'add_category' %}"-->
    <form role="form" id="category_form" method="post" action="{% url 'add_category' %}">
        <h2 class="form-signin-heading">Add a Category</a></h2>
            {
    
    % csrf_token %}
            {
    
    {
    
     form|as_bootstrap }}
            <br/>
            <button class="btn btn-primary" type="submit" name="submit" />Create Category</button>
    </form>
{
    
    % endblock %}

这样得到的模板更简洁,而且自动化程度更高,但是渲染结果没有手动集成的细致,因此还要做些调整和定制。

12.4 接下来

本章简要说明了如何使用Bootstrap装饰Rango应用。Bootstrap是个高度可拓展的框架,能轻易改变整体风格。StartBootstrap网站中有很多不同的风格。
除了Bootstrap之外,还有很多CSS框架可用,例如Zurb Foundation、Titon、Pure、GroundWorkd和BassCSS。
知道如何修改模板,实现响应式设计后,下面回归正题,继续为Rango应用添加功能。

小结:

  • 需删除之前未运行成功的代码,可能涉及base.html, registration,views.py之类的。
  • login后注意检查网页是否正常
  • 第12章教会我们借他山之石可以攻玉。

猜你喜欢

转载自blog.csdn.net/m0_46629123/article/details/113195973