Django3.0+Python3.8+MySQL8.0 个人博客搭建十一|博客首页开发(二)

本节,写的代码量有点大,不要慌,主要是理解,渲染数据的逻辑,不要纠结于局部。

【提示】——重点领悟 用户请求、路由、视图、自定义模板标签的关系,只要理解了这几个过程的逻辑和联系,前端写再多的代码,都不会感觉到慌乱

一、理论讲堂

视图函数(类),简称视图,是一个简单的 Python 函数(类),它接收 Web 请求并且返回 Web 响应。响应可以是一个网页的 HTML 内容,一个重定向,一个404错误,一个 XML 文档,或者一张图片,甚至一个文件。无论视图本身包含什么逻辑,都要返回响应。代码书写位置无要求,只要它在你当前项目目录下面。除此之外没有更多的要求——可以说 “没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中

正确的流程

  1. 分析前端代码
  2. 配置路由
  3. 书写视图逻辑

Django 工作原理是:

用户发出 http 请求 -> 匹配路由 -> 进入视图 -> 根据用户请求在视图内编写逻辑 -> 把渲染后的 html 代码返给浏览器 -> 浏览器解析后呈现给用户

  • 用户请求:就是 url(网址)
  • 路由:Django 根据 用户请求的地址,来判断用户是干啥的,把任务交给指定的视图函数去干活
  • 视图:接收到路由委派的任务后,开始操作数据库,增、删、查,基本就这些个活,干好后,把渲染后的thml交给浏览器,浏览器解析后展示给用户要看的东东

下面自上而下,自左而右,分块来渲染数据,只捡重要的几块分区,在结构整理中的四个大区为主,没有提到的数据渲染,可以仿照其它功能实现,下边不解释,直接贴代码,重点通过代码看渲染数据的方法和逻辑

推荐学习:django 的模板语言template ,自定义过滤器,自定义标签,模板继承

二、导航栏

个人理解:自定义模版标签,和(view)视图的区别就是不需要接收 request 请求,只需要在模板也即前端页面接收参数,返回需要的数据进行展示即可。也就意味着,除了需要和用户交互的内容,比如用户给某篇章点赞,需要使用 Jquery + ajax 实现无刷新给页面喜欢数量加一,这个就需要 Jquery 接收到用户点击行为后,AJAX 携带信息给指定路由发出请求,视图接收到请求,把处理结果返给 AJAX 实现无数刷新地更新喜欢量。只要不涉及交互,的数据请求都可以放在 Templatetags 处理前端需要展示的数据

更多自定义过滤函数装饰器:官方文档

fswy app中创建templatetags目录,新建 blog_tags.py文件

fswy -> templatetags -> blog_tags.py

# 创建了新的tags标签文件后必须重启服务器

from django import template
from ..models import Article, Category, Tag, Carousel, FriendLink, BigCategory, Activate, Keyword
from django.db.models.aggregates import Count
from django.utils.html import mark_safe
import re

# 注册自定义标签函数
register = template.Library()

# 获取导航条大分类查询集
@register.simple_tag
def get_bigcategory_list():
    '''返回大分类列表'''
    return BigCategory.objects.all()

# 返回文章分类查询集
@register.simple_tag
def get_category_list(id):
    '''返回小分类列表'''
    return Category.objects.filter(bigcategory_id=id)

templatetags:

必须写的头部

from django import template
# 注册自定义标签函数
register = template.Library()

blog ->templates -> base.html

头部引入文件,static静态文件、blog_tags 自定义模板标签,记得无论那个页面只要用到里边的函数都要在头部引入

{% load static %}
{% load blog_tags %}
<!DOCTYPE HTML>
<html>

导航栏渲染数据

找到<div id="nav-header" class="navbar">

将div里href,src等静态路径都改为动态路径

将变量通过{{ }}传入

blog ->templates -> base.html

