本渣渣不专注技术,只专注使用技术,不是一个资深的coder,是一个不折不扣的copier |
本节,写的代码量有点大,不要慌,主要是理解,渲染数据的逻辑,不要纠结于局部。
【提示】——重点领悟 用户请求、路由、视图、自定义模板标签的关系,只要理解了这几个过程的逻辑和联系,前端写再多的代码,都不会感觉到慌乱
1、理论讲堂
视图函数(类),简称视图,是一个简单的 Python 函数(类),它接收 Web 请求并且返回 Web 响应。响应可以是一个网页的 HTML 内容,一个重定向,一个404错误,一个 XML 文档,或者一张图片,甚至一个文件。无论视图本身包含什么逻辑,都要返回响应。代码书写位置无要求,只要它在你当前项目目录下面。除此之外没有更多的要求——可以说 "没有什么神奇的地方"。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中
正确的流程,应该是,先分析前端代码,来配置路由,然后书写视图逻辑
因为 Django 工作原理是:
用户发出 http 请求 -> 匹配路由 -> 进入视图 -> 根据用户请求在视图内编写逻辑 -> 把渲染后的 html 代码返给浏览器 -> 浏览器解析后呈现给用户
用户请求:就是 url(网址)
路由:Django 根据 用户请求的地址,来判断用户是干啥的,把任务交给指定的视图函数去干活
视图:接收到路由委派的任务后,开始操作数据库,增、删、查,基本就这些个活,干好后,把渲染后的thml交给浏览器,浏览器解析后展示给用户要看的东东
下面自上而下,自左而右,分块来渲染数据,只捡重要的几块分区,在结构整理中的四个大区为主,没有提到的数据渲染,可以仿照其它功能实现,下边不解释,直接贴代码,重点通过代码看渲染数据的方法和逻辑
推荐学习:django 的模板语言template ,自定义过滤器,自定义标签,模板继承
2、导航栏
blog ->templates -> base.html
头部引入文件,staticfiles静态文件、blog_tags 自定义模板标签,记得无论那个页面只要用到里边的函数都要在头部引入
{% load staticfiles %}
{% load blog_tags %}
<!DOCTYPE HTML>
<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>
<!--导航条结束-->
blog -> 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()
个人理解:自定义模版标签,和(view)视图的区别就是不需要接收 request 请求,只需要在模板也即前端页面接收参数,返回需要的数据进行展示即可。也就意味着,除了需要和用户交互的内容,比如用户给某篇章点赞,需要使用 Jquery + ajax 实现无刷新给页面喜欢数量加一,这个就需要 Jquery 接收到用户点击行为后,AJAX 携带信息给指定路由发出请求,视图接收到请求,把处理结果返给 AJAX 实现无数刷新地更新喜欢量。只要不涉及交互,的数据请求都可以放在 Templatetags 处理前端需要展示的数据
更多自定义过滤函数装饰器:官方文档
3、幻灯片
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.content }}">
<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>
blog -> templatetags -> blog_tags.py
# 获取滚动的大幻灯片查询集、获取左侧的幻灯片查询集,这两个部分用的图片是一样的
@register.simple_tag
def get_carousel_index():
return Carousel.objects.filter(number__lte=5)
在数据库内给幻灯片添加一些图片
运行项目,观看效果
4、热门文章
blog ->templates -> index.html
<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>
blog -> 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()
5、文章列表
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" width="200" height="123" 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 %}
这里没用到自定义模板标签
6、侧边栏
blog ->templates -> base_right.html
首先个人联系方式的矢量图没显示出来,需要引入一下矢量图文件
首先去awesome官网下载 font-awesome-4.7.0或者拷贝Github项目中的矢量文件,然后把文件放入 static 静态文件中,然后在
blog ->templates -> base.html中的head标签引入头部文件的地方导入路径
<link rel='stylesheet' id='page-list-style-css' href='/static/font-awesome-4.7.0/css/font-awesome.min.css' type='text/css' media='all' />
侧边栏热门专题轮播图
blog ->templates -> base_right.html
不要忘记在头部引入自定义模板标签
{% load blog_tags %}
热门专题轮播图
<div class="widget widget_metaslider_widget">
<!--热门专题-->
<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>
<!--热门专题结束-->
<script type="text/javascript">
var metaslider_2698 = function ($) {
$('#metaslider_2698').nivoSlider({
boxCols: 7,
boxRows: 5,
pauseTime: 3000,
effect: "random",
controlNav: false,
directionNav: true,
pauseOnHover: true,
animSpeed: 600,
prevText: "<",
nextText: ">",
slices: 15,
manualAdvance: false
});
};
var timer_metaslider_2698 = function () {
var slider = !window.jQuery ? window.setTimeout(timer_metaslider_2698, 100) : !jQuery.isReady ? window.setTimeout(timer_metaslider_2698, 1) : metaslider_2698(window.jQuery);
};
timer_metaslider_2698();
</script>
</div>
<!--// meta slider-->
</div>
blog -> 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
<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>
<!--文章归档结束-->
blog -> 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 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>
<!--猜你喜欢结束-->
blog -> templatetags -> blog_tags.py
# 文章相关标签函数,和热门文章使用同一个函数
@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 -> 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>
<!--标签云结束-->
<!--友情链接-->
<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="{{ friend.link }}" target="_blank">{{ friend.name }}</a></li>
{% endfor %}
{% else %}
<div> 暂无友链,欢迎来战</div>
{% endif %}
</ul>
</div>
<!--友情链接结束-->
storm -> templatetags -> blog_tags.py
# 获取文章标签信息,参数文章ID
@register.simple_tag
def get_article_tag(article_id):
return Tag.objects.filter(article=article_id)
【友情提示】——如果发现有表达错误,或者知识点错误,或者搞不懂的地方,请及时留言,可以在评论区互相帮助,让后来者少走弯路是我的初衷。我也是一步步摸着石头走过来的,深知网络上只言片语的图文教程,给初学者带来的深深困扰。
【建议】——在对项目结构不太熟悉时,参照完整源码少走弯路
转载请注明: StormSha » Django个人博客开发十 | 博客首页开发二