7.5 Django Book ---未完待续

来源:互联网 发布:微动力cms 编辑:程序博客网 时间:2024/06/04 01:21

文章的连接
6.13
框架的概念
使用Python开发Web,最简单,原始和直接的办法是使用CGI标准,在1998年这种方式很流行。 现在从应用角度解释它是如何工作: 首先做一个Python脚本,输出HTML代码,然后保存成.cgi扩展名的文件,通过浏览器访问此文件

MVC 设计模式,模型-视图-控制器(MVC)
models.py 文件主要用一个 Python 类来描述数据表。 称为 模型(model) 。 运用这个类,你可以通过简单的 Python 的代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句

iews.py文件包含了页面的业务逻辑。 latest_books()函数叫做视图。

template 是 html 模板,它描述了这个页面的设计是如何的。 使用带基本逻辑声明的模板语言,如{% for book in book_list %}

推荐你读一下官方的 Python 教程,它可 以从 http://docs.python.org/tut/ 在线获得。 另外我们也推荐 Mark Pilgrims的 书Dive Into Python ( http://www.diveintopython.org/ )

安装的版本
官方发布版和Trunk版本,trunk,可以从django的subversion处获得,最后,如果你使用trunk,你要知道使用的是哪个trunk版本。 如果你去社区寻求帮助,或是为Django框架提供改进,知道你使用的版本号是非常重要的。 因此,当你到社区去求助,或者为 django 提供改进意见的时候,请时刻记住说明你正在使用的 django 的版本号。 如何知道你正在使用的 django 的版本号呢?进入djtrunk 目录,然后键入 svn info ,在输出信息中查看 Revision: (版本:) 后跟的数字。 Django在每次更新后,版本号都是递增的,无论是修复Bug、增加特性、改进文档或者是其他。 在一些Django社区中,版本号甚至成为了一种荣誉的象征,我从[写上非常低的版本号]开始就已经使用Djano了

开始一个项目
项目 是 Django 实例的一系列设置的集合,它包括数据库配置、Django 特定选项以及应用程序的特定设置。

新建一个目录的位置
1.在 Django 中,任何Python代码和web server的文档根(root)不应该放在一起,把代码放置在文档根目录之外的某些目录中,django-admin.py startproject mysite 表示在当前目录下创建新目录mysite

2.django-admin.py 的安装和路径安排在系统路径中的方式,方便以后使用,
安装Django的方式有两种,如果是setup.py 工具安装的 Django ,django-admin.py 应该已被加入了系统路径中,如果是一个trunk版本,django-admin原本在djtrunk/django/bin,需要手动加载到系统路径中去,这里又按照系统的不同进行分

linux (软连接): sudo ln -s /path/to/django/bin/django-admin.py /usr/local/bin/django-admin.py .

windows :加到path 路径下

服务器:用自带的服务器,准备发布产品之前,无需进行产品级 Web 服务器(比如 Apache)的配置工作。 开发服务器监测你的代码并自动加载它,这样你会很容易修改代码而不用重启动服务python manage.py runserver,在端口8000启动一个本地服务器, 并且只能从你的这台电脑连接和访问。 既然服务器已经运行起来了,现在用网页浏览器访问,http://127.0.0.1:8000/
默认情况下, runserver 命令在 8000 端口启动开发服务器,且仅监听本地连接。 要想要更改服务器端口的话,可将端口作为命令行参数传入:python manage.py runserver 8080这样子就可以实现允许非本地连接访问 ,如果在开发的时候,想要共享同一开发站点的话0.0.0.0 这个 IP 地址,告诉服务器去侦听任意的网络接口。python manage.py runserver 0.0.0.0:8000


from django.http import HttpResponsedef hello(request):    return HttpResponse("Hello world")

视图函数,每个视图函数至少要有一个参数,通常被叫作request。函数第一个参数的类型是HttpRequest;它返回一个HttpResponse实例。为了使一个Python的函数成为一个Django可识别的视图,它必须满足这两个条件。 (也有例外,但是我们稍后才会接触到!) 


URLconf:执行 django-admin.py startproject 时,该脚本会自动为你建了一份 URLconf(即 urls.py 文件)。 默认的urls.py会像下面这个样子,
Django 期望能从 ROOT_URLCONF 模块中找到urlpatterns变量 , 该变量定义了 URL 以及用于处理这些 URL 的代码之间的映射关系

from django.conf.urls.defaults import *urlpatterns = patterns('',   ('^hello/$', hello),)

搜索路径:
搜索路径指的是使用import语句的时候,python 要查找的目录清单,察看 python的路径的方式import sys,print sys.path,但是通常是不需要处理搜索路径的,后台会自动帮你处理好


URLpattern的语法:('^hello/$', hello),
模式包含了一个尖号(^)和一个美元符号($)。这些都是正则表达式符号,并且有特定的含义: 上箭头要求表达式对字符串的头部进行匹配,美元符号则要求表达式对字符串的尾部进行匹配,如果没有就会对所有的进行匹配
任何不匹配或尾部没有斜杠(/)的申请URL,将被重定向至尾部包含斜杠的相同字眼的URL,这个是受到setting中APPEND_SLASH项控制的,APPEND_SLASH”为”True”表示所有的url的默认添加斜杠,


根目录的使用方式
如果你在浏览器上,打http://127.0.0.1:8000/ 会报错404,因为即使是根目录也需要类似的操作,设定('^$',my_homepage_view)  


Django是处理请求的流程
1.开始都是起源于setting.py的文件,当你执行python manage.py runserver 命令的时候,脚本就会找到和manage.py同一个目录下的setting.py文件,告诉Django所有的配置信息,比如:其中最重要ROOT_URLCONF参数,比如 horizon.url 表示有一个horizon/url.py的文件 。
2 .当url 开始访问地址的时候,Django会根据ROOT_URLCONF里面的参数,找到对应的文件,逐一找到对应的URLpatterns,找到位置,找到后调用view函数,同时会把HttpRequest作为 第一个参数传进去,view 功能实现以后,需要返回一个返回一个HttpResponse,Djngo 把该对象 转换成 Web Response对象,里面有Http头和body


第二个视图,引入动态效果图,注意return HttpResponse(html) 里面的变量性质?
’URLconf和视图是松耦合的 ‘???是什么意思?

from django.http import HttpResponseimport datetimedef hello(request):    return HttpResponse("Hello world")def current_datetime(request):    now = datetime.datetime.now()    html = "<html><body>It is now %s.</body></html>" % now    return HttpResponse(html)

第三个视图 动态URL
1.使用通配符(wildcard URLpatterns)。正如我们之前提到过,一个URL模式就是一个正则表达式。因此,这里可以使用d+来匹配1个以上的数字(r'^time/plus/\d+/$', hours_ahead) d+来匹配1个以上的数字! 如果 是指匹配一个或两个数字,正则表达式的语法就是 \d{1,2},
r 表示的是一个原始字符串,不需要处理里面的转义字符串,如果你熟悉正则表达式,那么你应该已经了解,正则表达式也是用圆括号来从文本里 提取 数据的。???

from django.http import Http404, HttpResponseimport datetime#request 是HttpRequest 对象,offset是从匹配的url的提取出来的,/time/plus/3/里面的参数赋值给offsetdef hours_ahead(request, offset):    try:        offset = int(offset)#这会把这个字符串值转换为整数    except ValueError:        raise Http404()    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)    return HttpResponse(html)

URLpattern提供的是“适度但有用”级别的输入校验,所以不能用它作为可靠的教验装置!


在你视图的任何位置,临时插入一个 assert False 来触发出错页。 然后,你就可以看到局部变量和程序语句了,但是很多信息都是敏感的,它暴露了你 Python 代码的内部结构以及 Django 配置,因此Django 出错信息仅在 debug 模式下才会显现。 我们稍后 说明如何禁用 debug 模式。 现在,你只要知道 Django 服务器在你开启它时默认运行在 debug 模式就行了。


第四章 模板系统 (Template System)
在template 里面有几个需要理解的位置,
一个是变量(variable),例如 {{ person_name }}
一个是模板标签(template tag) 例如 {% if ordered_warranty %}
一个是filter过滤器的例子,例如{{ship_date|date:”F j, Y” }}它是一种最便捷的转换变量输出格式的方式。 我们将变量ship_date传递给date过滤器,同时指定参数”F j,Y”。date过滤器根据参数进行格式输出。 过滤器是用管道符(|)来调用的,具体可以参见Unix管道符???

