前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于 Django 的个人网站(4)

基于 Django 的个人网站(4)

作者头像
不可言诉的深渊
发布2020-05-27 11:40:11
1K0
发布2020-05-27 11:40:11
举报
上回说到,虽然已经基本上把显示的格式改的差不多了,但是界面还是不够美观,同时也没有实现分类页面和检索文章页面,今天我们先来实现分类页面和检索文章的页面。

分类页面的实现

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

代码语言:javascript
复制
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 列表中添加一项,代码如下:

代码语言:javascript
复制
path('categories/<category_id>', CategoryView.as_view())

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

代码语言:javascript
复制
<nav>
    <a href="/">首页</a>
    {% for category in categories %}
        <a href="/categories/{{ category.id }}">{{ category }}</a>
    {% endfor %}
</nav>

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

搜索页面的实现

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

代码语言:javascript
复制
<form action="/search" method="get">
    <label>
        <input name="keyword" type="text">
    </label>
    <input type="submit" value="搜索">
</form>

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

代码语言:javascript
复制
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 列表中添加一项,代码如下:

代码语言:javascript
复制
path('search/', SearchView.as_view())

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

代码语言:javascript
复制
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,代码如下:

代码语言:javascript
复制
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,代码如下:

代码语言:javascript
复制
<!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 %}
        &nbsp;第&nbsp;{{ page_obj.number }}&nbsp;页/共&nbsp;{{ page_obj.paginator.num_pages }}&nbsp;页&nbsp;
        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">下一页</a>
        {% endif %}
    {% endif %}
</p>
</body>
</html>

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

代码语言:javascript
复制
<!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>

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

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

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

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

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

bootstrap 的安装

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

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python机器学习算法说书人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档