600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Django个人博客搭建8-优化文章模块

Django个人博客搭建8-优化文章模块

时间:2019-03-02 19:10:57

相关推荐

Django个人博客搭建8-优化文章模块

Django个人博客搭建1-创建Django项目和第一个App

Django个人博客搭建2-编写文章Model模型,View视图

Django个人博客搭建3-创建superuser并向数据库中添加数据并改写视图

Django个人博客搭建4-配置使用 Bootstrap 4 改写模板文件

Django个人博客搭建5-编写文章详情页面并支持markdown语法

Django个人博客搭建6-对文章进行增删查改

Django个人博客搭建7-对用户登陆注册等需求的实现

Django个人博客搭建8-优化文章模块

Django个人博客搭建9-增加文章评论模块

1.文章分页

利用Django内置的分页模块:Paginator类(:Paginator官网例子),因为是对文章分页,因此需要修改article/views.py中article_list视图:

from django.core.paginator import Paginator# 文章列表函数def article_list(request):# 取出所有博客文章article_list = ArticlePost.objects.all()# 每页显示一篇文章paginator = Paginator(article_list, 1)# 获取url中的页码page = request.GET.get('page')# 将导航对象相应的页码内容返回给articlesarticles = paginator.get_page(page)# 需要传递给模板对象context = {'articles': articles}# render函数载入模板,并返回context对象return render(request, 'article/list.html', context)# article/list.html:模板位置context:传入模板的对象

接下来修改templates/article/list.html加入分页内容

...<div class="pagination row"><div class="m-auto"><span class="step-links"><!-- 如果不是第一页,则显示上翻按钮 -->{% if articles.has_previous %}<a href="?page=1" class="btn btn-success">&laquo; 1</a><span>...</span><a href="?page={{ articles.previous_page_number }}"class="btn btn-secondary">{{ articles.previous_page_number }}</a>{% endif %}<!-- 当前页面 --><span class="current btn btn-danger btn-lg">{{ articles.number }}</span><!-- 如果不是最末页,则显示下翻按钮 -->{% if articles.has_next %}<a href="?page={{ articles.next_page_number }}"class="btn btn-secondary">{{ articles.next_page_number }}</a><span>...</span><a href="?page={{ articles.paginator.num_pages }}"class="btn btn-success">{{ articles.paginator.num_pages }} &raquo;</a>{% endif %}</span></div></div>

最后查看效果:

分页功能完成

2.文章浏览量

首先修改文章的模型article/models.py

# 博客文章数据模型class ArticlePost(models.Model):...updated = models.DateTimeField(auto_now=True)total_views = models.PositiveIntegerField(default=0)...

PositiveIntegerField是用于存储正整数的字段

接着生成迁移

python manage.py makemigrations

F:\Desktop\myblog>python manage.py makemigrationsSystem check identified some issues:WARNINGS:article.ArticlePost.created: (fields.W161) Fixed default value provided.HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`Migrations for 'article':article\migrations\0003_auto_0210_1956.py- Add field total_views to articlepost- Alter field created on articlepostMigrations for 'userprofile':userprofile\migrations\0002_auto_0210_1956.py- Alter field avatar on profile

执行迁移:

F:\Desktop\myblog>python manage.py migrateSystem check identified some issues:WARNINGS:article.ArticlePost.created: (fields.W161) Fixed default value provided.HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`Operations to perform:Apply all migrations: admin, article, auth, contenttypes, sessions, userprofileRunning migrations:Applying article.0003_auto_0210_1956... OKApplying userprofile.0002_auto_0210_1956... OKF:\Desktop\myblog>

我们一般需要在文章列表和文章详情中显示各个文章的浏览量,因此先修改article/list.html

...<div class="card-footer"><a href="{% url 'article:article_detail' article.id %}" class="btn btn-primary">阅读本文</a><span><small class="col align-self-end" style="color: gray;">浏览量:{{ article.total_views }}</small></span>...

接着修改详情模板article/detail.html:

<!-- extends表明此页面继承自 base.html 文件 -->{% extends "base.html" %}{% load staticfiles %}<!-- 写入 base.html 中定义的 title -->{% block title %}文章详情{% endblock title %}<!-- 写入 base.html 中定义的 content -->{% block content %}<!-- 文章详情 --><div class="container">...{% if user == article.author %}.<a href="#" onclick="confirm_delete()">删除文章</a>.<a href="{% url "article:article_update" article.id %}">编辑文章</a>{% endif %}</div><div>浏览量:{{ article.total_views }}</div><div class="col-12"><p>{{ article.body|safe }}</p>...{% endblock content %}