<!--导航条-->
<div id="nav-header" class="navbar">
    <ul class="nav">
        <!--获取一级分类信息-->
        {% get_bigcategory_list as bigcategory %}
        <li id="menu-item-44"
            class="menu-item menu-item-type-custom menu-item-object-custom {% if not category %}current-menu-item current_page_item{% endif %} menu-item-home menu-item-44"><a
                href="/">首页</a></li>

        <!--导航条一级分类渲染-->
        {% for big in bigcategory %}

            <!--获取二级分类信息-->
            {% get_category_list big.id as cate %}

            <!--如果一级分类下有二级分类则进行渲染-->
            {% if cate %}
                <li id="menu-item-14"
                        class="menu-item menu-item-type-taxonomy menu-item-object-category {% if category == big.slug %}current-menu-item {% endif %} menu-item-has-children menu-item-14">
                        <a href="{% url 'blog:category' big.slug '' %}">{{ big.name }}</a>
                            <ul class="sub-menu">
                                <!--导航条二级分类渲染-->
                                {% for c in cate %}
                                        <li id="menu-item-19" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-19"><a href="{% url 'blog:category'  big.slug   c.slug  %}">{{ c.name }}</a></li>
                                {% endfor %}
                            </ul>
                </li>

            <!--无二级分类的一级分类渲染-->
            {% else %}
                <li id="menu-item-851" class="menu-item menu-item-type-post_type menu-item-object-page {% if category == big.slug %}current-menu-item {% endif %} menu-item-851"><a href="{% url 'blog:category' big.slug '' %}">{{ big.name }}</a></li>
            {% endif %}
        {% endfor %}
        <!--导航条结束-->

        <!--搜索框-->
        <!--目前搜索框功能感觉没必要没做-->
        <li style="float:right;">
            <div class="toggle-search"><i class="fa fa-search"></i></div>
            <div class="search-expand" style="display: none;">
                <div class="search-expand-inner">
                    <form method="get" class="searchform themeform"
                          onsubmit="location.href='/?s=' + encodeURIComponent(this.s.value).replace(/%20/g, '+'); return false;"
                          action="/">
                        <div><input type="ext" class="search" name="s" onblur="if(this.value=='')this.value='search...';"
                                    onfocus="if(this.value=='search...')this.value='';" value="search..."></div>
                    </form>
                </div>
            </div>
        </li>
        <!--搜索框结束-->

    </ul>
</div>
<!--导航条结束-->

三、幻灯片

fswy -> templatetags -> blog_tags.py

# 获取滚动的大幻灯片查询集、获取左侧的幻灯片查询集,这两个部分用的图片是一样的
@register.simple_tag
def get_carousel_index():
    return Carousel.objects.filter(number__lte=5)

在数据库内给幻灯片添加一些图片在这里插入图片描述

blog ->templates -> index.html

<!--幻灯片 -->
<div id="wowslider-container1">
     <div class="ws_images">
         <ul>
             {% get_carousel_index as carousels %}
             {% for carousel in carousels %}
             <li>
                 <a target="_blank" href="{{ carousel.url }}" title="{{ carousel.context }}">
                     <img src="{{ carousel.img_url }}" title="{{ carousel.title }}" alt="{{ carousel.title}}" />
                 </a>
             </li>
             {% endfor %}
         </ul>
     </div>
     <div class="ws_thumbs">
         <div>
             {% get_carousel_index as carousels %}
             {% for carousel in carousels %}
             <a target="_blank" href="#" title="{{carousel.title}}">
                 <img src="{{ carousel.img_url }}" /></a>
             {%  endfor %}
         </div>
     </div>
     <div class="ws_shadow"></div>
 </div>
 <!--幻灯片结束 -->

运行项目,观看效果

在这里插入图片描述

四、热门文章

fswy -> templatetags -> blog_tags.py

# 获取热门排行数据查询集,参数:sort 文章类型, num 数量
@register.simple_tag
def get_article_list(sort=None, num=None):
    '''获取指定排序方式和指定数量的文章'''
    if sort:
        if num:
            return Article.objects.order_by(sort)[:num]
        return Article.objects.order_by(sort)
    if num:
        return Article.objects.all()[:num]
    return Article.objects.all()

blog ->templates -> index.html

<!--热门文章 -->
<div>
    <div class="left-ad" style="clear: both;background-color: #fff; width: 30%;float: left;margin-right:2%;"></div>
    <div class="hot-posts">
        <h2 class="title">热门排行</h2>
        <ul>
            {% get_article_list 'views' 5 as hot_article  %}
            {% for hot in hot_article %}
            <li>
                <p>
                    <span class="muted">
                        <a href="javascript:;" data-action="ding" data-id="{{ hot.id}}" id="Addlike" class="action">
                        <i class="fa fa-heart-o"></i>
                        <span class="count">{{ hot.loves }}</span> 喜欢</a>
                    </span>
                </p>
                <span class="label label-1">{{ forloop.counter }}</span>
                <a href="/article/{{ hot.slug }}" title="{{ hot.title}}">{{ hot.title }}</a></li>
        {% endfor %}
        </ul>
    </div>
