本渣渣不专注技术,只专注使用技术,不是一个资深的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个人博客开发十 | 博客首页开发二
我想问一下{%if category == big.slug %}中的category是从哪来的,非常感谢