python 之 Django 框架html
本节内容前端
1.web 框架python
2.mvc和mtv模式jquery
3.django流程和命令git
4.django URL程序员
5.django viewsweb
6.django temple正则表达式
7.django modelsshell
8.django admin数据库
1.web框架
框架,即framework,特指为解决一个开放性问题而设计的具备必定约束性的支撑结构,使用框架能够帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来作表演。
Web应用的流程:
//浏览器发送一个HTTP请求;
//服务器收到请求,生成一个HTML文档;
//服务器把HTML文档做为HTTP响应的Body发送给浏览器;
//浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
对于全部的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("<h1 style='color:red'>Hello, world</h1>".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。
实现一个简单的web框架
one:
from wsgiref.simple_server import make_server def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'<h1>Hello, web!</h1>'] httpd = make_server('', 8080, application) print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()
整个application()函数自己没有涉及到任何解析HTTP的部分,也就是说,底层代码不须要咱们本身编写,
咱们只负责在更高层次上考虑如何响应请求就能够了。
application()函数必须由WSGI服务器来调用。有不少符合WSGI规范的服务器,咱们能够挑选一个来用。
Python内置了一个WSGI服务器,这个模块叫wsgiref
application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
//environ:一个包含全部HTTP请求信息的dict对象;
//start_response:一个发送HTTP响应的函数。
在application()函数中,调用:
start_response('200 OK', [('Content-Type', 'text/html')])
就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每一个Header用一个包含两个str的tuple表示。
一般状况下,都应该把Content-Type头发送给浏览器。其余不少经常使用的HTTP Header也应该发送。
而后,函数的返回值b'<h1>Hello, web!</h1>'将做为HTTP响应的Body发送给浏览器。
有了WSGI,咱们关心的就是如何从environ这个dict对象拿到HTTP请求信息,而后构造HTML,
经过start_response()发送Header,最后返回Body。
two:
print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) f1=open("index1.html","rb") data1=f1.read() f2=open("index2.html","rb") data2=f2.read() if path=="/yuan": return [data1] elif path=="/alex": return [data2] else: return ["<h1>404</h1>".encode('utf8')]
Three:
from wsgiref.simple_server import make_server def f1(): f1=open("index1.html","rb") data1=f1.read() return [data1] def f2(): f2=open("index2.html","rb") data2=f2.read() return [data2] def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) if path=="/yuan": return f1() elif path=="/alex": return f2() else: return ["<h1>404</h1>".encode("utf8")] httpd = make_server('', 8502, application) print('Serving HTTP on port 8084...') # 开始监听HTTP请求: httpd.serve_forever()
Four:
from wsgiref.simple_server import make_server def f1(req): print(req) print(req["QUERY_STRING"]) f1=open("index1.html","rb") data1=f1.read() return [data1] def f2(req): f2=open("index2.html","rb") data2=f2.read() return [data2] import time def f3(req): #模版以及数据库 f3=open("index3.html","rb") data3=f3.read() times=time.strftime("%Y-%m-%d %X", time.localtime()) data3=str(data3,"utf8").replace("!time!",str(times)) return [data3.encode("utf8")] def routers(): urlpatterns = ( ('/yuan',f1), ('/alex',f2), ("/cur_time",f3) ) return urlpatterns def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) urlpatterns = routers() func = None for item in urlpatterns: if item[0] == path: func = item[1] break if func: return func(environ) else: return ["<h1>404</h1>".encode("utf8")] httpd = make_server('', 8518, application) print('Serving HTTP on port 8084...') # 开始监听HTTP请求: httpd.serve_forever()
2.mvc和mtv模式
著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式链接在一块儿。
模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Django的MTV模式本质上与MVC模式没有什么差异,也是各组件之间为了保持松耦合关系,只是定义上有些许不一样,Django的MTV分别表明:
此外,Django还有一个url分发器,它的做用是将一个个URL的页面请求分发给不一样的view处理,view再调用相应的Model和Template
3.django流程和命令
django
#安装: pip3 install django
添加环境变量
#1 建立project
django-admin startproject mysite
---mysite
---settings.py
---url.py
---wsgi.py
---- manage.py(启动文件)
#2 建立APP
python mannage.py startapp app01
#3 settings配置
TEMPLATES
STATICFILES_DIRS=(
os.path.join(BASE_DIR,"statics"),
)
STATIC_URL = '/static/'
# 咱们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找
<script src="/statics/jquery-3.1.1.js"></script> ------error-----不能直接用,必须用STATIC_URL = '/static/'
<script src="/static/jquery-3.1.1.js"></script>
采用第二种方式 ,后端的更改不会影响前端的引入,避免形成前端大量修改
#4 根据需求设计代码
url.py
view.py
#5 使用模版
render(req,"index.html")
#6 启动项目
python manage.py runserver 127.0.0.1:8090
#7 链接数据库,操做数据
model.py
2.django命令行工具
django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每个Django Project里都会有一个mannage.py。
当前目录下会生成mysite的工程,目录结构以下:
.
└── mysite
├── manage.py
└── mysite
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
manage.py ——- Django项目里面的工具,经过它能够调用django shell和数据库等。
.
├── blog
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
└── mysite
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-35.pyc
│ └── settings.cpython-35.pyc
├── settings.py
├── urls.py
└── wsgi.py
<3>启动django项目:python manage.py runserver 8080
这样咱们的django就启动起来了!当咱们访问:http://127.0.0.1:8080/ 时就能够看到”It worked!”
<4>生成数据库
生成同步数据库的脚本:python manage.py makemigrations
同步数据库:python manage.py migrate
注意:在开发过程当中,数据库同步误操做以后,不免会遇到后面不能同步成功的状况,解决这个问题的一个简单粗暴方法是把migrations目录下的脚本(除init.py以外)所有删掉,再把数据库删掉以后建立一个新的数据库,数据库同步操做再从新作一遍。
<5>admin后台
当咱们访问http://127.0.0.1:8080/admin/ 时,会出现admin后台的登陆页面
因此咱们须要为进入这个项目的后台建立超级管理员: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 能够看到详细的列表,在忘记子名称的时候特别有用。
demo1提交数据并展现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>建立我的信息</h1> <form action="/userInfor/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性别<input type="text" name="sex"></p> <p>邮箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> <hr> <h1>信息展现</h1> <table border="1"> <tr> <td>姓名</td> <td>性别</td> <td>邮箱</td> </tr> {% for i in info_list %} <tr> <td>{{ i.username }}</td> <td>{{ i.sex }}</td> <td>{{ i.email }}</td> </tr> {% endfor %} </table> </body> </html>
-----------------------url.py---------------------------------------
url(r'^userInfor/', views.userInfor) -----------------------views.py-------------------------------------- info_list=[] def userInfor(req): if req.method=="POST": username=req.POST.get("username",None) sex=req.POST.get("sex",None) email=req.POST.get("email",None) info={"username":username,"sex":sex,"email":email} info_list.append(info) return render(req,"userInfor.html",{"info_list":info_list})
demo2提交数据并展现(数据库)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>建立我的信息</h1> <form action="/userInfor/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性别<input type="text" name="sex"></p> <p>邮箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> <hr> <h1>信息展现</h1> <table border="1"> <tr> <td>姓名</td> <td>性别</td> <td>邮箱</td> </tr> {% for i in info_list %} <tr> <td>{{ i.username }}</td> <td>{{ i.sex }}</td> <td>{{ i.email }}</td> </tr> {% endfor %} </table> </body> </html>
----------------------------------------------models.py
from django.db import models # Create your models here. class UserInfor(models.Model): username=models.CharField(max_length=64) sex=models.CharField(max_length=64) email=models.CharField(max_length=64) ----------------------------------------------views.py from django.shortcuts import render from app01 import models # Create your views here. def userInfor(req): if req.method=="POST": u=req.POST.get("username",None) s=req.POST.get("sex",None) e=req.POST.get("email",None) #---------表中插入数据方式一 # info={"username":u,"sex":e,"email":e} # models.UserInfor.objects.create(**info) #---------表中插入数据方式二 models.UserInfor.objects.create( username=u, sex=s, email=e ) info_list=models.UserInfor.objects.all() return render(req,"userInfor.html",{"info_list":info_list}) return render(req,"userInfor.html")
4.django URL
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。
urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ]
参数说明:
简单url配置
from django.conf.urls import url from django.contrib import admin from blog import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), #url(r'^articles/[0-9]{4}/$', views.year_archive), url(r'^articles/([0-9]{4})/$', views.year_archive), #no_named group url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
上面用括号括住的内容将被当作参数传递给视图函数,()在正则中表示分组,这些分组是无名分组,将做为普通参数传递进入视图函数。
命名分组url配置
from django.conf.urls import url from blog import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
上面形似(?P正则表达式)的形式在正则表达式中叫作命名分组,就是给该分组取了个名字,在这里,有名分组将做为key:value对的方式以关键字参数传递进视图函数。
扩展参数配置
from django.conf.urls import url from blog import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
第三个参数是一个字典,这个字典的键值对将做为关键字参数传递进视图函数,若是url中的命名分组和字典中的键相同,则字典中的键对应的值将会覆盖url中的命名分组的值传递进视图函数中。
别名配置
-------------------------------------urls------------------------------------- urlpatterns = [ url(r'^index',views.index,name='bieming'), url(r'^admin/', admin.site.urls), # url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ] ------------------------------------views------------------------------------- def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登录成功") return render(req,'index.html')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# <form action="/index/" method="post">#} <form action="{% url 'bieming' %}" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html>
第四个参数name=bieming做用就是给url取了个别名,以后在html中若是有form表单要提交到该url,则能够经过{% url “bieming” %}转换成相应的url。
添加子url
#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.
#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:
from django.conf.urls import include, url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog', include('blog.urls')),
]
--------------------------blog.urls----------------------------------
from django.conf.urls import url
from blog import views
urlpatterns = [
url(r'login/', views.login),
url(r'home/', views.home)
]
在主项目的urls文件中先导入include,以后在url中的blog中设置include(“blog.urls”)将会将blog子项目中的urls文件中的全部Url添加到django的url路由中。注意,在新版的django中建议include中的url blog后面和blog里面的url的前面都不须要加/,由于django会给咱们加好。
5.django views
http请求中产生两个核心对象:
所在位置:django.http
以前咱们用到的参数request就是HttpRequest 检测方法:isinstance(request,HttpRequest)
# path: 请求页面的全路径,不包括域名
#
# method: 请求中使用的HTTP方法的字符串表示。全大写表示。例如
#
# if req.method=="GET":
#
# do_something()
#
# elseif req.method=="POST":
#
# do_something_else()
#
# GET: 包含全部HTTP GET参数的类字典对象
#
# POST: 包含全部HTTP POST参数的类字典对象
#
# 服务器收到空的POST请求的状况也是可能发生的,也就是说,表单form经过
# HTTP POST方法提交请求,可是表单中可能没有数据,所以不能使用
# if req.POST来判断是否使用了HTTP POST 方法;应该使用 if req.method=="POST"
#
#
#
# COOKIES: 包含全部cookies的标准Python字典对象;keys和values都是字符串。
#
# FILES: 包含全部上传文件的类字典对象;FILES中的每个Key都是<input type="file" name="" />标签中 name属性的值,FILES中的每个value同时也是一个标准的python字典对象,包含下面三个Keys:
#
# filename: 上传文件名,用字符串表示
# content_type: 上传文件的Content Type
# content: 上传文件的原始内容
#
#
# user: 是一个django.contrib.auth.models.User对象,表明当前登录的用户。若是访问用户当前
# 没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
# 能够经过user的is_authenticated()方法来辨别用户是否登录:
# if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
# 时该属性才可用
#
# session: 惟一可读写的属性,表明当前会话的字典对象;本身有激活Django中的session支持时该属性才可用。
#方法
get_full_path(), 好比:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()获得的结果就是/index33/?name=123
req.path:/index33
对于HttpRequest对象来讲,是由django自动建立的,可是,HttpResponse对象就必须咱们本身建立。每一个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的经常使用方法:
总结: render和redirect的区别:
render浏览器只是作了一次url请求,的到了一次返回页面,而redirect浏览器第一次请求时服务器给浏览器发了个302跳转,浏览器拿到新的url后又进行了一次请求,获取到了新的页面。
你可能已经注意到咱们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python代码之中。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
尽管这种技术便于解释视图是如何工做的,但直接将HTML硬编码到你的视图里却并非一个好主意。 让咱们来看一下为何:
基于这些缘由,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 咱们可使用 Django的 模板系统 (Template System)来实现这种模式,这就是本章要具体讨论的问题。
模板组成:HTML代码+逻辑控制代码
语法格式: {{var_name}}
>>> python manange.py shell (进入该django项目的环境)
>>> from django.template import Context, Template
>>> t = Template('My name is {{ name }}.')
>>> c = Context({'name': 'Stephane'})
>>> t.render(c)
'My name is Stephane.'
# 同一模板,多个上下文,一旦有了模板对象,你就能够经过它渲染多个context,不管什么时候咱们均可以
# 像这样使用同一模板源渲染多个context,只进行 一次模板建立而后屡次调用render()方法渲染会
# 更为高效:
# Low
for name in ('John', 'Julie', 'Pat'):
t = Template('Hello, {{ name }}')
print t.render(Context({'name': name}))
# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
print t.render(Context({'name': name}))
Django 模板解析很是快捷。 大部分的解析工做都是在后台经过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎造成鲜明对比,那些引擎承担了 XML 解析器的开销,且每每比 Django 模板渲染引擎要慢上几个数量级。
from django.shortcuts import render,HttpResponse
from django.template.loader import get_template #记得导入
# Create your views here.
import datetime
from django.template import Template,Context
# def current_time(req):
#原始的视图函数
# now=datetime.datetime.now()
# html="<html><body>如今时刻:<h1>%s.</h1></body></html>" %now
# return HttpResponse(html)
# def current_time(req):
#django模板修改的视图函数
# now=datetime.datetime.now()
# t=Template('<html><body>如今时刻是:<h1 style="color:red">{{current_date}}</h1></body></html>')
#t=get_template('current_datetime.html')
# c=Context({'current_date':now})
# html=t.render(c)
# return HttpResponse(html)
#另外一种写法(推荐)
def current_time(req):
now=datetime.datetime.now()
return render(req, 'current_datetime.html', {'current_date':now})
推荐方式
在到目前为止的例子中,咱们经过 context 传递的简单参数值主要是字符串,然而,模板系统可以很是简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。
在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。
#最好是用几个例子来讲明一下。
# 首先,句点可用于访问列表索引,例如:
>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'
#假设你要向模板传递一个 Python 字典。 要经过字典键访问该字典的值,可以使用一个句点:
>>> 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)
'Sally is 43 years old.'
#一样,也能够经过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
#year 、 month 和 day 几个属性,你一样能够在模板中使用句点来访问这些属性:
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
>>> d.month
>>> d.day
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'
# 这个例子使用了一个自定义的类,演示了经过实例变量加一点(dots)来访问它的属性,这个方法适
# 用于任意的对象。
>>> from django.template import Template, Context
>>> class Person(object):
... def __init__(self, first_name, last_name):
... self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'
# 点语法也能够用来引用对象的方法。 例如,每一个 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可使用一样的句点语法来调用它们:
>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'
# 注意这里调用方法时并* 没有* 使用圆括号 并且也没法给该方法传递参数;你只能调用不需参数的
# 方法。
语法格式: {{obj|filter:param}}
# 1 add : 给变量加上相应的值 # # 2 addslashes : 给变量中的引号前加上斜线 # # 3 capfirst : 首字母大写 # # 4 cut : 从字符串中移除指定的字符 # # 5 date : 格式化日期字符串 # # 6 default : 若是值是False,就替换成设置的默认值,不然就是用原本的值 # # 7 default_if_none: 若是值是None,就替换成设置的默认值,不然就使用原本的值 #实例: #value1="aBcDe" {{ value1|upper }}<br> #value2=5 {{ value2|add:3 }}<br> #value3='he llo wo r ld' {{ value3|cut:' ' }}<br> #import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }}<br> #value5=[] {{ value5|default:'空的' }}<br> #value6='<a href="#">跳转</a>' {{ value6 }} {% autoescape off %} {{ value6 }} {% endautoescape %} {{ value6|safe }}<br> {{ value6|striptags }} #value7='1234' {{ value7|filesizeformat }}<br> {{ value7|first }}<br> {{ value7|length }}<br> {{ value7|slice:":-1" }}<br> #value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }}<br>
语法:{% tags %}
{% if %}标签计算一个变量值,若是是“true”,即它存在、不为空而且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的全部内容
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大于200</p> {% else %} <p>num大于100小于200</p> {% endif %} {% elif num < 100%} <p>num小于100</p> {% else %} <p>num等于100</p> {% endif %} {% if %} 标签接受and,or或者not来测试多个变量值或者否认一个给定的变量 {% if %} 标签不容许同一标签里同时出现and和or,不然逻辑容易产生歧义,例以下面的标签是不合法的: {% if obj1 and obj2 or obj3 %}
{% for %}标签容许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的全部内容
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> #在标签里添加reversed来反序循环列表: {% for obj in list reversed %} ... {% endfor %} #{% for %}标签能够嵌套: {% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %} #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量, #这个变量含有一些属性能够提供给你一些关于循环的信息 1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 2,forloop.counter0 相似于forloop.counter,但它是从0开始计数,第一次循环设为0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first当第一次循环时值为True,在特别状况下颇有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop变量只能在循环中获得,当模板解析器到达{% endfor %}时forloop就消失了 # 若是你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它 # Django会在for标签的块中覆盖你定义的forloop变量的值 # 在其余非循环的地方,你的forloop变量仍然可用 #{% empty %} {{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %} <li>this is empty!</li> {% endfor %} # [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55
用于生成csrf_token的标签,用于防治跨站攻击验证。注意若是你在view的index里用的是render_to_response方法,不会生效
其实,这里是会生成一个input标签,和其余表单标签一块儿提交给后台的。
<form action="{% url "bieming"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
{% verbatim %} {{ hello }} {% endverbatim %}
步骤:
a、在app中建立templatetags模块(必须的)
b、建立任意 .py 文件,如:my_tags.py
c、在使用自定义simple_tag和filter的html文件中导入以前建立的 my_tags.py :{% load my_tags %}
d、使用simple_tag和filter(如何调用)
e、在settings中的INSTALLED_APPS配置当前app,否则django没法找到自定义的simple_tag.
------------------my_tags.py--------------------- from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改变 @register.filter def filter_multi(v1,v2): return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
-------------------------------.html {% load xxx %} #首行 # num=12 {{ num|filter_multi:2 }} #24 {{ num|filter_multi:"[22,333,4444]" }} {% simple_tag_multi 2 5 %} 参数不限,但不能放在if for语句中 {% simple_tag_multi num 5 %}
注意:
filter能够用在if等语句后,simple_tag不能够
{% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
在讲解了模板加载机制以后,咱们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签容许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,能够是一个变量,也能够是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减小重复。
到目前为止,咱们的模板范例都只是些零星的 HTML 片断,但在实际应用中,你将用 Django 模板系统来建立整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减小共用页面区域(好比站点导航)所引发的重复和冗余代码?
解决该问题的传统作法是使用 服务器端的 includes ,你能够在 HTML 页面中使用该指令将一个网页嵌入到另外一个中。 事实上, Django 经过刚才讲述的 {% include %} 支持了这种方法。 可是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。
本质上来讲,模板继承就是先构造一个基础框架模板,然后在其子模板中对它所包含站点公用部分和定义块进行重载。
让咱们经过修改 current_datetime.html 文件,为 current_datetime 建立一个更加完整的模板来体会一下这种作法:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>The current time</title> </head> <body> <h1>My helpful timestamp site</h1> <p>It is now {{ current_date }}.</p> <hr> <p>Thanks for visiting my site.</p> </body> </html>
这看起来很棒,但若是咱们要为 hours_ahead 视图建立另外一个模板会发生什么事情呢?1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>Future time</title> </head> <body> <h1>My helpful timestamp site</h1> <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> <hr> <p>Thanks for visiting my site.</p> </body> </html>
很明显,咱们刚才重复了大量的 HTML 代码。 想象一下,若是有一个更典型的网站,它有导航条、样式表,可能还有一些 JavaScript 代码,事情必将以向每一个模板填充各类冗余的 HTML 而了结。
解决这个问题的服务器端 include 方案是找出两个模板中的共同部分,将其保存为不一样的模板片断,而后在每一个模板中进行 include。 也许你会把模板头部的一些代码保存为 header.html 文件:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> 你可能会把底部保存到文件 footer.html : <hr> <p>Thanks for visiting my site.</p> </body> </html>
对基于 include 的策略,头部和底部的包含很简单。 麻烦的是中间部分。 在此范例中,每一个页面都有一个<\h1>My helpful timestamp site<\/h1> 标题,可是这个标题不能放在 header.html 中,由于每一个页面的 <\title> 是不一样的。 若是咱们将 <\h1> 包含在头部,咱们就不得不包含 <\title> ,但这样又不容许在每一个页面对它进行定制。 何去何从呢?
Django 的模板继承系统解决了这些问题。 你能够将其视为服务器端 include 的逆向思惟版本。 你能够对那些不一样 的代码段进行定义,而不是 共同 代码段。
第一步是定义 基础模板,该框架以后将由子模板所继承。 如下是咱们目前所讲述范例的基础模板:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html>
这个叫作 base.html 的模板定义了一个简单的 HTML 框架文档,咱们将在本站点的全部页面中使用。 子模板的做用就是重载、添加或保留那些块的内容。 (若是你一直按顺序学习到这里,保存这个文件到你的template目录下,命名为 base.html .)
咱们使用模板标签: {% block %} 。 全部的 {% block %} 标签告诉模板引擎,子模板能够重载这些部分。 每一个{% block %}标签所要作的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。
如今咱们已经有了一个基本模板,咱们能够修改 current_datetime.html 模板来 使用它:
{% extends "base.html" %} {% block title %}The current time{% endblock %} {% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}
再为 hours_ahead 视图建立一个模板,看起来是这样的:
{% extends "base.html" %} {% block title %}Future time{% endblock %} {% block content %} <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> {% endblock %}
看起来很漂亮是否是? 每一个模板只包含对本身而言 独一无二 的代码。 无需多余的部分。 若是想进行站点级的设计修改,仅需修改 base.html ,全部其它模板会当即反映出所做修改。
如下是其工做方式。 在加载 current_datetime.html 模板时,模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。 模板引擎当即装载其父模板,即本例中的 base.html 。
此时,模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的内容替换这些 block 。所以,引擎将会使用咱们在 { block title %} 中定义的标题,对 {% block content %} 也是如此。 因此,网页标题一块将由{% block title %}替换,一样地,网页的内容一块将由 {% block content %}替换。
注意因为子模板并无定义 footer 块,模板系统将使用在父模板中定义的值。 父模板 {% block %} 标签中的内容老是被看成一条退路。
继承并不会影响到模板的上下文。 换句话说,任何处在继承树上的模板均可以访问到你传到模板中的每个模板变量。
你能够根据须要使用任意多的继承次数。 使用继承的一种常见方式是下面的三层法:
这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工做。
如下是使用模板继承的一些诀窍: