django框架(1)

一什么是web框架?

框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。

对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端

import socket
 
def handle_request(client):
 
    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    client.send("

Hello, yuan

".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()

 最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

      正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

这个接口就是WSGI:Web Server Gateway Interface。

 

第一步

 1 from wsgiref.simple_server import make_server
 2  
 3  
 4 def application(environ, start_response):
 5     start_response('200 OK', [('Content-Type', 'text/html')])
 6     return [b'

Hello, web!

'] 7 8 9 httpd = make_server('', 8080, application) 10 11 print('Serving HTTP on port 8000...') 12 # 开始监听HTTP请求: 13 httpd.serve_forever()
View Code
 1 整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
 2 我们只负责在更高层次上考虑如何响应请求就可以了。
 3  
 4 application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。
 5  
 6 Python内置了一个WSGI服务器,这个模块叫wsgiref   
 7      
 8      
 9 application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
10  
11         //environ:一个包含所有HTTP请求信息的dict对象;
12          
13         //start_response:一个发送HTTP响应的函数。
14  
15 在application()函数中,调用:
16  
17 start_response('200 OK', [('Content-Type', 'text/html')])
18  
19 就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
20 start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
21 个Header用一个包含两个str的tuple表示。
22  
23 通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。
24  
25 然后,函数的返回值b'

Hello, web!

'将作为HTTP响应的Body发送给浏览器。 26 27 有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML, 28 通过start_response()发送Header,最后返回Body。  
View Code

第二步

 1 print(environ['PATH_INFO'])
 2     path=environ['PATH_INFO']
 3     start_response('200 OK', [('Content-Type', 'text/html')])
 4     f1=open("index1.html","rb")
 5     data1=f1.read()
 6     f2=open("index2.html","rb")
 7     data2=f2.read()
 8  
 9     if path=="/yuan":
10         return [data1]
11     elif path=="/alex":
12         return [data2]
13     else:
14         return ["

404

".encode('utf8')]
View Code

第三步

 1 from wsgiref.simple_server import make_server
 2  
 3 def f1():
 4     f1=open("index1.html","rb")
 5     data1=f1.read()
 6     return [data1]
 7  
 8 def f2():
 9     f2=open("index2.html","rb")
10     data2=f2.read()
11     return [data2]
12  
13 def application(environ, start_response):
14  
15     print(environ['PATH_INFO'])
16     path=environ['PATH_INFO']
17     start_response('200 OK', [('Content-Type', 'text/html')])
18  
19  
20     if path=="/tomp":
21         return f1()
22  
23     elif path=="/tom":
24         return f2()
25  
26     else:
27         return ["

404

".encode("utf8")] 28 29 30 httpd = make_server('', 8502, application) 31 32 print('Serving HTTP on port 8084...') 33 34 # 开始监听HTTP请求: 35 httpd.serve_forever()
View Code

第四步

 1 from wsgiref.simple_server import make_server
 2  
 3  
 4 def f1(req):
 5     print(req)
 6     print(req["QUERY_STRING"])
 7  
 8     f1=open("index1.html","rb")
 9     data1=f1.read()
10     return [data1]
11  
12 def f2(req):
13  
14     f2=open("index2.html","rb")
15     data2=f2.read()
16     return [data2]
17  
18 import time
19  
20 def f3(req):        #模版以及数据库
21  
22     f3=open("index3.html","rb")
23     data3=f3.read()
24     times=time.strftime("%Y-%m-%d %X", time.localtime())
25     data3=str(data3,"utf8").replace("!time!",str(times))
26  
27  
28     return [data3.encode("utf8")]
29  
30  
31 def routers():
32  
33     urlpatterns = (
34         ('/yuan',f1),
35         ('/alex',f2),
36         ("/cur_time",f3)
37     )
38     return urlpatterns
39  
40  
41 def application(environ, start_response):
42  
43     print(environ['PATH_INFO'])
44     path=environ['PATH_INFO']
45     start_response('200 OK', [('Content-Type', 'text/html')])
46  
47  
48     urlpatterns = routers()
49     func = None
50     for item in urlpatterns:
51         if item[0] == path:
52             func = item[1]
53             break
54     if func:
55         return func(environ)
56     else:
57         return ["

404

".encode("utf8")] 58 59 httpd = make_server('', 8518, application) 60 61 print('Serving HTTP on port 8084...') 62 63 # 开始监听HTTP请求: 64 65 httpd.serve_forever()
View Code

二MVC和MTV模式

MVC模式:把web应用分为模型(M),控制器(C),视图(V)三层; 他们之间以一种插件似的,松耦合的方式来连接在一起

模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图而完成用户的请求.

 

django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,django的MTV分别代表:

  Model(模型):负责业务对象与数据库的对象(ORM)

  Template(模板):负责如何把页面展示给用户

  View(视图):负责业务逻辑,并在适合的时候调用Model和Template

  此外,django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

django框架(1)_第1张图片

三 django的流程和命令行工具

django实现流程

 1 django
 2         安装:  pip3 install django
 3 
 4             添加环境变量
 5 
 6 1     创建project
 7     django-admin startproject mysite
 8 
 9 ---mysite
10 
11     ---settings.py
12     ---url.py
13     ---wsgi.py
14 
15 ---manage.py(启动文件)
16 
17 2     创建APP
18     python  mannage.py startapp app01
19 
20 3      settings配置
21 TEMPLATES
22  
23        STATICFILES_DIRS=(
24             os.path.join(BASE_DIR,"statics"),   #注意:静态文件括号里是元组,就算一个元素也要加上逗号
25         )
26  
27        STATIC_URL = '/static/'
28        #  我们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找#4  根据需求设计代码
29            url.py
30            view.py
31 
32     #5  使用模版
33        render(req,"index.html")  
34  
35     #6  启动项目
36        python manage.py runserver  127.0.0.1:8090
37  
38     #7  连接数据库,操作数据
39        model.py

django的命令行工具

django-admin.py是django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每一个django project里都会有一个manage.py

<1>创建一个django工程:django-admin.py  startproject  mysite

  当前目录下会生成mysite的工程,目录结构如下:

       

  manage.py-------django项目里面的工具,通过它可以调用django shell和数据库等

  settings.py-------包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量

  urls.py-------负责把Url模式映射到应用程序

<2>在mysite目录下创建blog应用:python manage.py startapp blog    

 

<3>启动django项目:python manage.py runserver 8080

 这样我们的django就启动起来了!当我们访问:  http://127.0.0.1:8080/时就可以看到:

<4>生成同步数据库的脚本: python manage.py makemigrations(此时并没有链接到数据库,在migrations文件夹中生成脚本文件)

    同步数据库: python manage.py migrate

  注意:  在开发过程中, 数据库同步误操作以后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法就是把migrations目录下的脚本(除__init__.py之外)全部删除,再把数据库删除之后创建一个新的数库,数据库同步操作再重新做一遍

<5>当我们访问http://127.0.0.1:8080/admin/时,会出现:

           django框架(1)_第2张图片

  所以我们需要为进入这个项目的后台创建超级管理员:

  python  manage.py createsuperuser, 设置好用户名和密码后便可登陆了

  <6>清空数据库:python manage.py    flush

  <7>查询某个命令的详细信息:django-admin.py  help startapp

    admin是django自带的一个后台数据库管理系统

  <8>启动交互界面: python manage.py shell

    这个命令和直接运行python进入shell的区别是:你可以在这个shell里面调用当前项目的models.py中的API,对于操作数据,还有一些小测试非常方便

       <9>终端上输入python manage.py 可以看到详细的列表,在忘记子名称的时候特别有用

四 django的配置文件(settings)

静态文件设置

  1 一、概述:
  2  
  3      #静态文件交由Web服务器处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例):
  4  
  5      #          URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx.
  6                              #conf里的location
  7  
  8                          |---------->如果是静态文件,则由nginx直接处理
  9  
 10                          |---------->如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配
 11  
 12     # 以上是部署到Web服务器后的处理方式,为了便于开发,Django提供了在开发环境的对静态文件的处理机制,方法是这样:
 13  
 14     #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles',
 15  
 16     #2、在urls.py里面加入
 17        if settings.DEBUG: 
 18            urlpatterns += patterns('', url(r'^media/(?P.*)$',
 19            'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),  
 20             url(r'^static/(?P.*)$',
 21           'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), ) 
 22  
 23     # 3、这样就可以在开发阶段直接使用静态文件了。
 24  
 25 二、MEDIA_ROOT和MEDIA_URL
 26  
 27         #而静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的:
 28  
 29         #MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件。如果你定义
 30  
 31         #MEDIA_ROOT=c:\temp\media,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c:\temp\media\abc 
 32         #eg:
 33             class blog(models.Model): 
 34                    Title=models.charField(max_length=64) 
 35                    Photo=models.ImageField(upload_to="photo")
 36         #     上传的图片就上传到c:\temp\media\photo,而在模板中要显示该文件,则在这样写
 37         #在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写:
 38                  BASE_DIR= os.path.abspath(os.path.dirname(__file__)) 
 39                  MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/')
 40  
 41         #MEDIA_URL是指从浏览器访问时的地址前缀,举个例子:
 42             MEDIA_ROOT=c:\temp\media\photo 
 43             MEDIA_URL="/data/"
 44         #在开发阶段,media的处理由django处理:
 45  
 46         #    访问http://localhost/data/abc/a.png就是访问c:\temp\media\photo\abc\a.png
 47  
 48         #    在模板里面这样写
 49  
 50         #    在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置,
 51         #  以便能让web服务器能访问media文件
 52         #    以nginx为例,可以在nginx.conf里面这样:
 53  
 54                  location ~/media/{
 55                        root/temp/
 56                        break;
 57                     }
 58  
 59         #    具体可以参考如何在nginx部署django的资料。
 60  
 61 三、STATIC_ROOT和STATIC_URL、
 62     STATIC主要指的是如css,js,images这样文件,在settings里面可以配置STATIC_ROOT和STATIC_URL,
 63     配置方式与MEDIA_ROOT是一样的,但是要注意
 64  
 65     #STATIC文件一般保存在以下位置:
 66  
 67     #1、STATIC_ROOT:在settings里面设置,一般用来放一些公共的js,css,images等。
 68  
 69     #2、app的static文件夹,在每个app所在文夹均可以建立一个static文件夹,然后当运行collectstatic时,
 70     #    Django会遍历INSTALL_APPS里面所有app的static文件夹,将里面所有的文件复制到STATIC_ROOT。因此,
 71     #   如果你要建立可复用的app,那么你要将该app所需要的静态文件放在static文件夹中。
 72  
 73     # 也就是说一个项目引用了很多app,那么这个项目所需要的css,images等静态文件是分散在各个app的static文件的,比
 74     #  较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT。
 75  
 76     #3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。
 77     #  STATIC_URL的含义与MEDIA_URL类似。
 78  
 79     # ----------------------------------------------------------------------------
 80     #注意1:
 81         #为了后端的更改不会影响前端的引入,避免造成前端大量修改
 82  
 83         STATIC_URL = '/static/'               #引用名
 84         STATICFILES_DIRS = (
 85             os.path.join(BASE_DIR,"statics")  #实际名 ,即实际文件夹的名字
 86         )
 87  
 88         #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找
 89         #
 90         #------error-----不能直接用,必须用STATIC_URL = '/static/':
 91         #
 92  
 93     #注意2(statics文件夹写在不同的app下,静态文件的调用):
 94  
 95         STATIC_URL = '/static/'
 96  
 97         STATICFILES_DIRS=(
 98             ('hello',os.path.join(BASE_DIR,"app01","statics")) ,
 99         )
100  
101         #
102  
103     #注意3:
104         STATIC_URL = '/static/'
105         {% load staticfiles %}
106        # 

其他重要参数设置:

1 APPEND_SLASH
2        Default: True
3        When set to True, if the request URL does not match any of the patterns in the URLconf and it
4        doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note
5        that the redirect may cause any data submitted in a POST request to be lost.

五 django url(路由系统)

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

1 urlpatterns = [
2     url(正则表达式, views视图函数,参数,别名),
3 ]

参数说明:

  一个正则表达式字符串

  一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串

  可选的要传递给视图函数的默认参数(字典形式)

  一个可选的name参数

 1 from django.conf.urls import url
 2 from django.contrib import admin
 3  
 4 from app01 import views
 5  
 6 urlpatterns = [
 7  
 8     url(r'^articles/2003/$', views.special_case_2003),   #从头到尾完全匹配
 9  
10     #url(r'^articles/[0-9]{4}/$', views.year_archive),
11  
12     url(r'^articles/([0-9]{4})/$', views.year_archive),  #无名分组,括号里的参数会传递给视图函数,同样的,视图函数也需要对应参数来接收,一个括号代表一个参数
13  
14     url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
15  
16     url(r'^articles/(?P[0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),#有名分组,括号里的参数会传递给视图函数,且视图函数需要接收的参数名字需与有名分组名字一致
17  
18 ]  

include用法:当项目中创建多个app时,在路由映射时通过include方法可以将用户访问的目标路径映射到对应的app中的视图函数中

  注意:

    1.在主路由系统中需要导入include

    2.映射格式:app.urls

 1 #At any point, your urlpatterns can “include” other URLconf modules. This
 2 #essentially “roots” a set of URLs below other ones.
 3  
 4 #For example, here’s an excerpt of the URLconf for the Django website itself.
 5 #It includes a number of other URLconfs:
 6  
 7  
 8 from django.conf.urls import include, url
 9  
10 urlpatterns = [
11    url(r'^admin/', admin.site.urls),
12    url(r'^blog/', include('blog.urls')),
13 ]

六 django views(视图函数)

http请求中产生两个核心对象:

  http请求: HttpRequest对象

  http响应:HttpResponse对象

所在位置: django.http

之前我们用到的参数request就是HttpRequest 检测方法:   isinstance(request,HttpRequest)

1 HttpRequest对象的属性和方法:

 1 path:                请求页面的全路径,不包括域名
 2 
 3 method:            请求使用的Http方法的字符串表示.全大写表示.例如
 4             
 5         if  req.method=="GET":
 6 
 7                   do_something()
 8 
 9          elseif req.method=="POST":
10 
11                    do_something_else()
12 
13 GET:     包含所有HTTP GET参数的类字典对象
14 
15 POST:    包含所有HTTP POST参数的类字典对象
16 
17             服务器收到空的POST请求的情况也是可能发生的,也就是说,表单 
18             form通过HTTP POST方法提交请求,但是表单中可能没有数据,因 
19             此不能使用 if  req.POST来判断是否使用了HTTP POST方法;应 
20             该使用 if req.method == "POST"    
21 
22 COOKIES:  包含所有cookies的标准python字典对象;keys和values都是 
23              字符串
24 
25 FILES:    包含所有上传文件的类字典对象;FILES中的每一个key都是"file" name>
26     
27           filename:    上传文件名,用字符串表示
28           content_type:  上传文件的 Content Type
29           content:      上传文件的原始内容
30 
31 user:      是一个django.contrib.auth.models.User对象,代表当前登陆的用户.如果访问用户没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例.可以通过user的is_authenticated()方法来辨别用户是否登陆
32 if req.user.is_authenticated();只有激活django中的AuthentionMiddlewar时该属性才可以用
33 
34 session:  唯一可读写的属性,代表当前会话的字典对象;自己有激活django 
35               中的session支持时该方法
36 
37 方法:
38 get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 
39 
40 req.path:/index33

注意一个常用方法:request.POST.getlist(" "),用于接受的value不为单个元素时使用

2  HttpResponse对象

对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建.每个view请求处理方法必须返回一个HttpResponse对象.

HttpResponse类在django.http.HttpResponse

在HttpResponse对象上扩展的常用方法:

1 页面渲染:       render()            render_to_response(),
2 
3 页面跳转:        redirect("路径")
4 locals():      可以直接将函数中所有的变量传给模板

七 Template基础

模板系统的介绍

  • 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。

  • Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。

  • 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式,这就是本章要具体讨论的问题。

 

**************************************************************模板语法****************************************

一  模板的组成

组成:HTML代码   +   逻辑控制代码

二  逻辑控制代码的组成

1  变量(使用双大括号来引用变量)

语法格式:       {{var_name}}

------Template和Context对象

 1 >>> python manange.py shell  (进入该django项目的环境)
 2 >>> from django.template import Context, Template
 3 >>> t = Template('My name is {{ name }}.')
 4 >>> c = Context({'name': 'Stephane'})
 5 >>> t.render(c)
 6 'My name is Stephane.'
 7  
 8  
 9 # 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
10 # 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
11 # 更为高效:
12 # Low
13 for name in ('John', 'Julie', 'Pat'):
14     t = Template('Hello, {{ name }}')
15     print t.render(Context({'name': name}))
16  
17 # Good
18 t = Template('Hello, {{ name }}')
19 for name in ('John', 'Julie', 'Pat'):
20     print t.render(Context({'name': name}))
View Code

Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。

 1 from django.shortcuts import render,HttpResponse
 2 from django.template.loader import get_template #记得导入
 3 # Create your views here.
 4  
 5  
 6 import datetime
 7 from django.template import Template,Context
 8  
 9 # def current_time(req):
10     #原始的视图函数
11     # now=datetime.datetime.now()
12     # html="现在时刻:

%s.

" %now
13 # return HttpResponse(html) 14 15 16 17 # def current_time(req): 18 19 #django模板修改的视图函数 20 # now=datetime.datetime.now() 21 # t=Template('现在时刻是:

{{current_date}}

')
22 #t=get_template('current_datetime.html') 23 # c=Context({'current_date':now}) 24 # html=t.render(c) 25 # return HttpResponse(html) 26 27 #另一种写法(推荐) 28 29 def current_time(req): 30 31 now=datetime.datetime.now() 32 33 return render(req, 'current_datetime.html', {'current_date':now}) 34 35 推荐方式
View Code

 

-------------------深度变量查询(万能的点)

在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。

在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)

 1 #最好是用几个例子来说明一下。
 2 # 首先,句点可用于访问列表索引,例如:
 3  
 4 >>> from django.template import Template, Context
 5 >>> t = Template('Item 2 is {{ items.2 }}.')
 6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
 7 >>> t.render(c)
 8 'Item 2 is carrots.'
 9  
10 #假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
11 >>> from django.template import Template, Context
12 >>> person = {'name': 'Sally', 'age': '43'}
13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
14 >>> c = Context({'person': person})
15 >>> t.render(c)
16 'Sally is 43 years old.'
17  
18 #同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
19 #year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:
20  
21 >>> from django.template import Template, Context
22 >>> import datetime
23 >>> d = datetime.date(1993, 5, 2)
24 >>> d.year
25 >>> d.month
26 >>> d.day
27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
28 >>> c = Context({'date': d})
29 >>> t.render(c)
30 'The month is 5 and the year is 1993.'
31  
32 # 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
33 # 用于任意的对象。
34 >>> from django.template import Template, Context
35 >>> class Person(object):
36 ...     def __init__(self, first_name, last_name):
37 ...         self.first_name, self.last_name = first_name, last_name
38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
39 >>> c = Context({'person': Person('John', 'Smith')})
40 >>> t.render(c)
41 'Hello, John Smith.'
42  
43 # 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
44 # 方法,你在模板中可以使用同样的句点语法来调用它们:
45 >>> from django.template import Template, Context
46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
47 >>> t.render(Context({'var': 'hello'}))
48 'hello -- HELLO -- False'
49 >>> t.render(Context({'var': '123'}))
50 '123 -- 123 -- True'
51  
52 # 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
53 # 方法。
View Code

-------------------变量的过滤器(filter)的使用

 1 语法格式:       {{obj | filter:param}}
 2 
 3 add   :  给变量加上相应的值
 4 
 5 addslashes:      给变量中的引号前加上斜线
 6 
 7 capfirst:        首字母大写
 8 
 9 cut:        从字符串中移除指定的字符
10 
11 date:       格式化日期字符串
12 
13 default:    如果值是False,就替换成设置的默认值,否则就是用本来的值
14 
15 default_if_none:  如果值是none,就替换成设置的默认值,否则就使用本来的值
16 
17 
18 #实例:
19  
20 #value1="aBcDe"
21 {{ value1|upper }}
22 23 #value2=5 24 {{ value2|add:3 }}
25 26 #value3='he llo wo r ld' 27 {{ value3|cut:' ' }}
28 29 #import datetime 30 #value4=datetime.datetime.now() 31 {{ value4|date:'Y-m-d' }}
32 33 #value5=[] 34 {{ value5|default:'空的' }}
35 36 #value6='跳转' 37 38 {{ value6 }} 39 40 {% autoescape off %} 41 {{ value6 }} 42 {% endautoescape %} 43 44 {{ value6|safe }}
45 46 {{ value6|striptags }} 47 48 #value7='1234' 49 {{ value7|filesizeformat }}
50 {{ value7|first }}
51 {{ value7|length }}
52 {{ value7|slice:":-1" }}
53 54 #value8='http://www.baidu.com/?a=1&b=3' 55 {{ value8|urlencode }}
56 value9='hello I am tom'

2 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

------{% if %} 的使用 

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

 1 {% if num >= 100 and 8 %}
 2  
 3     {% if num > 200 %}
 4         

num大于200

5 {% else %} 6

num大于100小于200

7 {% endif %} 8 9 {% elif num < 100%} 10

num小于100

11 12 {% else %} 13

num等于100

14 15 {% endif %} #与if成对出现 16 17 18 19 {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量 20 {% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的: 21 22 {% if obj1 and obj2 or obj3 %}
View Code

------{% for %}的使用

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

 1 
    2 {% for obj in list %} 3
  • {{ obj.name }}
  • 4 {% endfor %} 5
6 7 8 #在标签里添加reversed来反序循环列表: 9 10 {% for obj in list reversed %} 11 ... 12 {% endfor %} 13 14 #{% for %}标签可以嵌套: 15 16 {% for country in countries %} 17

{{ country.name }}

18
    19 {% for city in country.city_list %} 20
  • {{ city }}
  • 21 {% endfor %} 22
23 {% endfor %} 24 25 26 #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量, 27 #这个变量含有一些属性可以提供给你一些关于循环的信息 28 29 1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: 30 31 {% for item in todo_list %} 32

{{ forloop.counter }}: {{ item }}

33 {% endfor %} 34 2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0 35 3,forloop.revcounter 36 4,forloop.revcounter0 37 5,forloop.first当第一次循环时值为True,在特别情况下很有用: 38 39 40 {% for object in objects %} 41 {% if forloop.first %}
  • class="first">{% else %}
  • {% endif %} 42 {{ object }} 43
  • 44 {% endfor %} 45 46 # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了 47 # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它 48 # Django会在for标签的块中覆盖你定义的forloop变量的值 49 # 在其他非循环的地方,你的forloop变量仍然可用 50 51 52 #{% empty %} 53 54 {{li }} 55 {% for i in li %} 56
  • {{ forloop.counter0 }}----{{ i }}
  • 57 {% empty %} 58
  • this is empty!
  • 59 {% endfor %} 60 61 # [11, 22, 33, 44, 55] 62 # 0----11 63 # 1----22 64 # 2----33 65 # 3----44 66 # 4----55
    View Code

    ------{%csrf_token%}:csrf_token标签

         用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效

    其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

     

    ------{% url %}:  引用路由配置的地址

    1 
    "{% url "bieming"%}" > 2 "text"> 3 "submit"value="提交"> 4 {%csrf_token%} 5

    ------{% with %}:用更简单的变量名替代复杂的变量名

    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

    ------{% verbatim %}: 禁止render

    1 {% verbatim %}
    2          {{ hello }}
    3 {% endverbatim %}

    ------{% load %}: 加载标签库 

    3自定义filter和simple_tag

    ------a、在app中创建templatetags模块(必须的)

    ------b、创建任意 .py 文件,如:my_tags.py

     1 from django import template
     2 from django.utils.safestring import mark_safe
     3  
     4 register = template.Library()   #register的名字是固定的,不可改变
     5  
     6  
     7 @register.filter
     8 def filter_multi(v1,v2):
     9     return  v1 * v2
    10  
    11  
    12 @register.simple_tag
    13 def simple_tag_multi(v1,v2):
    14     return  v1 * v2
    15  
    16  
    17 @register.simple_tag
    18 def my_input(id,arg):
    19     result = "" %(id,arg,)
    20     return mark_safe(result)
    View Code

    ------c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

    ------d、使用simple_tag和filter(如何调用)

     1 -------------------------------.html
     2 {% load xxx %}   #首行
     3      
     4      
     5      
     6      
     7  # num=12
     8 {{ num|filter_multi:2 }} #24
     9  
    10 {{ num|filter_multi:"[22,333,4444]" }}
    11  
    12  
    13 {% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中
    14 {% simple_tag_multi num 5 %}
    View Code

    ------e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    注意:

    filter可以用在if等语句后,simple_tag不可以

    1 {% if num|filter_multi:30 > 100 %}
    2     {{ num|filter_multi:30 }}
    3 {% endif %}

    4 extend模板继承

    --------------------include模板标签

    在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。

    ------extend(继承)模板标签

    到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?

    解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。

    本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

    让我们通过修改 current_datetime.html 文件,为 current_datetime 创建一个更加完整的模板来体会一下这种做法:

     1 "-//W3C//DTD HTML 4.01//EN">
     2 "en">
     3 
     4     The current time
     5 
     6 
     7     

    My helpful timestamp site

    8

    It is now {{ current_date }}.

    9 10
    11

    Thanks for visiting my site.

    12 13
    View Code

    这看起来很棒,但如果我们要为 hours_ahead 视图创建另一个模板会发生什么事情呢?

     1 "-//W3C//DTD HTML 4.01//EN">
     2 "en">
     3 
     4     Future time
     5 
     6 
     7     

    My helpful timestamp site

    8

    In {{ hour_offset }} hour(s), it will be {{ next_time }}.

    9 10
    11

    Thanks for visiting my site.

    12 13
    View Code

    很明显,我们刚才重复了大量的 HTML 代码。 想象一下,如果有一个更典型的网站,它有导航

    条、样式表,可能还有一些 JavaScript 代码,事情必将以向每个模板填充各种冗余的 HTML 而告终。

    解决这个问题的服务器端 include 方案是找出两个模板中的共同部分,将其保存为不同的模板片段,然后在每个模板中进行 include。 也许你会把模板头部的一些代码保存为 header.html 文件:

    1 "-//W3C//DTD HTML 4.01//EN">
    2 "en">
    3 
    View Code

    你可能会把底部保存到文件 footer.html :

    1 
    2

    Thanks for visiting my site.

    3 4
    View Code

     

    对基于 include 的策略,头部和底部的包含很简单。 麻烦的是中间部分。 在此范例中,每个页面都有一个

    My helpful timestamp site

     标题,但是这个标题不能放在 header.html 中,因为每个页面的 </tt> 是不同的。 如果我们将 <tt class="docutils literal"><h1></tt> 包含在头部,我们就不得不包含 <tt class="docutils literal"><title></tt> ,但这样又不允许在每个页面对它进行定制。 何去何从呢?</p> <p id="cn404" class="cn">Django 的模板继承系统解决了这些问题。 你可以将其视为服务器端 include 的逆向思维版本。 你可以对那些<em>不同</em> 的代码段进行定义,而不是 <em>共同</em> 代码段。</p> <p class="cn">第一步是定义 基础模板,该框架之后将由子模板所继承。 以下是我们目前所讲述范例的基础模板:</p> <div class="cnblogs_code"> <img id="code_img_closed_4d54406c-e844-424f-be6a-febcc78fc4f8" class="code_img_closed" src="http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif" alt="" width="0" height="0"> <img id="code_img_opened_4d54406c-e844-424f-be6a-febcc78fc4f8" class="code_img_opened" src="http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif" alt="" width="0" height="0"> <div id="cnblogs_code_open_4d54406c-e844-424f-be6a-febcc78fc4f8" class="cnblogs_code_hide"> <pre><span style="color:#008080;"> 1</span> <!DOCTYPE HTML PUBLIC <span style="color:#800000;">"</span><span style="color:#800000;">-//W3C//DTD HTML 4.01//EN</span><span style="color:#800000;">"</span>> <span style="color:#008080;"> 2</span> <html lang=<span style="color:#800000;">"</span><span style="color:#800000;">en</span><span style="color:#800000;">"</span>> <span style="color:#008080;"> 3</span> <head> <span style="color:#008080;"> 4</span> <title>{% block title %}{% endblock %} 5 6 7

    My helpful timestamp site

    8 {% block content %}{% endblock %} 9 {% block footer %} 10
    11

    Thanks for visiting my site.

    12 {% endblock %} 13 14
    View Code

     

    这个叫做 base.html 的模板定义了一个简单的 HTML 框架文档,我们将在本站点的所有页面中使用。 子模板的作用就是重载、添加或保留那些块的内容。 (如果你一直按顺序学习到这里,保存这个文件到你的template目录下,命名为 base.html .)

    我们使用模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 每个{% block %}标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。

    现在我们已经有了一个基本模板,我们可以修改 current_datetime.html 模板来 使用它:

    1 {% extends "base.html" %}
    2   
    3 {% block title %}The current time{% endblock %}
    4   
    5 {% block content %}
    6 

    It is now {{ current_date }}.

    7 {% endblock %}
    View Code

    再为 hours_ahead 视图创建一个模板,看起来是这样的:

    1 {% extends "base.html" %}
    2   
    3 {% block title %}Future time{% endblock %}
    4   
    5 {% block content %}
    6 

    In {{ hour_offset }} hour(s), it will be {{ next_time }}.

    7 {% endblock %}
    View Code

     

    以下是其工作方式:

          在加载 current_datetime.html 模板时,模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。 模板引擎立即装载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 block title %} 中定义的标题,对 {% block content %} 也是如此。 所以,网页标题一块将由{% block title %}替换,同样地,网页的内容一块将由 {% block content %}替换。

         注意由于子模板并没有定义 footer 块,模板系统将使用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被当作一条退路。继承并不会影响到模板的上下文。 换句话说,任何处在继承树上的模板都可以访问到你传到模板中的每一个模板变量。你可以根据需要使用任意多的继承次数。 使用继承的一种常见方式是下面的三层法:

    <1> 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
       <2> 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,
           并包含区域特定的风格与设计。
       <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。

     

      这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。

    以下是使用模板继承的一些诀窍:

    <1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。
     
     <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
        你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
        多越好。
     
     <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
        如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模
        板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。
     
     <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
        也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
        相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

    八 Models

    数据库的配置

    1  django默认支持sqlite,mysql,oracle,postgresql数据库.

      <1>sqlite

        django默认使用sqlite的数据库, 默认自带sqlite的数据库驱动,引擎名称:                                       django.db.backends.sqlite3

      <2>mysql

         引擎名称:django.db.backends.mysql

    2    mysql驱动程序

      MySQLdb(mysql   python)

      mysqlclient

      MySQL

      PyMySQL(纯Python的mysql驱动程序)

    3  在django的项目中会默认使用sqlite数据库,在settings里有如下设置:

    如果我们想要更改数据库,需要修改如下:

     1 DATABASES = {
     2  
     3     'default': {
     4  
     5         'ENGINE': 'django.db.backends.mysql',
     6  
     7         'NAME': 'books',    #你的数据库名称
     8  
     9         'USER': 'root',   #你的数据库用户名
    10  
    11         'PASSWORD': '', #你的数据库密码
    12  
    13         'HOST': '', #你的数据库主机,留空默认为localhost
    14  
    15         'PORT': '3306', #你的数据库端口
    16  
    17     }
    18  
    19 }
    mysql配置
     1 NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
     2  
     3 USER和PASSWORD分别是数据库的用户名和密码。
     4  
     5 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
     6  
     7 然后,启动项目,会报错:no module named MySQLdb
     8  
     9 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
    10  
    11 所以,我们只需要找到项目名文件下的__init__,在里面写入:
    12  
    13 import pymysql
    14 pymysql.install_as_MySQLdb()
    15  
    mysql的配置完后的操作

     

    ORM(对象关系映射)

    用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

    优点: 1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

              2 可以避免一些新手程序猿写sql语句带来的性能问题。

                比如 我们查询User表中的所有字段:

      新手可能会用select * from  auth_user,这样会因为多了一个匹配动作而影响效率的。

     缺点:1  性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

              2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

              3  通过QuerySet的query属性查询对应操作的sql语句

    author_obj=models.Author.objects.filter(id=2)
    print(author_obj.query)

    表(模型)的创建

    实例:我们来假定下面这些概念,字段和关系

    作者模型:一个作者有姓名。

    作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

    出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

    书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键

     1 from django.db import models
    2 class Publisher(models.Model): 3 name = models.CharField(max_length=30, verbose_name="名称") 4 address = models.CharField("地址", max_length=50) 5 city = models.CharField('城市',max_length=60) 6 state_province = models.CharField(max_length=30) 7 country = models.CharField(max_length=50) 8 website = models.URLField() 9 10 class Meta: 11 verbose_name = '出版商' 12 verbose_name_plural = verbose_name 13 14 def __str__(self): 15 return self.name 16 17 class Author(models.Model): 18 name = models.CharField(max_length=30) 19 def __str__(self): 20 return self.name 21 22 class AuthorDetail(models.Model): 23 sex = models.BooleanField(max_length=1, choices=((0, ''),(1, ''),)) 24 email = models.EmailField() 25 address = models.CharField(max_length=50) 26 birthday = models.DateField() 27 author = models.OneToOneField(Author) #创建多对多关系的第三张表,数据库自动创建 28 29 class Book(models.Model): 30 title = models.CharField(max_length=100) 31 authors = models.ManyToManyField(Author) 32 publisher = models.ForeignKey(Publisher) 33 publication_date = models.DateField() 34 price=models.DecimalField(max_digits=5,decimal_places=2,default=10) 35 def __str__(self): 36 return self.title
    View Code

    注意1:记得在settings里的INSTALLED_APPS中加入'app01',然后再同步数据库。

    注意2: models.ForeignKey("Publish") & models.ForeignKey(Publish),由于python解释器加载顺序的原因,如果外键里调用的类名已经在上面被加载了可以直接写类名,不用加引号,否则要加上,不然解释器找不到

    分析代码:

           <1>  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

           <2>  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

           <3>  模型之间的三种关系:一对一,一对多,多对多。

                 一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;

                 一对多:就是主外键关系;(foreign key)

                 多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

      <4>模型常用的字段类型参数

      1 <1> CharField
      2         #字符串字段, 用于较短的字符串.
      3         #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
      4  
      5 <2> IntegerField
      6        #用于保存一个整数.
      7  
      8 <3> FloatField
      9         # 一个浮点数. 必须 提供两个参数:
     10         #
     11         # 参数    描述
     12         # max_digits    总位数(不包括小数点和符号)
     13         # decimal_places    小数位数
     14                 # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
     15                 #
     16                 # models.FloatField(..., max_digits=5, decimal_places=2)
     17                 # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
     18                 #
     19                 # models.FloatField(..., max_digits=19, decimal_places=10)
     20                 # admin 用一个文本框()表示该字段保存的数据.
     21  
     22 <4> AutoField
     23         # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
     24         # 自定义一个主键:my_id=models.AutoField(primary_key=True)
     25         # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
     26  
     27 <5> BooleanField
     28         # A true/false field. admin 用 checkbox 来表示此类字段.
     29  
     30 <6> TextField
     31         # 一个容量很大的文本字段.
     32         # admin 用一个