Django笔记07-博客首页(1)

博客首页

django 框架的工作流程已经大致了解了,接下来就是真正的完成博客首页

博客模板

 django 的优点之一就是将模板(Templates)独立出来,而本博客的模板是我自己使用Bootstrap框架编写的,完整代码我放在了github上,只是简单实现博客的部分功能。将其clone到本地以供使用。

安装

# 选择一个目录放置模板源文件,进入目录
$ git clone https://github.com/fbckf/blog-template.git
Cloning into 'blog-template'...
remote: Counting objects: 42, done.
remote: Total 42 (delta 0), reused 0 (delta 0), pack-reused 42
Unpacking objects: 100% (42/42), done.
Checking connectivity... done.

clone到本地之后,目录中会多出一个blog-template目录,里面就是博客模板的源文件。

# 查看 blog-template/ 目录结构
$ tree blog-template
blog-template
├── article.html
├── category.html
├── css
│      ├── base.css
│      ├── bootstrap.min.css
│      ├── bootstrap.min.css.map
│      ├── font-awesome.css
│      └── font-awesome.min.css
├── fonts
│      ├── FontAwesome.otf
│      ├── fontawesome-webfont.eot
│      ├── fontawesome-webfont.svg
│      ├── fontawesome-webfont.ttf
│      ├── fontawesome-webfont.woff
│      └── fontawesome-webfont.woff2
├── img
│      ├── 1.jpg
│      ├── 2.jpg
│      ├── 3.jpg
│      ├── 4.jpg
│      ├── carousel1.jpg
│      ├── carousel2.jpg
│      └── carousel3.jpg
├── index.html
├── js
│     ├── base.js
│     ├── bootstrap.min.js
│     ├── bootstrap.min.js.map
│     ├── jquery-3.2.1.min.js
│     └── popper.min.js
└── README.md

  • index.html 博客首页

  • article.html 文章详情页面

  • category.html 类别页面

  • css/ 存放 css 文件

  • fonts/存放 Font Awesome 图标字体 文件

  • img/ 存放 图片资源

  • js/ 存放 js 文件

预览

 首页


image
image

修改模板

 原先的首页模板只是简单编写的一个 html 文件,现在把它替换成新的的博客首页。

$ cp index.html ~/fbckf/templates/blog/

 刷新页面,发现没有显示出预计的效果


image

F12查看报错信息

...
Failed to load resource: the server responded with a status of 404 (Not Found)
base.css 
Failed to load resource: the server responded with a status of 404 (Not Found)
font-awesome.css 
Failed to load resource: the server responded with a status of 404 (Not Found)
font-awesome.min.css 
Failed to load resource: the server responded with a status of 404 (Not Found)
jquery-3.2.1.min.js 
Failed to load resource: the server responded with a status of 404 (Not Found)
base.js 
Failed to load resource: the server responded with a status of 404 (Not Found)
bootstrap.min.js 
Failed to load resource: the server responded with a status of 404 (Not Found)
base.js 
...

 原因是静态文件加载错误,静态文件与模板文件的相对位置发生改变,原先的加载路径无法加载到文件,所以无法现实样式效果

静态文件

 django 中,处理静态文件和模板文件差不多,都是放到指定的目录集中管理。在 blog 应用目录中创建static/blog/目录用以存放应用自身的静态文件,之后将博客模板的静态文件复制到static/blog/目录中

# 在 blog/ 目录中创建目录
$ mkdir static
$ mkdir static/blog
# 将静态文件复制到 blog/static/blog/ 目录中
$ cp -R css js img fonts ~/fbckf/blog/static/blog

 django 会自动在应用目录下搜索静态文件,也可以将公共的静态文件分离出来单独存放,只需在 settings.py 中指定路径即可

# fbckf/settings.py
...
# 静态文件的 url 映射
STATIC_URL = '/static/'
# 部署网站时指定的收集静态文件的路径
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# 在配置文件最末尾添加 STATICFILES_DIRS 列表,在其中添加静态文件路径
# 注意 STATICFILES_DIRS 中路径不可与 STATIC_ROOT 一致
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'blog/static'),
]

 django 在加载静态文件时,会在STATICFILES_DIRS列表中的目录下搜索目标文件进行加载,这里指定的目录是~/fbckf/blog/static/

 在模板文件中,原本加载静态文一般是使用src属性,如<link href="css/bootstrap.min.css" rel="stylesheet">或者<script src="js/jquery-3.2.1.min.js"></script>等。而在 django 中,则要用到 模板标签 {% %}

