公司动态
【2014-08-18】Django自学笔记:模板
[历史归档]本文原发布于 cstriker1407.info 个人博客内容为历史存档仅供参考。发布时间2014-08-18 标题Django自学笔记模板分类编程 / web / Django 标签模板·djangoDjango自学笔记模板备注添加模板支持模板原理代码Django加载模板文件模板语法.运算符if elseand or notforforloop多层循环注释简化后的模板加载代码Include标签模板{% block %}{{block.super}}:备注最近自学了下Django这里笔记下学习记录。备注1 学习记录中的代码和资料参考自网络教程【 http://djangobook.py3k.cn/2.0/ 】和【 http://www.djangobook.com/en/2.0/ 】版权归原作者所有。2 小弟第一次接触到Django本笔记可能有错误还请各位路过的大牛们给予指点。3 由于教程年代比较久远了而且Django不同版本改动很大这里作者的学习笔记是基于【python2.7.8 django1.6.5】实现的。4 由于时间关系学习记录里有的地方记得比较乱以后有时间再整理下吧。添加模板支持模板原理代码首先看下Django是如何支持模板的开启一个新的CMD然后输入如下命令D:\Documents\pythons\HelloDjangopython manage.py shell Python2.7.8(default,Jun302014,16:08:48)[MSC v.150064bit(AMD64)]on win32Typehelp,copyright,creditsorlicenseformore information.(InteractiveConsole)fromdjangoimporttemplatettemplate.Template(My name is {{ name }}.)ctemplate.Context({name:Adrian})printt.render(c)My nameisAdrian.ctemplate.Context({name:Fred})printt.render(c)My nameisFred.ctemplate.Context()printt.render(c)My nameis.因此可知在Python代码中使用Django模板的最基本方式如下创建一个 Template 对象将模板代码放入一个 string 中作为参数。调用模板(template)对象的 render() 方法把一组变量作为上下文(context)传入。这么做将会把模板(template)展开将所有变量(variables)和标签(tags)都赋予相应的值并作为 string 返回。Django加载模板文件由于Django版本间有差异这里作者使用的是1.6.5版本这里作者笔记下如何加载模板文件首先在HelloDjango文件夹下新建一个文件夹【templates】目录结构为【D:\Documents\pythons\HelloDjango\HelloDjango emplates】然后在templates文件夹下新建一个文件【HelloTemplates.html】内容很简单Hello Templates如下图然后添加URL解析代码如下图之后有很重要的一个步骤打开settings.py在INSTALLED_APPS中加入一行如下图然后刷新下网页就可以了这里笔记下为什么这样放置template在看教程时发现很多人在settings.py里面添加变量TEMPLATE_DIRS来实现tempate的查找这里我们看下网址【 https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-TEMPLATE_DIRS 】中TEMPLATE_DIRS Default: () (Empty tuple) List of locations of the template source files searched by django.template.loaders.filesystem.Loader, in search order. Note that these paths should use Unix-style forward slashes, even on Windows. See The Django template language.即该变量表示了如何要查找template的目录这里我们继续看网址【 https://docs.djangoproject.com/en/1.6/ref/templates/api/#django.template.loaders.filesystem.Loader 】class app_directories.Loader Loads templates from Django apps on the filesystem. For each app in INSTALLED_APPS, the loader looks for a templatessubdirectory. If the directory exists, Django looks for templates in there. This means you can store templates with your individual apps. This also makes it easy to distribute Django apps with default templates. For example, for this setting: INSTALLED_APPS (myproject.polls, myproject.music) ...then get_template(foo.html) will look for foo.html in these directories, in this order: ?/path/to/myproject/polls/templates/ ?/path/to/myproject/music/templates/ ... and will use the one it finds first.因此可以通过在INSTALLED_APPS中注册新的APP的方法来实现查找不过这里需要把template文件放到templates文件夹中这里我们为了简单就采取这种方式。模板语法.运算符通过.运算符可以方便的调用到字典变量ttemplate.Template({{ person.name }} is {{ person.age }} years old.)ctemplate.Context({person:{name:Sally,age:43}})t.render(c)uSally is 43 years old.也可以访问类的成员变量classPerson(object):...def__init__(self,first_name,last_name):...self.first_name,self.last_namefirst_name,last_name;...ttemplate.Template(Hello, {{ person.first_name }} {{ person.last_name }}.)ctemplate.Context({person:Person(John,Smith)})t.render(c)uHello, John Smith.也可以调用到无参数的方法ttemplate.Template({{ var }} -- {{ var.upper }} -- {{ var.isdigit }})t.render(template.Context({var:hello}))uhello -- HELLO -- Falset.render(template.Context({var:123}))u123 -- 123 -- True也可用于访问列表索引ttemplate.Template(Item 2 is {{ items.2 }}.)ctemplate.Context({items:[apples,bananas,carrots]})t.render(c)uItem 2 is carrots.句点查找规则可概括为当模板系统在变量名中遇到点时按照以下顺序尝试进行查找1 字典类型查找 比如 foo[bar] ) 2 属性查找 (比如 foo.bar ) 3 方法调用 比如 foo.bar() ) 4 列表类型索引查找 (比如 foo )if elseHelloTemplates.html:{% if today_is_weekend %}pWelcome to the weekend!/p{% else %}pGet back to work./p{% endif %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[today_is_weekend]True;htmlt.render(c);returnHttpResponse(html);and or notHelloTemplates.html:pnum1:{{num1}};num2:{{num2}};num3:{{num3}};num4:{{num4}};/p{% if num1 1 or num2 2 %}pnum1 1 or num2 2/p{% endif %} {% if num1 1 and num3 3 %}pnum1 1 and num3 3/p{% endif %} {% if not num4 4 %}pnum4 ! 4/p{% endif %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[num1]1;c[num2]2;c[num3]3;c[num4]5;htmlt.render(c);returnHttpResponse(html);输出forreversed使得该列表被反向迭代。在执行循环之前先检测列表的大小是一个通常的做法当列表为空时输出一些特别的提示。HelloTemplates.html:{% for athlete in athlete_list %} {{ athlete.name }}br/{% empty %} There are no athletes. Only computer programmers.br/{% endfor %}p/p{% for athlete in athlete_list reversed %} {{ athlete.name }}br/{% endfor %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[athlete_list][{name:xiaoming},{name:xiaoqiang},{name:xiaoli}];htmlt.render(c);returnHttpResponse(html);输出forloopHelloTemplates.html:{% for athlete in athlete_list %}p{{ athlete.name }}/pforloop.first:{{forloop.first}}br/forloop.last :{{forloop.last }}br/forloop.counter:{{forloop.counter}}br/forloop.counter0 :{{forloop.counter0 }}br/forloop.revcounter :{{forloop.revcounter }}br/forloop.revcounter0 :{{forloop.revcounter0 }}br/{% endfor %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[athlete_list][{name:xiaoming},{name:xiaoqiang},{name:xiaoli}];htmlt.render(c);returnHttpResponse(html);输出多层循环HelloTemplates.html:{% for country in countries %}table{% for city in country.city_list %}trtdCountry #{{ forloop.parentloop.counter }}/tdtdCity #{{ forloop.counter }}/tdtd{{ city }}/td/tr{% endfor %}/table{% endfor %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[countries][{city_list:[beijing,shanghai,nanjing]},{city_list:[New York,LA]}];htmlt.render(c);returnHttpResponse(html);输出注释{# This is a comment #} {% comment %} This is a multi-line comment. {% endcomment %}简化后的模板加载代码HelloTemplates.html:Hello My Blog Is {{myblog}}.MyViewControllers.py:fromdjango.shortcutsimportrender;defshowtemplates(request):returnrender(request,HelloTemplates.html,{myblog:http://116.62.110.235/blog/})Include标签首先新建一个文件夹navs在里面新建一个html文件HelloNav.html内容为pYOU ARE IN {{navtitle}}/p如下图HelloTemplates.html:{% include navs/HelloNav.html %}pThe Content IS:br/{{content}}/pMyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[navtitle]Hello This Is Title;c[content]Hello This Is Content;htmlt.render(c);returnHttpResponse(html);输出模板{% block %}{% block %}标签告诉模板引擎子模板可以重载这些部分。 每个{% block %}标签所要做的是告诉模板引擎该模板下的这一块内容将有可能被子模板覆盖。首先新建一个父模板文件base.html内容如下{{ title }}h1This Is Content A/h1{% block contentA %}pHello This Is The ContentA In base.html./p{% endblock %}h1This Is Content B/h1{% block contentB %}pHello This Is The ContentB In base.html./p{% endblock %}h1This Is Content C/h1{% block contentC %}{% endblock %}然后我们修改HelloTemplates.html让其继承自base.html{% extends base.html %} {% block contentA %} This Is The ContentA In HelloTemplates.html {% endblock %} {% block contentC %} {{content}} {% endblock %} {% block contentD %} This Is The ContentD In HelloTemplates.html {% endblock %}MyViewControllers.py:defshowtemplates(request):ttemplate.loader.get_template(HelloTemplates.html);ctemplate.Context();c[title]Hello This Is Title;c[content]Hello This Is Content;htmlt.render(c);returnHttpResponse(html);如下图各个block之间的关系{{block.super}}:base.html:{{ title }}h1This Is Content A/h1{% block contentA %}pHello This Is The ContentA In base.html./p{% endblock %}HelloTemplates.html:{% extends base.html %} {% block contentA %} {{ block.super }} This Is The ContentA In HelloTemplates.html {% endblock %}输出备注一些有意思的评注