一 模板繼承
1. 爲什麼要用模板繼承
其實很簡單,就像寫繼承類一樣,不同的html頁面也會存在大量的相同html代碼塊,而使用模板繼承可以大大減少這種重複工作,例如現在幾乎所有web站每個頁面都有導航信息塊以及底部的版權信息塊。這些相同的HTML結構塊就可以抽取出來作爲公共模板來使用。
2. 模板繼承的語法
父類模板base.html:
content1
{% block info1 %} content2 {% endblock %}
{% block info2 %}content3{% endblock %}
content4
從父類繼承的模板son.html:
{% extends 'base.html' %} 繼承語法
{% block info1 %}重寫內容{% endblock %}
以上的son.html 會繼承base.html,那son.html具體內容會有哪些呢?具體結果如下
content1 # 直接繼承過來
重寫內容 # 父模板有info1的block塊,子模板進行了擴展重寫
content3 # 雖然父模板有info2的block快,但是子模板沒有擴展重寫,所以這邊默認是直接繼承該block包含的內容的
content4 # 直接繼承過來
3. 模板代碼
瞭解基礎語法以後,我們可以創建博客的基類模板,代碼中主要包含了4個block塊,title、樣式CSS、正文主題內容content、以及最後的script, 這4個部分內容是需要擴展重寫的。具體代碼如下:
基礎模板 website/templates/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">
<!-- 上述3個meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<title>{% block title %}博客Base模板{% endblock %}</title>
<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
{% block css %}
{% endblock %}
<!-- HTML5 shim 和 Respond.js 是爲了讓 IE8 支持 HTML5 元素和媒體查詢(media queries)功能 -->
<!-- 警告:通過 file:// 協議(就是直接將 html 頁面拖拽到瀏覽器中)訪問頁面時 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
{# 導航條#}
<nav id="common-nav" class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<!-- 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">
<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="#">
<img class="navbar-logo" src="/images/bazel-navbar.svg">
</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 navbar-right">
<li>
<a href="#">
<span class="hidden-sm">GitHub</span>
<span class="nav-icon visible-sm"><i class="fa fa-github"></i></span>
</a>
</li>
<li>
<a href="#">
<span class="navbar-left">登錄</span>
</a>
</li>
<li>
<a href="#">
<span class="navbar-left">註冊</span>
</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-left">
<li>
<a href="#">博客首頁</a>
</li>
<li>
<a href="#">Python</a>
</li>
<li>
<a href="#">Django</a>
</li>
<li>
<a href="#">生活雜談</a>
</li>
<li>
<a href="#">聯繫我</a>
</li>
</ul>
<form class="navbar-form navbar-left" action="/search.html" id="cse-search-box">
<div class="form-group ">
<input type="hidden" name="cx" value="009927877080525621790:2pxlpaexqpc">
<input type="hidden" name="cof" value="FORID:10">
<input type="hidden" name="ie" value="UTF-8">
<input type="search" name="q" id="q" class="form-control input-sm" placeholder="Search">
</div>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<hr/><hr/>
<h4>這是繼承了博客基礎模板的證明</h4>
{% block content %}
{% endblock %}
{# 底部版權條#}
<footer class="footer">
<div class="container">
<div class="col-sm-1 col-md-2">
<ul class="list-unstyled">
<li><a href="#">主頁</a></li>
<li><a href="#">聯繫我</a></li>
<li><a href="#">GitHub</a></li>
<li><a href="#">版本號</a></li>
</ul>
</div>
<div class="row">
<div class="col-lg-12">
<p class="text-muted">Copyright © 2019 大嘴李的博客</p>
</div>
</div>
</div>
</footer>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依賴 jQuery,所以必須放在前邊) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<!-- 加載 Bootstrap 的所有 JavaScript 插件。你也可以根據需要只加載單個插件。 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
{% block script %}
{% endblock %}
</body>
</html>
博客首頁 index.html (這樣index就繼承了base模板):
{% extends 'base.html' %}
{% block title %}博客首頁{% endblock %}
效果圖:
二 靜態文件的配置和使用
在上述的HTML模板代碼中,可以看到bootstrap、css樣式以及js都是網絡資源,現在我們需要將這些資源配置成靜態文件來加載使用(以及之前模型設計中的img)
1.static靜態文件配置
配置之前,首先在你的目錄中創建static文件夾,將來可以在該文件目錄下存儲你的靜態文件如css、js、圖片等。
website/website/settings.py中增加如下配置:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
配置結束後,記得下載相應的靜態js/css/Bootstrap文件到相應的目錄中,或者直接頁面底部github下載。
Bootstrap : https://v3.bootcss.com/getting-started/#download
jquery: http://www.jq22.com/jquery-info122
2. 使用static靜態文件
安裝和配置結束後,就可以在模板中加載使用靜態代碼了。
語法:
首先在需要加載靜態文件的模板中(例如模板 base.html)輸入以下語句:
{% load staticfiles %}
而具體加載哪個靜態文件的語法如下:
比如要加載static文件夾下的 test.css 的文件。那麼示例代碼如下:
<link rel="stylesheet" href="{% static 'test.css' %}">
現在你可以修改base.html模板中的文件引用資源了。(如果搞不定,具體代碼文章末尾git鏈接下載吧)
3. 配置media靜態文件
在day2的模型設計中,有這麼一條關於博客插圖的語句:
img = models.ImageField(upload_to='images', blank=True, null=True, verbose_name='博客插圖')
這條語句中第一個參數upload_to是必填的,它表示的是上傳的圖片資源的路徑,其存儲路徑是相對於MEIDA_ROOT而來的。所以我們需要進行以下的配置將來纔可以正確地在博客上展示我們上傳的圖片:
website/website/seetings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace("\\", "/")
MEDIA_URL = '/media/'
配置結束後, 在我們的項目根目錄下建立如下的文件目錄。
由於上次(days2)中我們沒有配置MEDIA_ROOT的相關配置,所以上次的“博客插圖”其實並沒有上傳存儲成功,所以這邊需要我們啓動項目重新給文章進行一次圖片上傳。
啓動項目後進入admin管理界面:
python manage.py runserver
重新給博客上傳圖片,保存之後在 media/images 目錄下就可以看到我們上傳的博客配圖了。
三、 給用戶展示博客首頁(index.html)
補:
在之前的模板設計中忘記增加博客訪問量的條目了,這邊補上:
記得再重新生成遷移文件和執行遷移:
python manage.py makemigrations
python manage.py migrate
現在完成前期配置,就可以向用戶展示博客的首頁了,首先編寫views.py中的視圖函數index,然後完成展示模板index.html。
website/blog/views.py:
from django.shortcuts import render
from blog.models import Categorys,Tags,Article
def index(request):
article_list = Article.objects.all() # 獲取所有的文章
return render(request, 'index.html', {'article_list':article_list})
website/templates/index.html:
{% extends 'base.html' %}
{% block title %}博客首頁{% endblock %}
{% block content %}
<hr/>
{% for article in article_list %}
<h3>文章標題: <a href="">{{ article.title }}</a></h3>
{% if article.abstract %}
<p>{{ article.abstract }}</p>
{% else %}
<p>{{ article.body | truncatechars:100 }}</p>
{% endif %}
{% if article.img %}
<div><img src="{{ article.img.url }}" alt="博客插圖" width="25%"/></div>
{% endif %}
<p>
<span>作者:{{ article.auth }}</span>
<span>發表時間:{{ article.create_time }}</span>
<span>瀏覽量:{{ article.page_view }}</span>
</p>
<hr/>
{% endfor %}
{% endblock %}
結果展示:
可以看到圖片沒有在頁面中顯示處理,審查元素可以看到圖片的src內容是圖片文件的相對路徑;要想在前端頁面顯示圖片具體內容,有很多種方法,這裏只介紹一種:
在項目目錄級別的urls中加入以下配置和代碼:
website/website/urls.py:
from django.conf.urls import url,include
from django.contrib import admin
from django.views.static import serve # 新增的
from .settings import MEDIA_ROOT # 新增的
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/', include('blog.urls')), # include路由轉發
url(r'^media/(?P<path>.*)$', serve, {'document_root': MEDIA_ROOT}), # 新增的
]
重新啓動項目,再次打開網頁就可以看到這次圖片正常加載顯示了。
今天內容總結:
昨天主要講了模型的設計以及admin管理博客內容, 今天簡單介紹了下如何向用戶展示你admin添加的博客內容,涉及到模板的繼承,靜態文件的配置和使用。
git:
https://github.com/syjzlee/Django-website-days
下一節預計內容:
- 利用markdown美化正文排版
- 博客分頁
- 詳情頁展示
- 詳情頁標籤以及分類跳轉