<html><head><title>Ordering notice</title></head><body><h1>Ordering notice</h1><p>Dear {{ person_name }},</p><p>Thanks for placing an order from {{ company }}. It's scheduled toship on {{ ship_date|date:"F j, Y" }}.</p><p>Here are the items you've ordered:</p><ul>{% for item in item_list %}    <li>{{ item }}</li>{% endfor %}</ul>{% if ordered_warranty %}    <p>Your warranty information will be included in the packaging.</p>{% else %}    <p>You didn't order a warranty, so you're on your own when    the products inevitably stop working.</p>{% endif %}<p>Sincerely,<br />{{ company }}</p></body></html>

Django 中 使用模板系统基本方式如下,感觉是变量+html分开的方式
1.首先创建一个 Template 对象,

>>> from django import template>>> t = template.Template('My name is {{ name }}.')

2.调用render方法,传入一套变量context,他将返回一个模板的展现字符串,把之前模板中对应的地方都替换掉

>>> c = template.Context({'name': 'Adrian'})>>> print t.render(c)My name is Adrian.

python manage.py shell 和 python命令都会启动交互解释器,但是有点区别,python manage.py shell 会告诉Django使用哪个设置文件,也就是会自动帮你填充参数自动帮你处理DJANGO_SETTINGS_MODULE 这个参数 ,但是你也可以手动设置参数变量


模板渲染
Context()方法是表示 一系列变量和它们值的集合,Context 构造的参数是Python 字典数据类型
Template 对象 的 render() 方法,用来传递context来填充模板,并且把参数加进去,但是我们必须明白render()方法得到的是unicode 对象不是普通的python字符串对象

>>> from django.template import Context, Template>>> t = Template('My name is {{ name }}.')>>> c = Context({'name': 'Stephane'})>>> t.render(c)u'My name is Stephane.'

以下的例子解释了完整的过程

>>> from django.template import Template, Context>>> raw_template = """<p>Dear {{ person_name }},</p>...... <p>Thanks for placing an order from {{ company }}. It's scheduled to... ship on {{ ship_date|date:"F j, Y" }}.</p>...... {% if ordered_warranty %}... <p>Your warranty information will be included in the packaging.</p>... {% else %}... <p>You didn't order a warranty, so you're on your own when... the products inevitably stop working.</p>... {% endif %}...... <p>Sincerely,<br />{{ company }}</p>"""#创建一个template对象>>> t = Template(raw_template)>>> import datetime#我们创建一个 Context 对象, c 。Context 构造的参数是Python 字典数据类型>>> c = Context({'person_name': 'John Smith',...     'company': 'Outdoor Equipment',...     'ship_date': datetime.date(2009, 4, 2),...     'ordered_warranty': False})#最后通过render()方式传递参数给他>>> t.render(c)u"<p>Dear John Smith,</p>\n\n<p>Thanks for placing an order from OutdoorEquipment. It's scheduled to\nship on April 2, 2009.</p>\n\n\n<p>Youdidn't order a warranty, so you're on your own when\nthe productsinevitably stop working.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment</p>"

”’
?????
如果你是Python初学者,你可能在想为什么输出里有回车换行的字符(‘\n’ )而不是 显示回车换行? 因为这是Python交互解释器的缘故: 调用 t.render(c) 返回字符串, 解释器缺省显示这些字符串的 真实内容呈现,而不是打印这个变量的值。 要显示换行而不是 ‘\n’ ,使用 print 语句: print t.render(c) 。
”’


深度变量的查找,通过传递对象的方式,然后通过.符号去引用对象的属性,方法还有列表的形式

对象的属性的例子

>>> from django.template import Template, Context>>> person = {'name': 'Sally', 'age': '43'}>>> t = Template('{{ person.name }} is {{ person.age }} years old.')>>> c = Context({'person': person})>>> t.render(c)u'Sally is 43 years old.'

对象的方法的例子,注意这里调用方法时,并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的方法。

>>> from django.template import Template, Context>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')>>> t.render(Context({'var': 'hello'}))u'hello -- HELLO -- False'>>> t.render(Context({'var': '123'}))u'123 -- 123 -- True

访问列表索引,注意 Context({‘items’: [‘apples’, ‘bananas’, ‘carrots’]}),里面整体还是一个字典类型,只是字典的值是list 类型的,可以通过list下标的形式获取值!

>>> from django.template import Template, Context>>> t = Template('Item 2 is {{ items.2 }}.')>>> c = Context({'items': ['apples', 'bananas', 'carrots']})>>> t.render(c)u'Item 2 is carrots.'

句点查找可以深度嵌套,比如 下面的例子中{{person.name.upper }},调用的方式是这样子的{{person.name.upper}}

