本节,写的代码量有点大,不要慌,主要是理解,渲染数据的逻辑,不要纠结于局部。
【提示】——重点领悟 用户请求、路由、视图、自定义模板标签的关系,只要理解了这几个过程的逻辑和联系,前端写再多的代码,都不会感觉到慌乱
一、理论讲堂
视图函数(类),简称视图,是一个简单的 Python 函数(类),它接收 Web 请求并且返回 Web 响应。响应可以是一个网页的 HTML 内容,一个重定向,一个404错误,一个 XML 文档,或者一张图片,甚至一个文件。无论视图本身包含什么逻辑,都要返回响应。代码书写位置无要求,只要它在你当前项目目录下面。除此之外没有更多的要求——可以说 “没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中
正确的流程
- 分析前端代码
- 配置路由
- 书写视图逻辑
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> 暂无友链,欢迎来战</div>
{% endif %}
</ul>
</div>
<!--友情链接结束 -->
友情提示
如果发现有表达错误,或者知识点错误,或者搞不懂的地方,请及时留言,可以在评论区互相帮助,让后来者少走弯路是我的初衷。我也是一步步摸着石头走过来的,深知网络上只言片语的图文教程,给初学者带来的深深困扰。
建议
在对项目结构不太熟悉时,参照完整源码少走弯路