<!-- fbckf/templates/blog/index.html -->
<!-- 原首页源文件 -->
...
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/font-awesome.css">
<link rel="stylesheet" type="text/css" href="css/font-awesome.min.css">
...
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<!-- myjq -->
<script src="js/base.js"></script>
...
<!-- fbckf/templates/blog/index.html -->
<!-- 使用模板标签 -->
...
<!-- 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' %}">
...
<!-- 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>
...

 修改完成之后再刷新页面,可以看到静态文件已经加载成功,样式效果也出来了。

image

首页数据

 之前编写的的视图函数中,只获取了指定的一篇文章,然而首页中显示的文章显然不止一篇,所以需要对视图函数进行修改。

文章列表

# blog/views.py
from django.shortcuts import render
from .models import Category, Article

def index(request):
    # 之前使用 get() 方法只是返回符合指定条件的文章
    # 而 all() 方法则返回所有的文章,返回的对象是一个QuerySet类型数据
    article_list = Article.objects.all() 
    # 同样的方法获取所以类别
    category_list = Category.objects.all()
    # 将 article_list 和 category_list 放到字典中,将该字典传递给模板
    context = {
        'article_list': article_list, 
        'category_list': category_list
    }
    return render(request, 'blog/index.html', context=context)

 再修改模板文件,显示文章数据

<!-- fbckf/templates/blog/index.html -->
...
<!-- blog-content -->
...
<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 }}</p>
            <a href="#" class="btn btn-dark btn-lg" role="button">Read more</a> 
        </div>
    {% empty %}
        <div class="jumbotron bg-light">
            <p class="lead">暂无文章,敬请期待!</p>
        </div>
    {% endfor %}
    </div> 
...
  • 在模板文件中,可以找到 `` 这个注释,在这个注释之后找到 <div class="container content"> 标签和他的子标签 <div class="row">,如上所示。而每一篇文章都包含在一个 <div class="jumbotron bg-light"> 标签中

  • 使用 {% for %} 模板标签循环遍历article_list列表,并赋值给 article变量,每一个 article 都是一个对象(Article类的实例),{{ article.title }}就是调用 title 属性。

  • {% empty %} 表示当 article_list 为空是执行标签中的代码。

  • {% endfor %}{% for %} 模板标签的结束标签

分类列表

 分类列表中需要两个数据,第一个是分类名称,第二个是分类下的文章数量,因为之前没有考虑到文章数量,所以现在要修改数据模型,在 category 模型中加入 article_count 字段来存储文章数量这一数据。

# blog/models.py
...
class Category(models.Model):
    name = models.CharField(max_length=20, unique=True)
    instructions = models.TextField(max_length=100, default="")
    # 添加文章数量这一字段,该字段只能是正整数,默认为零
    article_count = models.PositiveIntegerField(default=0)

    def __str__(self):
        return self.name
...

 修改完模型之后,需要进行数据库迁移,更改数据库中的结构

$ python manage.py makemigrations
Migrations for 'blog':
  blog/migrations/0002_category_article_count.py
    - Add field article_count to category

$ python manage.py migrate  
Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:

 在数据库表 category 中增加了文章数量的字段之后,还没有真正完成。现在只是增加了这个字段,但是还没有去更新它,用户也不可能每次在增加文章之后,手动的去更新这个字段,所以还需要让它能够自动的去更新该字段的值。

 办法有很多,这用的是最简单的一种。每次在刷新首页时更新 article_count 字段

# blog/views.py

...
def index(request):
    ...
    category_list = Category.objects.all()
    for category in category_list:
        # 使用 filter() 将各个分类下的文章筛选出来,再使用 count() 方法获取数量
        count = Article.objects.all().filter(category=category).count()
        # 之后更新字段
        category.article_count = count
        category.save()
...

 更改保存,之后每次用户刷新首页,都会更新文章所属类别的 article_count字段,这个方法简单,但是效率却不高

<!-- templates/blog/index.html -->
...
<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="category.html">{{ 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="row"> 标签内找到 <h4>分类</h4>这一标签,修改之后的 <ul> 标签,显示分类和分类下的文章数量。

 登陆后台管理系统,添加一个新的文章进行测试,添加完成之后刷新博客首页

image

 文章列表和分类列表都正确的显示出数据

总结

 博客首页的大概轮廓已经搭建完成,但是还有一些细节部分还需要调整,另外分页搜索功能放到后面完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容