Django 个人博客搭建 (4)- 博客主页设计和显示

本贴最后更新于 1666 天前,其中的信息可能已经事过境迁

一. 前言

对于博客而言,首页的合理布局和展示非常关键,本文将利用 Boundless-UI 这套我自己开发的个人博客模板结合具体代码,讲述如何编写主页视图和在主页中动态显示文章。关于这套主题模板的结构和功能在我的 github 主页中有详细介绍。

文章总共分为四个部分,一为前端准备,介绍如何导入静态文件;二编写视图,讲述如何在视图中获取文章;三文章动态显示,讲述如何在主页中利用模板语言动态地显示文章;四样例测试,运行项目进行效果测试。

二. 前端准备

1. 下载模板

  • 前往 Boundless-UI ,在 github 主页下载项目的 zip 包,解压到指定目录,进入解压目录。

2. 初始化静态文件夹

  • 将解压目录中的 statictemplates 文件夹复制到项目的 article 目录下。

  • 将解压目录中的 media 文件夹复制到项目根目录下,如下所示。
    01.png

templates 放置的是 html 模板文件,static 中存放的是图片,css 和 js 等静态资源文件,media 为媒体文件。

三. 编写视图

1. 修改模型字段

  • 由于模板的主页文章中还包含文章图片,因此需要在 models.py 中为文章模型类添加新的图片字段。修改 article/models.py,为 article 模型类添加图片字段,为后台的图片上传做准备。如下所示。
# 文章模型类
class Article(models.Model):
id = models.BigAutoField(primary_key=True) # 主键
img = models.ImageField(max_length=255, null=True, verbose_name="文章图片") # 图片字段
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="作者") # 与自带的auth.user关联
label = models.ManyToManyField('Label', verbose_name="标签") # Label和Article为多对多关系
title = models.CharField(max_length=100, verbose_name="标题") # 标题
content = models.TextField(max_length=100000, verbose_name="内容") # 内容
summary = models.CharField(blank=True, max_length=200, verbose_name="摘要") # 摘要
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # 创建时间
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # 修改时间

class Meta:
verbose_name = '文章'
verbose_name_plural = '文章'

def __str__(self):
return self.title
  • 由于调用了 django 自带的图片上传方法,所以需要配置图片上传的路径。进入项目根目录的 settings.py,在其中加入以下配置。
MEDIA_URL = '/media/'  # URL访问路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  # 本地路径
  • 修改 article/models.py,为文章图片指定保存路径,为了防止重名,重写保存路径方法 upload_to ,具体代码如下。

    upload_to 的值表示图片将被保存在相对于之前配置的 MEDIA_ROOT 中,若 upload_to = 'mmm' 则图片将被保存到 media/mmm/目录下。

import uuid
from django.conf import settings
from django.db import models

# 重写保存图片路径函数
def article_image_upload_to(instance, filename):
    return 'article/{uuid}/{filename}'.format(uuid=uuid.uuid4().hex, filename=filename)

# 文章模型类
class Article(models.Model):
    id = models.BigAutoField(primary_key=True)  # 主键
    img = models.ImageField(upload_to=article_image_upload_to, max_length=255, null=True, verbose_name="文章图片")  # 图片字段
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="作者")  # 与自带的auth.user关联
    label = models.ManyToManyField('Label', verbose_name="标签")  # Label和Article为多对多关系
    title = models.CharField(max_length=100, verbose_name="标题")  # 标题
    content = models.TextField(max_length=100000, verbose_name="内容")  # 内容
    summary = models.CharField(blank=True, max_length=200, verbose_name="摘要")  # 摘要
    gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True)  # 创建时间
    gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True)  # 修改时间

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章'

    def __str__(self):
        return self.title
  • 进入项目根目录,依次执行 python manage.py makemigrationspython manage.py migrate 命令行更新数据表。

  • 执行过程中出现了错误,提示 Pillow 库未安装,于是利用 pip install pillow 命令安装好 pillow 库之后,继续执行上述步骤中的两句命令行。
    02.png

pillow 库用于图像处理,报错的原因是在模型类中调用了 models.ImageField(),调用此字段,django 就会利用 pillow 库自动保存上传的图片(我们只需指定保存图片的路径即可),而保存图片依赖于 pillow 库。

2. 编写主页视图

  • article/views.py 中编写主页视图函数,获取文章列表,将文章列表信息传入 index.html 模板中,具体代码如下所示。
from django.shortcuts import render
from article.models import Article