</div>
<!--热门文章 -->

在这里插入图片描述

、文章列表

blog ->templates -> index.html

<!--文章列表 -->
{% for article in page_obj %}
<article class="excerpt">
    <header>
        <a class="label label-important" href="/category/{{ article.category.bigcategory.name }}/{{ article.category.name|lower }}">{{ article.category.name }}<i class="label-arrow"></i></a>
        <h2>
            <a target="_blank" href="/article/{{ article.slug }}" title="{{ article.title }}">{{ article.title }} </a>
        </h2>
    </header>
    <div class="focus">
        <a target="_blank" href="/article/{{ article.slug }}">
            <img class="thumb" src="{{ article.img_link }}" alt="{{ article.title }}" /></a>
    </div>
    <span class="note">{{ article.summary }}</span>
    <p class="auth-span">
        <span class="muted"><i class="fa fa-user"></i> <a href="/author/{{ article.author }}">{{ article.author }}</a></span>
        <span class="muted"><i class="fa fa-clock-o"></i>{{ article.create_date|date:'Y-m-d' }}</span>    <span class="muted"><i class="fa fa-eye"></i>{{ article.views }}浏览</span>
        <span class="muted"><i class="fa fa-comments-o"></i> <a target="_blank" href="/article/{{ article.slug }}#comments">评论</a></span>
        <span class="muted"><a href="javascript:;" data-action="ding" data-id="{{ article.id }}" id="Addlike" class="action"><i class="fa fa-heart-o"></i>
        <span class="count">{{ article.loves }}</span>喜欢</a></span>
    </p>
</article>
{% empty %}
<div class="no-post">暂时还没有发布的文章!</div>
{% endfor %}
<!--文章列表结束 -->

这里没用到自定义模板标签

在这里插入图片描述

六、侧边栏

(一)、侧边栏-联系方式

blog ->templates -> base_right.html

首先个人联系方式的矢量图没显示出来,需要引入一下矢量图文件

在这里插入图片描述

首先去awesome官网下载 font-awesome-4.7.0或者拷贝Github项目中的矢量文件,然后把文件放入 static 静态文件中,然后在

blog ->templates -> base.html

中的head标签引入头部文件的地方导入路径

<link rel='stylesheet' id='style-css' href='{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}' type='text/css' media='all'/>

注意

这里引用的是动态路径,后面会将前面的静态路径全部置换为动态路径。

效果图

在这里插入图片描述

(二)、侧边栏-热门专题轮播图

fswy -> templatetags -> blog_tags.py

# 获取右侧栏热门专题幻灯片查询集
@register.simple_tag
def get_carousel_right():
    return Carousel.objects.filter(number__gt=5, number__lte=10)

注意

Carousel表前五个是首页大轮播图、后五个是热门专题轮播图

blog ->templates -> base_right.html

不要忘记在头部引入自定义模板标签

{% load blog_tags %}

热门专题轮播图

<!-- 热门专题-->
 <div class="title"><h2>热门专题</h2></div><!-- meta slider -->
 <div style="width: 100%;" class="metaslider metaslider-nivo metaslider-2698 ml-slider meta-slider">
     <div id="metaslider_container_2698">
         <div class='slider-wrapper theme-bar'>
             <div class='ribbon'></div>
             <div id='metaslider_2698' class='nivoSlider'>
                 {% get_carousel_right as carousels %}
                 {% for carousel in carousels %}
                 <a href="{{ carousel.url }}" target="_blank">
                     <img src="{{ carousel.img_url }}" height="300" width="320" data-title="{{ carousel.content }}" title="{{ carousel.title }}" alt="{{ carousel.title }}" class="slider-2698 slide-1720" />
                 </a>
                 {% endfor %}
	
	     	  </div>
	   	 </div>
	</div>
<!--热门专题结束 -->

在这里插入图片描述

(三)、侧边栏-文章归档

fswy -> templatetags -> blog_tags.py