from django.template  import  Template,Context>>>person = {'name':'Sam','age':'78'}>t =template(“{{person.name.upper}}' ,his age is {{person.age}} year old." )>c = Context('person':person)>t.render(c)>>

方法调用行为???


上下文(context)对象,之前的Context()函数中添加一个字典 ,在初始化以后还是可以对这个对象进行增删改查,

from django.template import Contextc=context("foo":'bar')>>>c['foo']>>>c['newfoo']='newbar'>>>c['newfoo']>>newbar

基本的模板标签和过滤器注意点

注意点1 if里面无法同时有and 和 or ,下面是不合理的

{% if athlete_list and coach_list or cheerleader_list %}

注意点2 并没有 {% elif %} 标签, 请使用嵌套的{% if %} 标签来达成同样的效果:并且每一个if 需要有endif 关闭

{% if athlete_list %}    <p>Here are the athletes: {{ athlete_list }}.</p>{% else %}    <p>No athletes are available.</p>    {% if coach_list %}        <p>Here are the coaches: {{ coach_list }}.</p>    {% endif %}{% endif %}

注意点3 循环语句支持可选的{% empty %} 分句,可以定义当列表为空时的输出内容

{% for athlete in athlete_list %}    <p>{{ athlete.name }}</p>{% empty %}    <p>There are no athletes. Only computer programmers.</p>{% endfor %}

注意点 4 在每个{% for %}循环里有一个称为forloop 的模板变量。这个变量有一些提示循环进度信息的属性,该 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了counter() 和 counter 函数是相似的但是开始的位置是不同的,forloop.first 是一个boolean 值用来判定是不是第一次循环,

{% for item  in todo_list %}{% if forloop.first %}<li class="first">{% else %}<li><% endif %><p> {{ forloop.counter()}}:{{item }} </p>{% endfor %}

注意点 5 {% ifequal A B %} 和 {% endifequal %} 用来判定A,B是否相等,同时 还支持 {% else%} 标签,参数可以是 模板变量,字符串,整数和小数,但是不可以是 Python的字典类型、列表类型、布尔类型,

{% ifequal section "community" %}    <h1>Community</h1>{% else %}    <h1>No News Here </h1>{% endifequal %}

模板过滤器
使用方式
举例:{ name|lower }},显示的是{name }} 被过滤器lower以后的结果
常用的几个过滤器
addlashes:添加反斜杠到任何反斜杠,单引号,双引号前面,在处理js 的时候经常用到
date 把字符串参数的格式化,比如pub_date|date:"Fj,Y"


模板加载,Django 提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板,使用这个API 就需要把模板的保存位置告诉框架,设置的方式是在setting.py 里面的TEMPLATE_DIRS,该设置告诉 Django 的模板加载机制在哪里查找模板。 修改里面的内容如下,ps 记得加逗号,最安全就是使用以下的方法,__file__ 是找到当前的代码所在的 Python 模块文件名(setting.py),os.path.dirname(__file__) 取到对应的路径,os.path.join 表示的是添加这个路径

TEMPLATE_DIRS = (    os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),    #windows版本下的replace的方式)

修改函数,里面面使用了get_template() 自动的加载模板,并不是之前手动的打开路径

def current_datetime(request):    now = datetime.datetime.now()    t = get_template('current_datetime.html')    html = t.render(Context({'current_date': now}))    return HttpResponse(html)

render_to_response()
此函数的作用是让你一次性地载入某个模板文件,渲染它,然后将此作为 HttpResponse返回,用了这个函数以后,再需要导入 get_template(模板加载) 、 Template 、 Context (模板解析)和 HttpResponse函数(创建工作)了,
里面有几个参数,第一个参数是使用的模板名称。 第二个参数,那么该参数必须是为该模板创建 Context 时所使用的字典。 如果不提供第二个参数, render_to_response() 使用一个空字典


locals() 技巧,
此函数主要是节省代码,它囊括了函数执行到该时间点时所定义的一切变量,只要保证模板所预期的变量名称和变量名称相同就可以了,没有别的作用只是为了节省时间和代码

例子如下,注意,里面的current_date原本名字叫做now 

def current_datetime(request):    current_date = datetime.datetime.now()    return render_to_response('current_datetime.html', locals())

include 模板标签
include是”模板加载机制的内建模板标签”: {% include %},表示可以使用其他模板的内容,例如{% include 'nav.html' %} 加载的是 "TEMPLATE_DIRS 的模板目录+模板的文件名"下面的路径

原创粉丝点击