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>© 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章教会我们借他山之石可以攻玉。