分类页面与模板继承
显示单一类别的文章列表
分类页面
分类页面与首页基本相同,但是显示的是指定类别的文章
模板
在之前下载的模板文件中,有一个名为 category.html
的文件,将其复制到 templates/blog/
目录下
$ cp category.html ~/fbckf/templates/blog
添加 url 规则
分类页面的 url 是 127.0.0.1:8000/category/[分类名称]/
这种格式
# blog/urls.py
from . import views
app_name = 'blog'
urlpatterns = [
...
path('category/<slug>/', views.category, name='category'),
]
添加视图函数
# blog/views.py
...
def category(request, slug):
context = {}
category = Category.objects.get(name=slug)
context['category'] = category.name
article_list = category.article_set.all()
context['article_list'] = article_list
category_list = Category.objects.all()
context['category_list'] = category_list
if request.user.is_authenticated:
context['username']= request.user.username
return render(request, 'blog/category.html', context=context)
修改模板文件
模板文件中大部分和首页差不多
<!-- templates/blog/category.html -->
<!-- blog-content -->
...
<div class="container content">
<div class="blog-header">
<h1 class="blog-title ">Simple</h1>
<p class="lead blog-description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non quos commodi mollitia possimus, ab ad inventore consectetur in nam! Enim harum ipsum aspernatur similique et, quia earum dolor accusantium unde?</p>
</div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-light">
<li class="breadcrumb-item active" aria-current="page">{{ category }}</li>
<!-- <li class="breadcrumb-item active" aria-current="page">Library</li> -->
</ol>
</nav>
<div class="row">
<div class="col-sm-8">
{% if article_list %}
{% for article in article_list %}
<div class="card">
<img src="{% static 'blog/img/1.jpg' %}" alt="cat" class="card-img-top">
<div class="card-body">
<h5 class="card-title">{{ article.title }}</h5>
<p class="card-text">{{ article.abstract }}</p>
<a href="{% url 'blog:article' article.title %}" class="btn btn-dark">more</a>
</div>
</div>
{% endfor %}
{% endif %}
</div>
...
以上部分是最大的不同点
模板继承
仔细对比,可以发现首页和分类页面有很大的相同,而这些相同地方的代码无疑是重复,django 中,将重复的 html 代码抽离出来形成一个新的 html 文件,之后通过特定的标签进行继承。
分离代码
将相同的代码抽离放在 templates/base.html
中
<!-- templates/base.html -->
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Fbckf Blog</title>
<!-- Bootstrap -->
<link href="{% static 'blog/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'blog/css/base.css' %}" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/font-awesome.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/font-awesome.min.css' %}">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- nav -->
<div class="container">
<nav class="navbar navbar-light border-bottom" style="background-color: white">
<span class="navbar-brand font-italic">
<a href="{% url 'blog:index' %}" class="btn-light">
Fbckf
</a>
</span>
<div class="my-2 my-lg-0">
{% if username %}
<a href="/admin" class="btn btn-outline-dark" role="button">{{ username }}</a>
{% else %}
<a href="/admin" class="btn btn-outline-dark" role="button">Sign in</a>
{% endif %}
</div>
</nav>
</div>
<!-- blog-content -->
<div class="container content">
<div class="blog-header">
<h1 class="blog-title ">Simple</h1>
<p class="lead blog-description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non quos commodi mollitia possimus, ab ad inventore consectetur in nam! Enim harum ipsum aspernatur similique et, quia earum dolor accusantium unde?</p>
</div>
<!-- 用 block 标签将不同部分替代 -->
{% block body %}
{% endblock body %}
<div class="col-sm-4 col-sm-offset blog-sidebar">
<div class="sidebar-module sidebar-module-inset">
<h4>关于</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ullam alias fugiat, commodi eum fugit in fuga veritatis magni, velit minima tenetur deserunt minus repellat ea voluptatibus consequuntur asperiores quam cumque.</p>
</div>
<div class="sidebar-module">
<h4>分类</h4>
<ul class="list-group">
{% for category in category_list %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<a href="{% url 'blog:category' category.name %}">{{ category.name }}</a>
<span class="badge badge-light badge-pill">{{ category.article_count }}</span>
</li>
{% empty %}
<li class="list-group-item d-flex justify-content-between align-items-center">
暂无分类
</li>
{% endfor %}
</ul>
</div>
<div class="sidebar-module">
<div class="input-group mb-3 content">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<i class="fa fa-search" aria-hidden="true"></i>
</span>
</div>
<form action="{% url 'blog:search' %}" method="post">
{% csrf_token %}
<input name="query" type="text" class="form-control" placeholder="Search" aria-label="Search" aria-describedby="basic-addon1">
</form>
</div>
</div>
</div>
</div>
</div>
{% if is_page %}
<!-- Pagination -->
<div class="justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
<li class="page-item">
<a href="?page=1" class="page-link bg-light text-dark" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
{% ifequal article_list.number article_list.paginator.num_pages %}
<li class="page-item"><a href="?page={{ article_list.number|add:-2 }}" class="page-link bg-light text-dark">{{ article_list.number|add:-2 }}</a></li>
{% endifequal %}
{% ifnotequal article_list.number|add:-1 0 %}
<li class="page-item"><a href="?page={{ article_list.number|add:-1 }}" class="page-link bg-light text-dark">{{ article_list.number|add:-1 }}</a></li>
{% endifnotequal %}
<li class="page-item disabled"><a href="?page={{ article_list.number }}" class="page-link bg-dark text-light">{{ article_list.number}}</a></li>
{% ifnotequal article_list.number article_list.paginator.num_pages %}
<li class="page-item"><a href="?page={{ article_list.number|add:1 }}" class="page-link bg-light text-dark">{{ article_list.number|add:1 }}</a></li>
{% endifnotequal %}
{% ifequal article_list.number|add:-1 0 %}
<li class="page-item"><a href="?page={{ article_list.number|add:2 }}" class="page-link bg-light text-dark">{{ article_list.number|add:2 }}</a></li>
{% endifequal %}
<li class="page-item">
<a href="?page={{ article_list.paginator.num_pages}}" class="page-link bg-light text-dark" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
</div>
{% endif %}
<!-- button-back-top -->
<button class="btn btn-outline-dark back-top" id="backTop">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</button>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="{% static 'blog/js/jquery-3.2.1.min.js' %}"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="{% static 'blog/js/bootstrap.min.js' %}"></script>
<!-- myjq -->
<script src="{% static 'blog/js/base.js' %}"></script>
</body>
</html>
&esmp;以上就是两个模板文件的相同部分,提取出来之后,修改 index.html
和 category.html
模板,将相同部分删除,只留下不同部分
<!-- templates/blog/index.html -->
{% extends 'base.html' %}
{% load staticfiles %}
{% block body %}
<div class="row">
<div class="blog-main col-sm-8">
{% for article in article_list %}
<div class="jumbotron bg-light">
<h1 class="display-4">{{ article.title }}</h1>
<p class="lead">{{ article.abstract }}</p>
<hr class="my-4">
<p class="text-muted">{{ article.create_time }} , by {{ article.author }}</p>
<a href="{% url 'blog:article' article.title %}" class="btn btn-dark btn-lg" role="button">Read more</a>
</div>
{% empty %}
{% if error_msg %}
<div class="jumbotron bg-light">
<p class="lead">{{ error_msg }}</p>
</div>
{% else %}
<div class="jumbotron bg-light">
<p class="lead">暂无文章,敬请期待!</p>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock body %}
通过 {% extends 'base.html' %}
继承 base.html
模板,再使用 {% block %}
标签将代码包括起来,渲染时会替代 base.html
模板中的相同标签。
category.html
模板也差不多
<!-- templates/blog/category.html -->
{% extends 'base.html' %}
{% load staticfiles %}
{% block body %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb bg-light">
<li class="breadcrumb-item active" aria-current="page">{{ category }}</li>
<!-- <li class="breadcrumb-item active" aria-current="page">Library</li> -->
</ol>
</nav>
<div class="row">
<div class="col-sm-8">
{% if article_list %}
{% for article in article_list %}
<div class="card">
<img src="{% static 'blog/img/1.jpg' %}" alt="cat" class="card-img-top">
<div class="card-body">
<h5 class="card-title">{{ article.title }}</h5>
<p class="card-text">{{ article.abstract }}</p>
<a href="{% url 'blog:article' article.title %}" class="btn btn-dark">more</a>
</div>
</div>
{% endfor %}
{% endif %}
</div>
{% endblock body %}
分类页面也有分页功能,需要修改视图函数
# blog/views.py
...
def category(request, slug):
context = {}
if slug:
category = Category.objects.get(name=slug)
context['category'] = category.name
article_list = category.article_set.all().order_by('-create_time')
if article_list.count() > 10:
paginator = Paginator(article_list, 5)
page = request.GET.get('page')
if page == None:
page=1
page_list = paginator.page(page)
context['article_list'] = page_list
context['is_page'] = True
else:
context['article_list'] = article_list
category_list = Category.objects.all()
context['category_list'] = category_list
if request.user.is_authenticated:
context['username']= request.user.username
return render(request, 'blog/category.html', context=context)
总结
总的来说,个人博客项目到这里就已经完成了,剩下的只是一些细微的调整。之后可以将项目部署到服务器上使用了。
网友评论