# 获取归档文章查询集
@register.simple_tag
def get_data_date():
    '''获取文章发表的不同月份'''
    article_dates = Article.objects.datetimes('create_date', 'month', order='DESC')
    return article_dates

blog ->templates -> base_right.html

<!--文章归档 -->
<div class="widget widget_archive">
    <div class="title"><h2>文章归档</h2></div>
    {% get_data_date as data_date %}
    <ul>
        {% if data_date %}
            {% for date in data_date %}
        <li><a href='{% url 'blog:date' date|date:'Y' date|date:'m' %}'>{{ date|date:'Y-m' }}</a></li>
            {% endfor %}
        {% else %}
            <div>近期没有发表过文章</div>
        {% endif %}
    </ul>
</div>
<!--文章归档结束 -->

在这里插入图片描述

(四)、侧边栏-猜你喜欢

fswy -> templatetags -> blog_tags.py

# 获取热门排行数据查询集,参数:sort 文章类型,num 数量
# 文章相关标签函数,和热门文章使用同一个函数
@register.simple_tag
def get_article_list(sort=None, num=None):
    '''获取指定排序方式和指定数量的文章'''
    if sort:
        if num:
            return Article.objects.order_by(sort)[:num]
        return Article.objects.order_by(sort)
    if num:
        return Article.objects.all()[:num]
    return Article.objects.all()

注意

和热门文章使用的是同一个函数get_article_lis

blog ->templates -> base_right.html

<!--猜你喜欢 -->
 <div class="widget d_postlist">
     <div class="title"><h2>猜你喜欢</h2></div>
     <ul>
         {%  get_article_list 'loves' 6 as hot_tag %}
         {% for hot in hot_tag %}
         <li>
             <a href="/article/{{ hot.slug }}" title="{{ hot.title }}" >
             <span class="thumbnail">
             <img src="{{ hot.img_link }}" alt="{{ hot.title }}" />
             </span>
             <span class="text">{{ hot.title }}</span>
             <span class="muted">{{ hot.create_date|date:'Y-m-d' }}</span>
             <span class="muted">{{ hot.loves }}喜欢</span>
             </a>
         </li>

         {% endfor %}
     </ul>
 </div>
 <!--猜你喜欢结束 -->

在这里插入图片描述

(五)、侧边栏-标签云

fswy -> templatetags -> blog_tags.py

# 返回标签查询集
@register.simple_tag
def get_tag_list():
    """返回标签列表"""
    return Tag.objects.annotate(total_num=Count('article')).filter(total_num__gt=0)

blog ->templates -> base_right.html

<!--标签云 -->
<div class="widget d_tag">
    <div class="title"><h2>标签云</h2></div>
    <div class="d_tags">
        {% get_tag_list as tags %}
        {% for tag in tags %}

        <!--tag.total_num直接获得标签次标签下的文章数 -->
        <a title="{{ tag.total_num }}个话题" href="{% url 'blog:tag' tag.name %}">{{ tag.name }}({{ tag.total_num }})</a>
        {% endfor %}
    </div>
</div>
<!--标签云结束-->

(六)、侧边栏-友情链接

fswy -> templatetags -> blog_tags.py

# 返回活跃的友情链接查询集
@register.simple_tag
def get_friends():
    """获取活跃的友情链接"""
    return FriendLink.objects.filter(is_show=True, is_active=True)

blog ->templates -> base_right.html

<!--友情链接 -->
<div class="widget widget_links">
    <div class="title"><h2>友情链接</h2></div>
        {% get_friends as friends %}
        <ul class='xoxo blogroll'>
            {% if friends %}
                {% for friend in friends %}
            <li><a href="http://www.99banzou.com" target="_blank">99伴奏网</a></li>
                {% endfor %}
            {% else %}
                <div>&nbsp;&nbsp;暂无友链,欢迎来战</div>
            {% endif %}
        </ul>
</div>
<!--友情链接结束 -->

友情提示

如果发现有表达错误,或者知识点错误,或者搞不懂的地方,请及时留言,可以在评论区互相帮助,让后来者少走弯路是我的初衷。我也是一步步摸着石头走过来的,深知网络上只言片语的图文教程,给初学者带来的深深困扰。

建议

在对项目结构不太熟悉时,参照完整源码少走弯路

原创文章 214 获赞 359 访问量 89万+

猜你喜欢

转载自blog.csdn.net/yxys01/article/details/105825729