本文學習如何經過Django使用Bootstrap。其實在以前好幾個Django項目中已經嘗試使用過了Bootstrap,並且都留有學習記錄,我已經大概有了一個大的框架,那麼本文就從頭再走一遍流程,其實主要細節仍是Bootstrap的經常使用的語法使用。除了基本流程,本文基於BBS+Blog項目進行學習,主要是完成其項目的模板的功能,順帶學習一下Bootstrap的內容。css
我使用的Python版本爲3.X,Bootstrap版本爲3.3.31,Django版本爲2.0。html
模板語法不懂的能夠參考博客:Django學習筆記(3)——表單,路由控制和模板語法的學習前端
點擊:Bootstrap官網下載連接html5
咱們選擇第一個,或者第二個均可以:二者的區別就是源碼內容更加完善,而用於生產的比較輕便。jquery
咱們能夠看看二者的目錄結構。git
預編譯文件能夠直接使用到任何web項目中。官方提供了編譯好的CSS和JS(bootstrap.*)文件,還有通過壓縮的CSS和JS(bootstrap.*)文件。同時還提供了CSS源碼映射表(bootstrap.*.map),能夠在某些瀏覽器的開發工具中使用。web
固然,有時候咱們作測試的時候,也能夠直接使用CDN。ajax
Bootstrap中文網爲Bootstrap專門構建了免費的CDN加速服務,訪問速度更快,加速效果更明顯,沒有速度和帶寬限制,永久免費。npm
代碼以下:django
<!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 可選的 Bootstrap 主題文件(通常不用引入) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
那所謂的CDN就是經過一個互聯網部署在多個數據中心的大型分佈式服務器系統。瀏覽器能夠並行的從CDN下載文件,不須要從本身的服務器下載文件。這些文件不在同一個域中,不會受瀏覽器的限制(同時只能在一個域下載幾個文件)。所以下載時不會一個一個排隊。另外CDN會根據用戶的位置和更快的路由速度來選擇服務器下載文件。
優勢:節省帶寬,提升網站性能。
基本結構:Bootstrap 提供了一個帶有網格系統,連接樣式,背景的基本結構。
CSS:Bootstrap 自帶如下特性:全局的CSS設置,定義基本的HTML元素樣式,可擴展的class,以及一個先進的網格系統。
組件:Bootstrap 包含了十幾個可重用的組件,其中包括如下組件:下拉菜單,按鈕組,按鈕下拉菜單,導航,導航條,路徑導航,分頁,排版,略縮圖,警告對話框,進度條,媒體對象等。
JavaScript插件:Bootstrap包含了十幾個自定義的jQuery插件。其中包括:模式對話框,標籤頁,滾動條,彈出框等。
定製:你能夠定製Bootstrap的組件,Less變量 和jQuery插件來獲得本身的版本。
咱們將下載的Bootstrap-3.3.7 放在Django項目中的static目錄下。我下載的是源碼版本的。
其次,Bootstrap插件所有依賴於jQuery,所以jQuery必須在Bootstrap以前就引入。
<!-- jQuery (Bootstrap 的全部 JavaScript 插件都依賴 jQuery,因此必須放在前邊) --> <script src="/static/JS/jquery-3.2.1.js"></script> <!-- 加載 Bootstrap 的全部 JavaScript 插件。你也能夠根據須要只加載單個插件。 --> <script src="/static/bootstrap-3.3.7/dist/js/bootstrap.min.js"></script>
咱們打開Django的settings文件,在最下面添加配置,用於指定靜態文件的搜索目錄。只有指定靜態文件的存放位置,才能在模板中正確引導他們。
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
注意:STATIC_URL 和STATICFILES_DIRS 不一樣,能夠說二者並無什麼聯繫。STATIC_URL主要是的是前端的URL搜索路徑。而STATCIFILES_DIRS 主要是聯繫的後臺靜態文件的路徑地址。
一個網站要有本身的統一風格和公共部分,能夠將這部份內容集中到一個基礎模板 base.html中,如今咱們在根目錄下的 template 中建一個 base.html 文件做爲站點的基礎模板。
在Bootstrap文檔中,爲咱們提供了一個很是簡單並且又實用的基礎模板。咱們能夠拷貝這段代碼,而後根據本身的需求對其進行改進便可。
下面是一個官網最基礎的Bootstrap頁面:
<!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"> <!-- 上述3個meta標籤*必須*放在最前面,任何其餘內容都*必須*跟隨其後! --> <title>Bootstrap 101 Template</title> <!-- Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim 和 Respond.js 是爲了讓 IE8 支持 HTML5 元素和媒體查詢(media queries)功能 --> <!-- 警告:經過 file:// 協議(就是直接將 html 頁面拖拽到瀏覽器中)訪問頁面時 Respond.js 不起做用 --> <!--[if lt IE 9]> <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script> <![endif]--> </head> <body> <h1>你好,世界!</h1> <!-- jQuery (Bootstrap 的全部 JavaScript 插件都依賴 jQuery,因此必須放在前邊) --> <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script> <!-- 加載 Bootstrap 的全部 JavaScript 插件。你也能夠根據須要只加載單個插件。 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script> </body> </html>
而後咱們修改部份內容,以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/CSS/home_site.css"> <link rel="stylesheet" href="/static/theme/{{ blog.theme }}"> <link rel="stylesheet" href="/static/CSS/article_detail.css"> <link rel="stylesheet" href="/static/CSS/index.css"> <link rel="stylesheet" href="/static/bootstrap-3.3.7/dist/css/bootstrap.css"> <script src="/static/JS/jquery-3.2.1.min.js"></script> </head> <body> <div class="header"> <div class="content"> <p class="title"> <span>{{ blog.title }}</span> <a href="/cn_backend/" class="backend">管理</a> </p> </div> </div> <div class="container"> <div class="row"> <div class="col-md-3 menu"> {% load my_tags %} {% get_classification_style username %} </div> <div class="col-md-9"> {% block content %} {% endblock %} </div> </div> </div> </body> </html>
{% load staticfiles %}
以後,纔可以使用 {% static 'path' %}
引用靜態文件。<head></head>
標籤內包含網頁的元數據,是不會在頁面內顯示出來的。<body></body>
標籤內纔是網頁會顯示的內容。這裏咱們以article_detail.html爲例進行改寫,其餘的就不一一列舉。
咱們能夠查看其部分樣式以下:
咱們能夠留意 {% block content %} 是如何與 base.html 進行對應起來的。
完整代碼以下:
{% extends "base.html" %} {% block content %} {% csrf_token %} <div class="article_info"> <h3 class="text-center title">{{ article_obj.title }}</h3> <div class="cont"> {{ article_obj.content|safe }} </div> <div class="clearfix"> <div id="div_digg"> <div class="diggit action"> <span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span> </div> <div class="buryit action"> <span class="burynum" id="bury_count">{{ article_obj.down_count }}</span> </div> <div class="clear"></div> <div class="diggword" id="digg_tips" style="color: red;"></div> </div> </div> <div class="comments list-group"> <p class="tree_btn">評論樹</p> <div class="comment_tree"> </div> <script> $.ajax({ url: "/get_comment_tree/", type: "get", data: { article_id: "{{ article_obj.pk }}" }, success: function (comment_list) { console.log(comment_list); $.each(comment_list, function (index, comment_object) { var pk = comment_object.pk; var content = comment_object.content; var parent_comment_id = comment_object.parent_comment_id; var s = '<div class="comment_item" comment_id=' + pk + '><span>' + content + '</span></div>'; if (!parent_comment_id) { $(".comment_tree").append(s); } else { $("[comment_id=" + parent_comment_id + "]").append(s); } }) } }) </script> <p>評論列表</p> <ul class="list-group comment_list"> {% for comment in comment_list %} <li class="list-group-item"> <div> <a href=""># {{ forloop.counter }}樓</a> <span>{{ comment.create_time|date:"Y-m-d H:i" }}</span> <a href=""><span>{{ comment.user.username }}</span></a> <a class="pull-right reply_btn" username="{{ comment.user.username }}" comment_pk="{{ comment.pk }}">回覆</a> </div> {% if comment.parent_comment_id %} <div class="pid_info well"> <p> {{ comment.parent_comment.user.username }}: {{ comment.parent_comment.content }} </p> </div> {% endif %} <div class="comment_con"> <p>{{ comment.content }}</p> </div> </li> {% endfor %} </ul> <p>發表評論</p> <p>暱稱:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{{ request.user.username }}"> </p> <p>評論內容:</p> <textarea name="" id="comment_content" cols="60" rows="10"></textarea> <p> <button class="btn btn-default comment_btn">提交評論</button> </p> </div> <script> // 點贊請求 $("#div_digg .action").click(function () { var is_up = $(this).hasClass("diggit"); $obj = $(this).children("span"); $.ajax({ url: "/digg/", type: "post", data: { "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(), "is_up": is_up, "article_id": "{{ article_obj.pk }}", }, success: function (data) { console.log(data); if (data.state) { var val = parseInt($obj.text()); $obj.text(val + 1); } else { var val = data.handled ? "您已經推薦過!" : "您已經反對過!"; $("#digg_tips").html(val); setTimeout(function () { $("#digg_tips").html("") }, 1000) } } }) }); // 評論請求 var pid = ""; $(".comment_btn").click(function () { var content = $("#comment_content").val(); if (pid) { var index = content.indexOf("\n"); content = content.slice(index + 1) } $.ajax({ url: "/comment/", type: "post", data: { "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(), "article_id": "{{ article_obj.pk }}", "content": content, pid: pid }, success: function (data) { console.log(data); var create_time = data.create_time; var username = data.username; var content = data.content; var s = ` <li class="list-group-item"> <div> <span>${create_time}</span> <a href=""><span>${username}</span></a> </div> <div class="comment_con"> <p>${content}</p> </div> </li>`; $("ul.comment_list").append(s); // 清空評論框 pid = "", $("#comment_content").val(""); } }) }); // 回覆按鈕事件 $(".reply_btn").click(function () { $('#comment_content').focus(); var val = "@" + $(this).attr("username") + "\n"; $('#comment_content').val(val); pid = $(this).attr("comment_pk"); }) </script> </div> {% endblock %}
url
訪問list.html
時,頂部的{% extends "base.html" %}
告訴Django:「這個文件是繼承base.html
的,你去調用它吧。」base.html
文件:{% include 'header.html' %}
代表這裏須要加入header.html
的內容。(若是存在的話,不存在忽略這一步){% include 'footer.html' %}
加入footer.html
的內容。{% block content %}{% endblock content %}
代表這裏應該加入list.html
中的對應塊的內容。當咱們循序漸進的完成的全部流程,咱們保存內容,運行開發服務器,能夠在瀏覽器輸入正確的URL地址,就能看到漂亮的頁面。
展現一下,我作的一個簡單的博客home頁面
導航條是咱們的應用或者網站中做爲導航頁頭的響應式基礎組件。他們在移動設備上能夠摺疊(而且可關可開),且再視口(viewport)寬度增長時逐漸變爲水平展開模式。
咱們能夠看到個人博客頁面右上角,若是登陸進去的話,以下:
若是沒有登陸的話,則顯示的是下面這樣的狀態:
那麼如何寫一個差很少樣式呢? 這裏爲了簡單方便起見,咱們使用Bootstrap的導航條代碼。地址:請點我
<nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <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="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</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> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</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> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>
那上面代碼顯示出來的前端頁面以下:
咱們將不須要的東西能夠去掉,留下咱們須要的,而後修改其中的語言。咱們能夠去Bootstrap中找到一個小人
而後添加到 index.html的模板中,最後修改獲得以下效果:
當首頁的導航區域設計完後,咱們開始對主體佈局,而後對尾部佈局,這裏簡單起見,咱們不打算寫尾部佈局。
咱們打算將主頁分爲三部分,第一部分是目錄區域,中間是代碼,第三部分是廣告欄區域。
咱們這裏主要學習第二部份內容的填充,因此咱們將第一部分和第三部分用進度條表示。
第一部分和第三部分進度條的代碼以下:
<div class="container-fluid"> <div class="row"> <div class="col-md-3"> <div class="panel panel-warning"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-danger"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-6">代碼</div> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-primary"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div>
效果以下:
那下面主要的任務就是文章列表的渲染,也就是中間的主要內容,包括文章的內容,點贊功能,評論功能。那主要功能就參考博客園首頁,我隨便截取了兩篇博客,效果以下:
那這就是主體內容,主要分爲博客題目,博客博主圖片博客索引,和博主名稱,發佈於,加上如期,加上評論,閱讀。
咱們就按照這樣的樣式寫便可,只不過把閱讀變爲點贊,由於後面咱們要實現這樣的效果。
因此咱們這裏主要分爲兩部分,一個是上面內容包括文章題目,頭像,索引內容渲染,一個是下面,某某博主發表於什麼時間,點贊,評論。
index.html
<div class="col-md-6"> <div class="article_list"> {% for article in article_list %} <div class="article-item"> <h5><a href="">{{ article.title }}</a></h5> <div class="article-desc"> <span class="media-left"> <a href=""><img height="56" width="56" src="media/{{ article.user.avatar }}" alt=""></a> </span> <span class="media-right"> {{ article.desc }} </span> </div> </div> <hr> {% endfor %} </div> </div>
views.py
def index(request): article_list = models.Article.objects.all() return render(request, 'index.html', locals())
前端頁面展現:
那大致效果作好後,咱們能夠完成文章點贊,評論的效果。
代碼以下:
<div class="small pub_info"> <span><a href="">{{ article.user.username }}</a> </span> <span>發佈於 {{ article.create_time|date:'Y-m-d:H:i' }}</span> <span class="glyphicon glyphicon-comment"></span>評論({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>點贊({{ article.up_count }}) </div>
咱們能夠去bootstrap中下載兩個效果圖,一個是評論,一個是點贊,下面是我隨便選擇的兩個樣式。
最後作出來的效果以下:
代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/CSS/index.css"> <link rel="stylesheet" href="/static/bootstrap-3.3.7/dist/css/bootstrap.css"> <script rel="stylesheet" src="/static/JS/jquery-3.2.1.js"></script> <script rel="stylesheet" src="/static/bootstrap-3.3.7/dist/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <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="#">博客園</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">隨筆<span class="sr-only">(current)</span></a></li> <li><a href="#">新聞</a></li> <li><a href="#">博文</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} <li><a href="#"><span id="user_icon" class="glyphicon glyphicon-user"></span>{{ request.user.username }}</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="#">修改密碼</a></li> <li><a href="#">修改頭像</a></li> <li><a href="/logout/">註銷</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> {% else %} <li><a href="/login/">登陸</a> </li> <li><a href="/register/">註冊</a> </li> {% endif %} </ul> </div> </div> </nav> <div class="container-fluid"> <div class="row"> <div class="col-md-3"> <div class="panel panel-warning"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-danger"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-6"> <div class="article_list"> {% for article in article_list %} <div class="article-item"> <h5><a href="">{{ article.title }}</a></h5> <div class="article-desc"> <span class="media-left"> <a href=""><img height="56" width="56" src="media/{{ article.user.avatar }}" alt=""></a> </span> <span class="media-right"> {{ article.desc }} </span> </div> <div class="small pub_info"> <span><a href="">{{ article.user.username }}</a> </span> <span>發佈於 {{ article.create_time|date:'Y-m-d:H:i' }}</span> <span class="glyphicon glyphicon-comment"></span>評論({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>點贊({{ article.up_count }}) </div> </div> <hr> {% endfor %} </div> </div> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-primary"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div> </body> </html>
那我的站點頁面的話,咱們但願作成和博客園差很少的效果,首先咱們查看個人博客站點:
那咱們也設置成相似的效果,有一個標題和設置,而我左邊欄目設置爲相似於博客園這種,個人標籤,隨筆分類,隨機歸檔就夠了。但願簡單容易。
上面的標題也不設置這種一張背景,前面加點字這種,設置成
標題欄目咱們就簡單的設置爲博客的名稱和設置便可。
home_site.html的代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin: 0; padding: 0; } .header{ width: 100%; height: 60px; background-color: #369; } .header .title{ font-size: 18px; font-weight: 100; line-height: 60px; color: #ffffff; margin-left: 15px; margin-top: -10px; } .backend{ float: right; color: #ffffff; font-size: 16px; margin-right: 14px; margin-top: 10px; text-decoration: none; } </style> </head> <body> <div class="header"> <div class="contents"> <p class="title"> <span>{{ blog.title }}</span> <a href="" class="backend">管理</a> </p> </div> </div> </body> </html>
視圖以下:
左邊標籤欄咱們打算設置爲個人標籤,隨筆分類,隨機歸檔就OK了。
代碼以下:
<div class="row"> <div class="col-md-3"> <div class="panel panel-warning"> <div class="panel-heading">個人標籤</div> <div class="panel-body"> {% for tag in tag_list %} <p>{{ tag.0 }}({{ tag.1 }})</p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">隨筆分類</div> <div class="panel-body"> {% for cate in cate_list %} <p>{{ cate.0 }}({{ cate.1 }})</p> {% endfor %} </div> </div> <div class="panel panel-success"> <div class="panel-heading">隨筆歸檔</div> <div class="panel-body"> {% for data in data_list %} <p>{{ data.0 }}({{ data.1 }})</p> {% endfor %} </div> </div> </div> <div class="col-md-9"> <div class="article_list"> {% for article in article_list %} <div class="article-item clearfix"> <h5><a href="">{{ article.title }}</a> </h5> <div class="article-desc"> {{ article.desc }} </div> <div class="small pub_info pull-right"> <span>發佈於 {{ article.create_time|date:'Y-m-d:H:i' }}</span> <span class="glyphicon glyphicon-comment"></span>評論({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>點贊({{ article.up_count }}) </div> </div> <hr> {% endfor %} </div> </div> </div>
展現效果以下:
index.html代碼以下:
{% extends 'base.html' %} {% block content %} <div class="article_list"> {% for article in article_list %} <div class="article-item clearfix"> <h5><a href="/{{ article.user.username }}/articles/{{ article.pk }}">{{ article.title }}</a></h5> <div class="article-desc"> {{ article.desc }} </div> <div class="small pub_info pull-right"> <span>發佈於 {{ article.create_time|date:"Y-m-d H:i" }}</span> <span class="glyphicon glyphicon-comment"></span>評論({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>點贊({{ article.up_count }}) </div> </div> <hr> {% endfor %} </div> {% endblock %}
效果以下:
因爲用了繼承,會傳相同參數致使代碼複用,因此某一些標籤(例如:菜單欄,css,js,以及一些複雜計算後的數據等)須要咱們自定義。而後在指定的HTML中引用並顯示。之因此要用到標籤,主要做用就是想讓一些內容在多個模板(HTML)中都要有,好比菜單欄。
咱們絕對不想讓每一個視圖函數(views)都寫一次這些變量內容,因此能夠繼承一些頁面的共同部分,提取出來搭配 base.html。那麼如何作呢?
首先咱們在blog這個APP下新建一個名爲 templatetags 的文件夾,並在下面建一個名爲 my_tags.py的文件,而後引入template包。其內容以下:
from django import template #註冊咱們自定義的標籤,只有註冊過的標籤,系統才能認識你,這是固定寫法 register = template.Library()
因爲需求是左邊的欄目會重複使用,其中包括他的引用函數,在views裏面也會重複使用,HTML代碼也會重複使用。因此咱們要是寫了標籤,就不須要重複再寫其代碼了。
咱們將其視圖函數中的函數和HTML中的重複代碼提取出來,視圖函數內容以下:
from django import template from django.db.models import Count from blog import models register = template.Library() @register.inclusion_tag("classification.html") def get_classification_style(username): user = models.UserInfo.objects.filter(username=username).first() blog = user.blog cate_list = models.Category.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values_list( "title", "c") tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c=Count("article")).values_list("title", "c") date_list = models.Article.objects.filter(user=user).extra( select={"y_m_date": "date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate( c=Count("nid")).values_list("y_m_date", "c") return {"blog": blog, "cate_list": cate_list, "date_list": date_list, "tag_list": tag_list}
classification.html代碼以下:
<div> <div class="panel panel-warning"> <div class="panel-heading">個人標籤</div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">隨筆分類</div> <div class="panel-body"> {% for cate in cate_list %} <p><a href="/{{ username }}/category/{{ cate.0 }}">{{ cate.0 }}({{ cate.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-success"> <div class="panel-heading">隨筆歸檔</div> <div class="panel-body"> {% for date in date_list %} <p><a href="/{{ username }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p> {% endfor %} </div> </div> </div>
標籤相關方法指的是在html顯示前,後臺先進行預處理,和咱們日常的方法相同,只不過這個方法是針對標籤所定義的,,inclution_tag模板語法把參數傳給 inclution_tag 渲染好公共部分後,直接返回 HTML 代碼會更爲方便。
那 base.html 裏面引用以下:
<div class="container"> <div class="row"> <div class="col-md-3 menu"> {% load my_tags %} {% get_classification_style username %} </div> <div class="col-md-9"> {% block content %} {% endblock %} </div> </div> </div>
咱們使用 load my_tags引用。
標籤字符 [轉義] 才能格式化出文章樣式 safe 後臺必須作一個篩選,不然加上 safe 可能會受到 xss 攻擊。
{% extends 'base.html' %} {# 繼承公共部分 #} {% block content %} <h3 class="text-center">{{ article_obj.title }}</h3> <div class="cont"> {{ article_obj.content|safe }} </div> {% endblock %}