首先修改得就是检查登陆用户是否为文章作者本人,如果是本人才会显示删除和编辑文章,接着在下面增加显示浏览量

重启服务器:

可以看见文章列表可以显示文章浏览量了,点击阅读本文:

前面修改了修改删除文章得权限,因此用户没有登陆时时没有这两个选项的,我们点击登陆

登陆后就显示了,但是由于没有对浏览量的进行逻辑处理,就是文章的浏览量总是初始给定的0,因此修改article/views.py中article_detail使其点击一次文章详情total_views就+1:

def article_detail(request, id):...article.total_views += 1article.save(update_fields=['total_views'])...

update_fields=[]指定了数据库只更新total_views字段,优化执行效率。

我们重新刷新一下详情页面:

发现文章的浏览量已经自动增加了

这样文章浏览量功能就已经完成了

3.根据浏览量排序最热文章:

重写article/views.py:article_list():

# 文章列表函数def article_list(request):# 根据GET请求中查询条件# 返回不同排序的对象数组if request.GET.get('order') == 'total_views':article_list = ArticlePost.objects.all().order_by('-total_views')order = 'total_views'else:article_list = ArticlePost.objects.all()order = 'normal'paginator = Paginator(article_list, 3)page = request.GET.get('page')articles = paginator.get_page(page)# 修改此行context = {'articles': articles, 'order': order}return render(request, 'article/list.html', context)

'-total_views’为反序,即文章浏览量高的在前面

接下来修改templates/article/list.html

...{% block content %}<!-- 定义放置文章标题的div容器 --><div class="container"><nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="{% url 'article:article_list' %}">最新</a></li><li class="breadcrumb-item"><a href="{% url 'article:article_list' %}?order=total_views">最热</a></li></ol></nav><div class="row mt-2">{% for article in articles %}<!-- 文章内容 -->...

重启服务器点击最热查看效果:

可以看见文章排序是按照文章浏览量排序的了

这样最热文章功能就完成了

4.搜索文章功能

Q对象

Model.objects.all()能够返回表中的所有对象。

对应的,Model.objects.filter(**kwargs)可以返回与给定参数匹配的部分对象。

还有Model.objects.exclude(**kwargs)返回与给定参数不匹配的对象

如果想对多个参数进行查询怎么办?比如同时查询文章标题和正文内容。这时候就需要Q对象。

首先修改article/views.py

# 文章列表函数def article_list(request):search = request.GET.get('search')order = request.GET.get('order')# 用户搜索逻辑,请求中有search,则走次逻辑if search:if order == 'total_views':# 用q对象进行联合搜索article_list = ArticlePost.objects.filter(Q(title__contains=search)| # icontains不区分分大小写,contains区分大小写Q(body__icontains=search)).order_by('-total_views')else:article_list = ArticlePost.objects.filter(Q(title__contains=search) |Q(body__icontains=search))# 根据GET请求中查询条件# 返回不同排序的对象数组else:search = ''if order == 'total_views':article_list = ArticlePost.objects.all().order_by('-total_views')else:article_list = ArticlePost.objects.all()paginator = Paginator(article_list, 3)page = request.GET.get('page')articles = paginator.get_page(page)# 修改此行context = {'articles': articles, 'order': order, 'search': search}return render(request, 'article/list.html', context)

接着修改模板:article/list.html

<nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="{% url 'article:article_list' %}">最新</a></li><li class="breadcrumb-item"><a href="{% url 'article:article_list' %}?order=total_views">最热</a></li></ol></nav><div class="row"><div class="col-auto mr-auto"><form class="form-inline"><label class="sr-only">content</label><input type="text"class="form-control"name="search"placeholder="搜索文章..."required></form></div></div>{# 搜索提示语 #}{% if search %}<h4><span style="color: red">{{ search }}</span>的搜索内容如下</h4><hr>{% else %}<h4>暂无<span style="color: red">{{ search }}</span> </h4>有关的文章<hr>{% endif %}<div class="row mt-2">{% for article in articles %}<!-- 文章内容 --><div class="col-4 mb-4"><!-- 卡片容器 --><div class="card h-100"><!-- 标题 --><h4 class="card-header">{{ article.title }}</h4><!-- 摘要 --><div class="card-body"><p class="card-text">{{ article.body|slice:'100' }}...</p></div><!-- 注脚 --><div class="card-footer"><a href="{% url 'article:article_detail' article.id %}" class="btn btn-primary">阅读本文</a><span><small class="col align-self-end" style="color: gray;">浏览量:{{ article.total_views }}</small></span></div></div></div>{% endfor %}</div></div><div class="pagination row"><div class="m-auto"><span class="step-links"><!-- 如果不是第一页,则显示上翻按钮 -->{% if articles.has_previous %}<a href="?page=1&order={{ order }}&search={{ search }}" class="btn btn-success">&laquo; 1</a><span>...</span><a href="?page={{ articles.previous_page_number }}&order={{ order }}&search={{ search }}"class="btn btn-secondary">{{ articles.previous_page_number }}</a>{% endif %}<!-- 当前页面 --><span class="current btn btn-danger btn-lg">{{ articles.number }}</span><!-- 如果不是最末页,则显示下翻按钮 -->{% if articles.has_next %}<a href="?page={{ articles.next_page_number }}&order={{ order }}&search={{ search }}"class="btn btn-secondary">{{ articles.next_page_number }}</a><span>...</span><a href="?page={{ articles.paginator.num_pages }}&order={{ order }}&search={{ search }}"class="btn btn-success">{{ articles.paginator.num_pages }} &raquo;</a>{% endif %}</span></div></div>

面包屑组件、页码组件都改动了href:增加了search参数

新增搜索栏,以GET请求提交search参数;required属性阻止用户提交空白文本

新增搜索提示语。好的UI必须让用户了解当前的状态

我们重启服务器打开文章列表页面

搜索java

这样文章的搜索功能就完成了

5.渲染Markdown目录

首先修改article/views.py:

# 文章详情def article_detail(request, id):...article.body = markdown.markdown(article.body,extensions=[# 包含 缩写、表格等常用扩展'markdown.extensions.extra',# 语法高亮扩展'markdown.extensions.codehilite',# 目录扩展'markdown.extensions.toc',])...

添加了一行代码,接着我们在之前的文章里添加几个级别的标题

其实就是插入不同级别的标题,然后在文章任何地方插入**[TOC]**即可自动生成目录

点击完成后观察效果:

如果我们想实现将目录插入到页面任何一个位置就徐娅萍修改Markdown的渲染方法:

# 文章详情def article_detail(request, id):article = ArticlePost.objects.get(id=id)article.total_views += 1article.save(update_fields=['total_views'])md = markdown.Markdown(extensions=[# 包含 缩写、表格等常用扩展'markdown.extensions.extra',# 语法高亮扩展'markdown.extensions.codehilite',# 目录扩展'markdown.extensions.toc',])article.body = md.convert(article.body)context = {'article': article, 'toc': md.toc}# 载入模板,并返回context对象preturn render(request, 'article/detail.html', context)

为了能将toc单独提取出来,我们先将Markdown类赋值给一个临时变量md,然后用convert()方法将正文渲染为html页面。通过md.toc将目录传递给模板。

修改article/detail.html

...<!-- 文章详情 --><div class="container"><div class="row"><div class="col-9"><h1 class="col-12 mt-4">{{ article.title }}</h1><div class="col-12 alert alert-success">作者: {{ article.author }}{% if user == article.author %}.<a href="#" onclick="confirm_delete()">删除文章</a>.<a href="{% url "article:article_update" article.id %}">编辑文章</a>{% endif %}</div><div>浏览量:{{ article.total_views }}</div><div class="col-12"><p>{{ article.body|safe }}</p></div></div>{# 目录 #}<div class="col-3 mt-4"><h4><strong>目录</strong><hr><div>{{ toc|safe }}</div></h4></div></div></div><script>//删除文章的函数function confirm_delete() {...

将原来的内容装进col-9的容器中,将右侧col-3的空间留给目录,toc需要|safe标签才能正确渲染

我们重新刷新页面:

发现右边已经正确显示目录了

Django个人博客搭建1-创建Django项目和第一个App

Django个人博客搭建2-编写文章Model模型,View视图

Django个人博客搭建3-创建superuser并向数据库中添加数据并改写视图

Django个人博客搭建4-配置使用 Bootstrap 4 改写模板文件

Django个人博客搭建5-编写文章详情页面并支持markdown语法

Django个人博客搭建6-对文章进行增删查改

Django个人博客搭建7-对用户登陆注册等需求的实现

Django个人博客搭建8-优化文章模块

Django个人博客搭建9-增加文章评论模块

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。