# 主页
def index(request):
articles = Article.objects.all() # 获取所有文章
return render(request, 'index.html', {'articles': articles}) # 返回至index.html,传入articles
  • 将此视图函数注册到项目根目录的 urls.py 中,如下所示。
from django.contrib import admin
from django.urls import path, include
from article.views import index

urlpatterns = [
path('', index, name='index'), # path第一个参数为空表示主页
path('admin/', admin.site.urls),
path('front/', include('front.urls')),
]

四. 文章动态显示

1. 导入静态文件

在 django 中 css , js , img 等静态文件资源,需要在模板文件中加入 {% load static %} 来加载。

  • 编辑 article/templates/index.html 模板文件,在顶部加入 {% load static %} ,改写 css 和 js 的路径,利用 {% static '具体路径' %} 导入静态资源,如下所示。
    {% load static %}    <!--别忘记在html顶部导入-->
    <!--样式-->
    <link rel="stylesheet" type="text/css" href="{% static 'css/global.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'css/index.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'css/myPagination.css' %}">
    <link rel="shortcut icon" href="{% static 'img/favicon.ico' %}" />
    <!--脚本-->
    <script type="text/javascript" src="{% static 'js/jquery-3.4.1.min.js' %}"></script>
    <script type="text/javascript" src="{% static 'js/global.js' %}"></script>
    <script type="text/javascript" src="{% static 'js/myPagination.js' %}"></script>
    <script type="text/javascript" src="{% static 'js/index.js' %}"></script>

2. 遍历文章列表

  • 找到 class 属性值为 article-box 的 div,保留一个 div 即可,利用模板中的 for 循环语句遍历从后台获取的 articles 列表,并获取循环变量中的标题、摘要、作者、发布时间等值,如下所示。

    小伙伴若是不大懂模板语句,可以看我的另外一篇博文 Django 模板介绍和基本变量语法,在本文中不详细论述。

            <!--文章内容-->
            <div id="article-holder" style="width: 100%; float: left">
                {% for article in articles %}
                    <div class="article-box">
                        <div class="ab-content">
                            <div class="article-title"><a href="article-detail.html">{{ article.title }}</a></div>
                            <a href="article-detail.html" class="article-img-box">
                                <img class="article-img" alt=""
                                     src="{{ MEDIA_URL }}{{ article.img }}">
                            </a>
                            <div class="article-detail-box c-666">
                                {{ article.summary }}
                            </div>
                            <span class="article-tail-box"> <i class="fl"
                                                               style="background-image: url('{% static 'img/read-index.svg' %}')"></i>
                                <span class="read-number c-999 fl">0</span>
                                <i class="fl" style="background-image: url('{% static 'img/comment-index.svg' %}')"></i>
                                <span class="comment-number c-999 fl">0</span>
                                <span class="article-date c-999">{{ article.gmt_created | date:'Y-m-d' }}</span>
                                <span class="article-author one-line-overflow c-999">{{ article.user.name }}</span>
                            </span>
                        </div>
                    </div>
                {% endfor %}
            </div>

五. 样例测试

  • 运行项目,在浏览器中输入 http://127.0.0.1:8000/admin,登录进入后台。给文章添加图片,丰富文章内容。

  • 然后在浏览器中输入 http://127.0.0.1:8000 回到主页,查看具体效果,若操作无误即可看到更新之后的文章列表信息。但是我们发现图片无法访问。
    03.png

  • 修改项目根目录下的 urls.py(总路由),加入 media 配置信息,如下所示。

from django.contrib import admin
from django.urls import path, include, re_path
from django.views.static import serve
from article.views import index
from rainbow_blog import settings

urlpatterns = [
    path('', index, name='index'),  # path第一个参数为空表示主页
    path('admin/', admin.site.urls),
    path('front/', include('front.urls')),
    re_path(r'media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),  # media配置
]
  • 然后在 settings.py 中将 MEDIA_URL 加入其中,如下所示。
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.media',  # 加入MEDIA_URL
            ],
        },
    },
]
  • 重新运行项目,刷新主页,就能看到我们之前上传的文章图片了。
    04.png

本文主要论述了 Django 个人博客主页视图的编写,模板的导入以及 Django 中静态文件的处理,如有不足之处可以在评论区留言。

  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    534 引用 • 671 回帖
  • Django
    47 引用 • 72 回帖 • 4 关注
  • 博客

    记录并分享人生的经历。

    270 引用 • 2386 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...