0
点赞
收藏
分享

微信扫一扫

基于 Django 的个人网站(4)



上回说到,虽然已经基本上把显示的格式改的差不多了,但是界面还是不够美观,同时也没有实现分类页面和检索文章页面,今天我们先来实现分类页面和检索文章的页面。





分类页面的实现


考虑到分类页面是一个用来展示属于当前类别的所有文章,和首页一样的格式,就是显示的列表项十有八九会比首页少,因此分类页面的视图直接继承首页的视图,然后重写 get_queryset 方法就完事了,代码如下:

class CategoryView(IndexView):
def get_queryset(self):
return super().queryset.filter(categories__in=Category.objects.filter(id=self.kwargs['category_id'])).order_by(
'-id')

然后去配置一下 URL,向 urlpatterns 列表中添加一项,代码如下:

path('categories/<category_id>', CategoryView.as_view())

最后去对应的模板文件中增加带有超链接的导航栏,代码如下:

<nav>
<a href="/">首页</a>
{% for category in categories %}
<a href="/categories/{{ category.id }}">{{ category }}</a>
{% endfor %}
</nav>

运行之后点击分类的超链接就跳到分类页面,分类页面从逻辑上来说就已经实现了,可能会有排版和导包的问题,最后我会给出 views.py 的源码和 html 文件的源码,我们先不管了,接着去实现搜索页面,最后再一起测试。



搜索页面的实现


要想搜索首先必须有一个输入框,一个按钮,这两个组件直接使用 html 的表单就可以完成了,表单代码如下:

<form action="/search" method="get">
<label>
<input name="keyword" type="text">
</label>
<input type="submit" value="搜索">
</form>

接下来我们就去想一下搜索页面是个什么样的格式——其实还是和主页面差不多,同样继承主页面对应的视图,然后重写 get_queryset 方法就完事了,代码如下:

class SearchView(IndexView):
def get_queryset(self):
keyword = self.request.GET.get('keyword', '')
return super().queryset if not keyword else super().queryset.filter(Q(title__icontains=keyword) | Q(
abstract__icontains=keyword))

我为了性能考虑,就不从文章内容中匹配关键字了,只从标题和摘要中匹配一下,分类也不需要考虑,一篇文章对应多个分类,模糊检索本来就很耗费时间,多个分类就对应了多个模糊检索。

表单有了,视图有了,最后我们直接配置 URL,在 urlpatterns 列表中添加一项,代码如下:

path('search/', SearchView.as_view())

现在该实现的也基本全都实现了,接下来我就给出视图、模板和 URL 的完整代码,首先是视图 personal_website\views.py,代码如下:

from django.db.models import Q
from django.views.generic import DetailView, ListView
from.models import Article, Category




# Create your views here.
class IndexView(ListView):
context_object_name = 'articles'
paginate_by = 10
queryset = Article.objects.filter(state=1).order_by('-id')
template_name = 'index.html'


def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data()
context['categories'] = Category.objects.order_by('-id')
return context




class ArticleDetailView(DetailView):
context_object_name = 'article'
model = Article
template_name = 'article_detail.html'


def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data()
context['categories'] = Category.objects.order_by('-id')
return context




class CategoryView(IndexView):
def get_queryset(self):
return super().queryset.filter(categories__in=Category.objects.filter(id=self.kwargs['category_id'])).order_by(
'-id')




class SearchView(IndexView):
def get_queryset(self):
keyword = self.request.GET.get('keyword', '')
return super().queryset if not keyword else super().queryset.filter(Q(title__icontains=keyword) | Q(
abstract__icontains=keyword))

接下来是 URL 配置的代码,对应文件为 PersonalWebsite\urls.py,代码如下:

from django.contrib import admin
from django.urls import path, include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings
from django.conf.urls.static import static
from personal_website.views import IndexView, ArticleDetailView, CategoryView, SearchView
urlpatterns = [
path('admin/', admin.site.urls),
path("ckeditor5/", include('django_ckeditor_5.urls')),
path('', IndexView.as_view()),
path('articles/<pk>', ArticleDetailView.as_view()),
path('categories/<category_id>', CategoryView.as_view()),
path('search/', SearchView.as_view())
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)+staticfiles_urlpatterns()

