一 模板继承
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/bootstrap@3.3.7/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/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>
{# 导航条#}
<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/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>
{% 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美化正文排版
- 博客分页
- 详情页展示
- 详情页标签以及分类跳转