最后是两个模板文件,首先是列表页的模板文件——templates\index.html,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>陈志豪的个人网站</title>
<style>
p{
text-indent: 2em;
}
</style>
</head>
<body>
<!--suppress HtmlDeprecatedAttribute -->
<h1 align="center">陈志豪的个人网站</h1>
<nav>
<a href="/">首页</a>
{% for category in categories %}
<a href="/categories/{{ category.id }}">{{ category }}</a>
{% endfor %}
</nav>
<!--suppress HtmlUnknownTarget -->
<form action="/search" method="get">
<label>
<input name="keyword" type="text">
</label>
<input type="submit" value="搜索">
</form>
{% for article in articles %}
<h2><a href="/articles/{{ article.id }}">{{ article.title }}</a></h2>
<p>{{ article.abstract }}</p>
{% endfor %}
<p>
{% if is_paginated %}
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">上一页</a>
{% endif %}
 第 {{ page_obj.number }} 页/共 {{ page_obj.paginator.num_pages }} 页 
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">下一页</a>
{% endif %}
{% endif %}
</p>
</body>
</html>

其次是文章详情页面的模板文件——templates\article_detail.html,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ article.title }}</title>
<link href="/static/css/prism.css" rel="stylesheet" />
<style>
p{
text-indent: 2em;
}
figure{
text-align: center;
margin: 0 auto;
}
</style>
</head>
<body>
<!--suppress HtmlDeprecatedAttribute -->
<h1 align="center">陈志豪的个人网站</h1>
<nav>
<a href="/">首页</a>
{% for category in categories %}
<a href="/categories/{{ category.id }}">{{ category }}</a>
{% endfor %}
</nav>
<!--suppress HtmlUnknownTarget -->
<form action="/search" method="get">
<label>
<input name="keyword" type="text">
</label>
<input type="submit" value="搜索">
</form>
<!--suppress HtmlDeprecatedAttribute -->
<h1 align="center">{{ article.title }}</h1>
<p>{{ article.abstract }}</p>
{{ article.content|safe }}
<script src="/static/js/prism.js"></script>
</body>
</html>

最后我们来看一下运行的效果,运行项目进入首页,如图所示。

基于 Django 的个人网站(4)_django

这个时候虽然有点怪怪的,但是导航栏和搜索框都有了,我们虽点在导航栏中点击一个类别,我在这里点击类别5,如图所示。

基于 Django 的个人网站(4)_搜索_02

看到 URL 最后是 5 就说明没有问题,同时也可以去管理后台看显示的这两篇文章是不是有类别5 这个分类。接下来我们就尝试搜索,在搜索框中输入一个东西,看看是否可以被检索到,我在这里直接输入 2,然后点击搜索,最后搜索的结果如图所示。

基于 Django 的个人网站(4)_django_03

说明这可以实现对标题或者摘要的模糊搜索,其实可以多测试几个,我就不进行测试了。

今天的内容基本上结束了,最后讲一下怎么安装配置 bootstrap。



bootstrap 的安装


在安装 bootstrap 之前,我们首先需要了解一下什么是 bootstrap,Bootstrap,来自 Twitter,是目前最受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。

首先进入 bootstrap 官网(https://www.bootcss.com/)把东西下载下来,下载好之后应该会得到一个压缩文件,我们进行解压,解压之后如图所示。

基于 Django 的个人网站(4)_搜索_04

接下来不用去看都应该知道怎么弄了吧,把这里 css 文件夹下面所有文件复制到项目中的 css 静态文件目录,同时把 js 文件夹中的所有文件复制到项目中的 js 静态文件目录,完成之后项目中静态文件目录如图所示。

基于 Django 的个人网站(4)_django_05

好,今天就讲到这里,明天我就直接给出修改好的模板文件的源码,同时给出运行的效果。

今天的文章有不懂的可以后台回复“加群”,备注:小陈学Python,不备注可是会被拒绝的哦~!



基于 Django 的个人网站(4)_django_06

扫描二维码更精彩




文章都看完了

不点个

基于 Django 的个人网站(4)_django_08


举报

相关推荐

0 条评论