HTTPRequest与HTTPresponse 1、 1、互联网两台机器之间通行:ip、端口、协议 - 协议 - HTTP (80) - HTTPS (443) 2、浏览器输入URL一回车返回页面发生了什么? - 域名 -> DNS解析 -->ip地址 -> 找到服务端 ->服务端返回消息 -> 浏览器 - 浏览器 <-> 服务器 - 服务器把 写好的HTML页面,返回给浏览器,浏览器按照HTML格式渲染 「 」 3、请求和相应 - HTTP协议的特色: - 浏览器给服务端发消息的过程叫请求(request) - 服务器给浏览器回复消息的过程叫响应(response) - 请求和相应的消息都必须遵循一个固定的格式 4、python中Web框架分类 - a、收发socket消息,按照HTTP协议解析消息 Web服务程序 wsgiref(模块)、gunicorn、uWSGI - b、字符串替换,用来实现动态网页 - c、业务逻辑处理 Web应用程序 1- 本身实现abc的 - Tronado 2- 本身实现bc使用别人的a - Django 3- 本身实现c使用别人的ab - Flask 五、Web服务程序 <- WSGI协议 -> Web应用程序 5.5、Django版本 - LTS版本 (Long Team support) 6、建立第一个Django项目 安装: pip install django==1.11.11 pip install django==1.11.11 -i 指定源 - 一、命令行 Django-admin startproject first_Django - 2、Pycharm建立 - file -> new Project ->右侧选Django -> 选好路径 ->选好环境 -> 名字app -> 在新的窗口打开文件 - 3、启动项目 - 命令行启动(切换到项目的根目录) - python manage.py runserver 127.0.0.1:8090(改端口这样指定) - pycharm启动 - 框中选项为项目名->让后点击启动按钮(右上角)(若是想改就在旁边点编辑-就能够改端口等) - 目录介绍 - 和项目名同样的是根目录 - --------------------- - 先来一份本身的理解 - 1、(与咱们所建立文件名一致的目录)根目录 - manage.py - 这是启动文件,程序入口。 - settings.py - 包含了项目的一些设置,包括数据库信息、调试标志以及其余的一些工做的变量。 - BASE_DIR = 项目的根目录 - TIMELATES = templates去哪找 - DATABASES = 数据库 - 静态文件配置 - STATIC_URL = '/static/' # 请别名 - STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),] # 配置去static下找静态文件 - urls.py - 路径与视图函数的映射关系 - 二、templates - 这个文件夹存放的是HTML文件 - 三、static - 这个文件夹是存放静态文件,须要本身配置,用的时候的导入时用 /static/.. 来引入所用的静态文件 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ # 这个static就表明了下面的路径 (寻找的时候就是去static下面的路径中挨个找) STATIC_URL = '/static/' # 起别名, HTML中找静态文件都要以这个别名开始 (找到别名后就去这个别名的配置比文件中找对应的文件) # 这个常量是固定格式 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ] 7、项目流程 - 先输入url - 去Django的urls中匹配urlpatterns->匹配上调用后面匹配的函数->去找对应的函数 - 找到执行的函数->Django调用要执行的函数给函数传一个request参数,全部和请求相关的数据 都在request中 - render去templates文件夹找到HTML文件,打开读取内容,按照http响应格式给浏览器返回读取的内容 - 浏览器收到Django返回的响应消息,按照HTML格式显示这个消息 其余: - from django.shortcuts import HttpResponse, render - HttpResponse (封装了协议头等-有待商议) - render (渲染) - 文件的上传(form表单的提交, 必须用POST) def index(request): print(request.GET) print(request.POST) print(request.FILES) for item in request.FILES: fileobj = request.FILES.get(item) f = open('upload/%s' % fileobj.name, 'wb') item_file = fileobj.chunks() for line in item_file: f.write(line) f.close() return HttpResponse("成功") - form表单上传文件时须要注意的事情 - action 最后加 / 或者 修改settings:APPEND_SLASH=False - method 必须为post - enctype = “multipart/form-data” 必须写 - 指定IP登陆 默认IP和端口 python manage.py runserver 指定端口: python manage.py runserver 192.168.12.12:8080 此时会报错,咱们须要修改配置文件: 修改settings.py,将192.168.12.12添加到ALLOWED_HOSTS中 ALLOWED_HOSTS=['172.31.169.182','127.0.0.1','192.168.1.50','192.168.1.115'] 也能够将ALLOWED_HOSTS改为通配符 * ALLOWED_HOSTS = ["*"] 2、 1、表单的提交(登陆) - submit -> action -> 对应函数(参数request(数据信息))-> 处理 注意:必需要有name属性 ***** - 提交到服务器的是QueryDict对象,能够经过get获取值 2、form表单提交的三个要素 - form标签必须有action和method属性 - 全部获取用户输入的标签必须放在form表单中,必须有name属性(input,select,textarea) - 必须有submit按钮 3、redirect 跳转,改变方向 - 跳转到别人的页面,本身的页面 - 跳转比人页面 redirect("https://baidu.com") - 跳转本身页面 redirect("/相对路径/") 四、Django必会三件套 from django.shortcuts import - HttpRequest 返回一个指定的字符串 (把字符串转为而二进制,而后按照HTTP响应格式要求返回) - render 返回一个HTML文件 HTML文件 模板语言 (第一个参数为request, 第二个参数为render的页面,第三个参数为字典,将render页面中的特殊符号替换{字典的键为html的变量,值为给页面展现的值}) - redirect 跳转 路径 URL (redirect(/index/) -> 在同网站不一样地址间跳转(返回重定向响应) redirect('https://wwww.baidu.com') -> 访问指定的网址) 5、request相关属性 (全部和请求相关的数据都封装在request对象中) - POST 取到POST提交的数据(form表单提交的) - GET 取到URL携带的参数 - method 当前此次请求的方法(GET/POST) 6、Django的模板语言 {{ 变量 }} 7、Django项目project - app(应用) -> 不一样的功能放在不一样的app中 - 命令 : - 建立app python manage.py startapp app01(应用名) - 注册app(告诉Django建立了app) 在settings中的 INSTALLED_APPS 添加新建立的app(app名.apps.apps中的类) 8、程序连接mysql - 使用pymysql模块 - 导入pymysql - 建立连接 - 获取执行命令的游标 - 用游标执行SQL语句 - 获取SQL语句的执行结果 - 关闭游标 - 关闭连接 - ORM - Object Relationship Mapping (对象关系映射) - 这时,建立一种工具 帮助咱们翻译SQL语句(ORM - 面向对象的思想) - 优势 - 开发效率高 - 开发不用直接写SQL语句 - 缺点 - 执行效率低 - 对应关系 ORM DB 类 数据表 属性 字段 对象 数据行 - Django项目project - app(应用) -> 不一样的功能放在不一样的app中 - 命令 : - 建立app python manage.py startapp app01(应用名) - 告诉Django建立了app 在settings中的 INSTALLED_APPS 添加新建立的app(app名.apps.apps中的类) - Django中ORM使用 - 用处: - 操做数据表 - 操做数据行 - 使用 - 手动建立数据库 - 告诉Django连那个数据库 - settings中配置DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 连接数据库的类型 'NAME': 'db', # 连接数据库的名字 'HOST': '127.0.0.1', # 数据库主机地址 'PORT': 3306, # 数据库端口 'USER': 'root', # 数据库用户名 'PASSWORD': '123456', # 数据库密码 } } - 用什么连接数据库? - 利用第三方包 pymysql 和 MySQLdb(py2中) - 告诉Django用pymysql模块代替默认的MySQLdb连接MySQL数据库 和settings.py同级的__init__.py文件,写上 import pymysql pymysql.install_as_MySQLdb() - 在app/models.py的文件中建立类 类必须继承models.Model - 两个命令 - python manage.py makemigrations -> 生成脚本文件存放在app文件夹应用下的migrations文件夹中(至关于拿个小本本把models.py的变动记录下来) - python manage.py migrate -> 把上面的变动记录翻译成sql语句,去数据库执行 - ORM查询 modules.User.object.filter(email='', pwd='') 3、 1、图书管理系统 - 出版社 id name - 做者 id name - 书 id title 出版社_id - 书_做者关系表 id 书_id 做者_id 2.ORM增删改查 models.表名.object./filter()/all()/create() - filter() 按照指定内容筛选 (字段=值) 放回一个列表 - all() 查询出数据库全部信息(属性order_by(id)排序) 返回一个列表 - create() 向数据库添加信息 (字段=值)建立一个对象 返回一个建立的对象 - get() 返回一个对象 - filter(id='').delete() 删除 - obj = 类名.object.get(id='') obj.name = '新值' 修改对象的属性(修改数据行某个字段的值) obj.save() 把修改同步到数据库 3、模板语言 - for循环 {% for i in ret %} {{ i }} {{ forloop.counter }} for循环从1开始计数 {{ forloop.counter0 }} for循环从0开始计数 {% endfor %} 总结:ORM的 查、增、删、改 - 查 - client - 有一个展现页面(xxx_show.html) - 这一个页面一输入执行后,get请求向server端发送 - 这个展现页面有添加按钮、删除按钮、编辑按钮 - 这个页面要展现内容 - 是server端收到第一次的get请求而作出的response - 页面须要用到模板语言for循环 {% for i in result %} {{ i.xx }} #获取result中的每一个值(也就是server端传来的东西) {% endfor %} - server - 首先会收到一开始访问页面的GET请求 - 收到请求后到urls中找匹配的url,找到对应的url后,执行后面所对应的视图函数 - 找到对应的视图函数后就行执行响应的逻辑,也就是拿出数据库中的东西,发送给server - 能够经过 models.表名.objects.all() 获取数据库这张表中的全部内容(返回一个列表) - data = models.表名.objects.all() - 拿到数据后将这些数据给展现(经过render方法) - return render(request, 'xxx_show.html', 'result':data) #这里的result就是要传给xxx_show.html的一个变量(其中的值就是data的数据) - 增 - client - 有一个展现页面(xxx_show.html) - 这个页面有一个添加按钮(a标签) - 点击这个按钮(a标签),client会发送一个get请求,会用a标签的路径去访问server - 这时会跳转到a标签所指的url(/add_xxx/) - 而后server给出response(这里的业务逻辑就都得在server) - 第一次get请求server会返回一个add_xxx.html页面 - 这是能够添加数据 - 用form表单,action为add_xxx这个url,method为post - 点击提交以后client向server发送一个请求 - server收到请求后回复一个response - server - 收到a标签跳转的url(get请求响应) - 收到add_xxx这个url进入urls中匹配,匹配到就去他对应的视图函数 - 这个视图函数处理响应的业务逻辑 - 首先第一次来的时候时GET请求,这个时候应该将add_xxx.html这个页面返回给client - return render(request, add_xxx.html) - 而后server收到提交的POST请求 - 从POST请求中拿出client发送来的数据 - data = request.POST.get("input标签的name") - 将数据存入数据库 - models.tablename.objects.create(字段=data) - 将数据库中的结果从新返回(也就是xxx_show。html) - return redirect('/xxx_show/') - 删 - client - 有一个展现页面(xxx_show.html) - 有一个删除按钮(a标签) - 点击这个按钮(a标签),client会发送一个get请求,会用a标签的路径去访问server - 点击这个a标签(按钮)会跳转到他对应的url('/del_xxx/') - 这时须要将这个按钮对应的数据传到server,server才能按照这个数据去删除 - <a href="/del_xxx/?id={{ i.id }}"><button>del</button></a> - ?是一个固定格式,然后面就是一些参数(服务端要用的一些参数) - server收到这个参数后就能够按照他进行相应的操做 - 而后server会返回一个response(这里的业务逻辑在server端) - server - 收到a标签跳转的url(get请求响应) - 收到del_xxx这个url进入urls中匹配,匹配到就去他对应的视图函数 - 这个视图函数处理响应的业务逻辑 - 经过client传来的参数来锁定删除的id - del_id = request.GET.get("id") - 删除数据库中del_id对应的值 - models.tablename.objects.fileter(id=del_id).delete() - 删除成功后返回删除后的页面('/xxx_show/')(重定性) - return redirect('/xxx_show/') - 改 - client - 有一个展现页面(xxx_show.html) - 有一个编辑(edit)按钮(a标签) - 点击这个按钮(a标签),client会发送一个get请求,会用a标签的路径去访问server - 点击这个a标签(按钮)会跳转到他对应的url('/edit_xxx/') - 这时须要将这个按钮对应的数据传到server,server才能更改这个数据 - <a href="/edit_xxx/?id={{ i.id }}"><button>del</button></a> - ?是一个固定格式,然后面就是一些参数(服务端要用的一些参数) - server收到这个参数后就能够按照他进行相应的操做 - 而后server会返回一个response(这里的业务逻辑在server端) - 第一次发送get请求时会跳转到edit_xxx.html这个页面,这里面是该行对应的数据 - 第二次发送post请求,这里面会有修改后的数据而后发送给server处理 - <form action="/edit_press/?id={{ result.id }}" method="post"> <input type="text" name="updata_name" value="{{ result.name }}"> <input type="submit"> </form> - input中的数据都是在server查出的数据展示出来的 - id是经过点击edit按钮的时候将这个按钮对应的id值记录了下来 - 处理完后返回原来的xxx_show - server - 收到a标签跳转的url(get请求响应) - 收到edit_xxx这个url进入urls中匹配,匹配到就去他对应的视图函数 - 这个视图函数处理响应的业务逻辑 - 第一遍的GET请求 - 经过client传来的参数来锁定编辑(edit)的id - edit_id = request.GET.get("id") - 会返回当前编辑行的内容 - 从数据库中拿出这个值,将这个值展示在edit_xxx.html页面中 - result = models.tablename.objects.filter(id="")[0] - 返回当前编辑的页面 - return render(request, 'edit_xxx.html', {'resule': result}) - 第二遍请求是提交数据后的POST请求, - form表单中的action为这个编辑页面, - 这个页面后面的参数为第一次get请求获得的数据 - 能够经过GET方法来获取URL上的参数的值 - 这个时候form表单对应的url来urls中找对应的视图函数 - 这个视图函数就会执行POST请求的逻辑 - 用这个新数据把数据库中的旧数据掩盖 - 获取更改后的值 - data = request.POST.get("updata_name") - 更改数据库中的值 - 从数据库找到id对应的对象 - #这里的id就是第一次点击编辑的时候获得的id值(--对应的) - new_obj = models.tablename.objects.filter(id='edit_id')[0] - new_obj.name = data #将新的值赋值给数据库中的变量 - new_obj.save() #这个事务必须save数据库中的数据才会更改 - 更改完成后返回,xxx_show页面 - return redirect('/xxx_show/') 注意: 经过GET来获取URL中的值(和请求无关),POST获取表单提交的值。 4、 1、 a标签 - href属性 - 相对路径 - 绝对路径 - target = "_blank" 跳转到新页面, 不写默认覆盖本身的页面 - 锚点(同网站标签的跳转(#id名)) 2、 # 出版社 class Press(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) def __str__(self): # print的时候测试使用 return self.name # 书 class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) # Django1.1默认就是级联删除,2.0必须指定 # 能够经过字符串的反射找Press,若是在代码前面就能够直接用,to=关联的表名 # 外键字段ORM会给他默认加一个_id (加上_id后他的值就是对应关联表的主键值) press = models.ForeignKey(to='Press', on_delete=models.CASCADE) - 一对多 - 一个出版社对应多本书(外键设置在多的一方) - 书的属性有一个外键为连接出版社的press_id 书籍的增删改查 - 增 - 删 - 改 - 查 注意: - 增的时候,出版社就是表中的固定出版社,用一个select标签将数据展现,而不是用户本身填 <form action="/add_book/" method="post"> 书名:<input type="text" name="book_title"> <select name="title_name" id=""> {% for press in data %} <option value="{{ press.id }}"> {{ press.name }} </option> {% endfor %} </select> <input type="submit"> </form> - 改的实时,出版社的内容须要先选定好。须要用模板语言来判断 # 这中状况form表单不指定action他默认会提交当前的页面(这是的页面是点击编辑时的页面) <form action="/edit_book/?id={{ data.id }}" method="post"> <input type="text" name="title_name" value="{{ data.title }}"> <select name="press_name" id=""> {% for press in data_list %} {% if data.press == press %} <option value="{{ press.id }}" selected> </option> {{ press.name }} {% else %} <option value="{{ press.id }}"> {{ press.name }} </option> {% endif %} {% endfor %} </select> <input type="submit"> </form> 5、 - 给数据库中已经存在的表添加另一个字段,ORM不知道如何处理 - 1) 输入 1 会让用户本身填写一个默认值(在命令行中) - 2) 输入 2 本身在ORMclass中指定字段本身加默认值(退出命令行)在modules中修改 - null = True - default = 默认值 1. 多对多关系 做者 <--> 书籍 1. 表结构设计 1. SQL版 -- 建立做者表 create table author( id int primary key auto_increment, name varchar(32) not null ); -- 建立做者和书的关系表 create table author2book( id int primary key auto_increment, author_id int not null, book_id int not null, constraint fk_author foreign key (author_id) references author(id) on delete cascade on update cascade, constraint fk_book foreign key (book_id) references book(id) on delete cascade on update cascade ); 2. ORM版 1. 初版: 本身建立第三张表 2. 第二版 让ORM帮咱们建立第三张表 models.ManyToManyField() 3. 第三版 待补充...(ORM进阶操做的时候) 2. 做者的增删改查 1. 查询 author_obj.books --> 获得的只是一个关联关系,并不能拿到数据 author_obj.books.all() --> 获得和我这个做者关联的全部书籍对象列表 2. 添加 1. getlist() # 获得同一name的列表对象 2. add() 3. set() 3. 删除 4. 编辑 1. 模板语言中 {% if book in author.books.all %} 2. ORM编辑多对多 1. 不能直接操做第三张关系表 2. 借助ORM给提供的方法 1. all() 2. add(id1,id2) 3. set([id1, id2]) 4. clear() 3. Django模板语言 1. for循环 1. forloop.last {% if forloop.last %} ... 2. empty {% for i in x %} ... {% empty %} ... {% endfor %} 4. 上传文件 form表单上传文件 # 文件的上传 def index(request): print(request.FILES) # 上传的文件列表对象 for item in request.FILES: fileobj = request.FILES.get(item) # 挨个获取列表中每一个对象 f = open('upload/%s' % fileobj.name, 'wb') item_file = fileobj.chunks() for line in item_file: f.write(line) f.close() return HttpResponse("成功") 2. 学生管理系统 - 老师 和 班级 是多对多的关系 6、Django模板系统(模板语言)(very important) - 基础语法 - 跟变量相关 {{ }} 在Django的模板语言中按此语法使用:{{ 变量名 }}。 当模版引擎遇到一个变量,它将计算这个变量,而后用结果替换掉它自己。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。 点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询: ***** 属性->方法->索引 字典查询(Dictionary lookup) 属性或方法查询(Attribute or method lookup) 数字索引查询(Numeric index lookup) 注意事项: 若是计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。 若是使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。 {# 取l中的第一个参数 #} {{ l.0 }} {# 取字典中key的值 #} {{ d.name }} {# 取对象的name属性 #} {{ person_list.0.name }} {# .操做只能调用不带参数的方法 #} {{ person_list.0.dream }} - Filter过滤器 在Django的模板语言中,经过使用 过滤器 来改变变量的显示。 过滤器的语法: {{ value|filter_name:参数 }} 使用管道符"|"来应用过滤器。 例如:{{ name|lower }}会将name变量应用lower过滤器以后再显示它的值。lower在这里的做用是将文本全都变成小写。 注意事项: 过滤器支持“链式”操做。即一个过滤器的输出做为另外一个过滤器的输入。 过滤器能够接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。 过滤器参数包含空格的话,必须用引号包裹起来。好比使用逗号和空格去链接一个列表中的元素,如:{{ list|join:', ' }} '|'左右 没有空格没有空格没有空格 ****** Django的模板语言中提供了大约六十个内置过滤器 - 一些经常使用的过滤器 - default 若是一个变量是false或者为空,使用给定的默认值。 不然,使用变量的值。 {{ value|default:"nothing"}} 若是value没有传值或者值为空的话就显示nothing 注:TEMPLATES的OPTIONS能够增长一个选项:string_if_invalid:'找不到',能够替代default的的做用。 - length 返回值的长度,做用于字符串和列表。 {{ value|length }} 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4. - filesizeformat 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如: {{ value|filesizeformat }} 若是 value 是 1234567890,输出将会是 1.1GB。 - slice 切片 {{value|slice:"2:-1"}} - add 给变量加参数 {{ value|add:"2" }} value是数字4,则输出结果为6。 {{ first|add:second }} 若是first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。 - data 格式化 {{ value|date:"Y-m-d H:i:s"}} 可用的参数: 格式化字符 描述 示例输出 a 'a.m.'或'p.m.'(请注意,这与PHP的输出略有不一样,由于这包括符合Associated Press风格的期间) 'a.m.' A 'AM'或'PM'。 'AM' b 月,文字,3个字母,小写。 'jan' B 未实现。 c ISO 8601格式。 (注意:与其余格式化程序不一样,例如“Z”,“O”或“r”,若是值为naive datetime,则“c”格式化程序不会添加时区偏移量(请参阅datetime.tzinfo) 。 2008-01-02T10:30:00.000123+02:00或2008-01-02T10:30:00.000123若是datetime是天真的 d 月的日子,带前导零的2位数字。 '01'到'31' D 一周中的文字,3个字母。 “星期五” e 时区名称 多是任何格式,或者可能返回一个空字符串,具体取决于datetime。 ''、'GMT'、'-500'、'US/Eastern'等 E 月份,特定地区的替表明示一般用于长日期表示。 'listopada'(对于波兰语区域,而不是'Listopad') f 时间,在12小时的小时和分钟内,若是它们为零,则分钟停留。 专有扩展。 '1','1:30' F 月,文,长。 '一月' g 小时,12小时格式,无前导零。 '1'到'12' G 小时,24小时格式,无前导零。 '0'到'23' h 小时,12小时格式。 '01'到'12' H 小时,24小时格式。 '00'到'23' i 分钟。 '00'到'59' I 夏令时间,不管是否生效。 '1'或'0' j 没有前导零的月份的日子。 '1'到'31' l 星期几,文字长。 '星期五' L 布尔值是不是一个闰年。 True或False m 月,2位数字带前导零。 '01'到'12' M 月,文字,3个字母。 “扬” n 月无前导零。 '1'到'12' N 美联社风格的月份缩写。 专有扩展。 'Jan.','Feb.','March','May' o ISO-8601周编号,对应于使用闰年的ISO-8601周数(W)。 对于更常见的年份格式,请参见Y。 '1999年' O 与格林威治时间的差别在几小时内。 '+0200' P 时间为12小时,分钟和'a.m。'/'p.m。',若是为零,分钟停留,特殊状况下的字符串“午夜”和“中午”。 专有扩展。 '1 am','1:30 pm' / t3>,'midnight','noon','12:30 pm' / T10> r RFC 5322格式化日期。 'Thu, 21 Dec 2000 16:01:07 +0200' s 秒,带前导零的2位数字。 '00'到'59' S 一个月的英文序数后缀,2个字符。 'st','nd','rd'或'th' t 给定月份的天数。 28 to 31 T 本机的时区。 'EST','MDT' u 微秒。 000000 to 999999 U 自Unix Epoch以来的二分之一(1970年1月1日00:00:00 UTC)。 w 星期几,数字无前导零。 '0'(星期日)至'6'(星期六) W ISO-8601周数,周数从星期一开始。 1,53 y 年份,2位数字。 '99' Y 年,4位数。 '1999年' z 一年中的日子 0到365 Z 时区偏移量,单位为秒。 UTC以西时区的偏移量老是为负数,对于UTC以东时,它们老是为正。 -43200到43200 - safe Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。 可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的 文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本, 若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有 两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安 全的没必要转义。 好比: value = "<a href='#'>点我</a>" {{ value|safe}} - truncchars 若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 参数:截断的字符数 {{ value|truncatechars:9}} - truncatewords 在必定数量的字后截断字符串。 {{ value|truncatewords:9}} - cut 移除value中全部的与给出的变量相同的字符串 {{ value|cut:' ' }} 若是value为'i love you',那么将输出'iloveyou'. - join 使用字符串链接列表,例如Python的str.join(list) - timesince 将日期格式设为自该日期起的时间(例如,“4天,6小时”)。 采用一个可选参数,它是一个包含用做比较点的日期的变量(不带参数,比较点为如今)。 例如,若是blog_date是表示2006年6月1日午夜的日期实例,而且comment_date是2006年6月1日08:00的日期实例,则如下将返回“8小时”: {{ blog_date|timesince:comment_date }} 分钟是所使用的最小单位,对于相对于比较点的将来的任何日期,将返回“0分钟”。 - timeuntil 似于timesince,除了它测量从如今开始直到给定日期或日期时间的时间。 例如,若是今天是2006年6月1日,而conference_date是保留2006年6月29日的日期实例,则{{ conference_date | timeuntil }}将返回“4周”。 使用可选参数,它是一个包含用做比较点的日期(而不是如今)的变量。 若是from_date包含2006年6月22日,则如下内容将返回“1周”: {{ conference_date|timeuntil:from_date }} - 自定义filter - 自定义过滤器只是带有一个或两个参数的Python函数: 变量(输入)的值 - -不必定是一个字符串 参数的值 - 这能够有一个默认值,或彻底省略 例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”。 - 建立 (步骤) - 先在app目录下建立一个templatetagspython包(名字必须这个) - 在目录中建立一个py文件 - 在py文件中按照固定的格式自定义一个filter(就是一个函数) - 须要先导入 from django import template # 固定写法,生成一个注册实例对象 register = template.Library() @register.filter() # 告诉Django的模板语言我如今注册一个自定义的filter def add_str():pass # 第一个参数是变量名, 第二个参数为参数(最多一个) - 使用: - 重启DJango项目 - 在HTML页面中:{% load python文件名 %} - {{ name|add_str:'好人啊' }} - 例子: - 自定义过滤器只是带有一个或两个参数的Python函数: 变量(输入)的值 - -不必定是一个字符串 参数的值 - 这能够有一个默认值,或彻底省略 例如,在过滤器{{var | foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”。 - 自定义filter代码文件摆放位置: app01/ __init__.py models.py templatetags/ # 在app01下面新建一个package package __init__.py app01_filters.py # 建一个存放自定义filter的py文件 views.py - 编写自定义filter from django import template register = template.Library() @register.filter def fill(value, arg): return value.replace(" ", arg) @register.filter(name="addSB") def add_sb(value): return "{} SB".format(value) - 使用自定义filter {# 先导入咱们自定义filter那个文件 #} {% load app01_filters %} {# 使用咱们自定义的filter #} {{ somevariable|fill:"__" }} {{ d.name|addSB }} - 注意:过滤器能够连接 {{ text|escape|linebreaks }} 就是一个经常使用的过滤器链,它编码文本内容,而后把行打破转成<p> 标签。 - 跟逻辑相关 {% %} - 语法为:{% tag %} - for <ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul> for循环可用的一些参数: Variable Description forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(从1开始) forloop.revcounter0 当前循环的倒序索引值(从0开始) forloop.first 当前循环是否是第一次循环(布尔值) forloop.last 当前循环是否是最后一次循环(布尔值) forloop.parentloop 本层循环的外层循环(是个字典) forloop是一个字典 - for ... empty <ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空空如也</li> {% endfor %} </ul> - if,elif和else {% if user_list %} 用户人数:{{ user_list|length }} {% elif black_list %} 黑名单数:{{ black_list|length }} {% else %} 没有用户 {% endif %} 固然也能够只有if和else {% if user_list|length > 5 %} 七座豪华SUV {% else %} 黄包车 {% endif %} 注: - if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。 - with (就至关于起了一个别名) - {% with p1.dream as dream %} {{ dream }} # dream 代替p1.dream {% endwith %} - 定义一个中间变量 {% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %} - csrf_token - 这个标签用于跨站请求伪造保护。 - 在页面的form表单里面写上{% csrf_token %} - 用这个后就能够将中间件打开(这样就安全了,知道是我可以收取的) - 在表单中添加了一个隐藏的input标签 - name csrfmiddlewaretoken - value asksdasdas(64位) - # 注释 - {# ... #} - 母版(一个普通的html文件) block extends - 减小代码的重复 - 母版写好 - 不一样的地方用如下占位 - {{ block contenter(name) }} {{ endblock }} - 子文件 - {% extends '母版html' %} # 继承母版 - {% block contenter(name) %} # 将母版中的站好位置额contenter填充 本身的html文件 {% endblock %} - 注意事项: - {% extends '母版html' %} # 继承母版 必须写在开头 - {% extends name %} name写继承的模板的名字字符串 - 自定义的内容写在block中 - 定义多个block块,通常要有js css - 注意事项 - Django的模板语言不支持连续判断,即不支持如下写法: {% if a > b > c %} ... {% endif %} - Dja的模板语言中属性的优先级大于方法 def xx(request): d = {"a": 1, "b": 2, "c": 3, "items": "100"} return render(request, "xx.html", {"data": d}) 如上咱们在使用render方法渲染一个页面的时候,传的字典d有一个key是items而且还有默认的 d.items() 方法,此时在模板语言中: {{ data.items }} 默认会取d的items key的值。 - 组件 include - 能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方按以下语法导入便可。 {% include 'navbar.html' %} - 静态文件相关(动态拿取STATIC_URL配置的名字) - {% load static %} <img src="{% static "images/hi.jpg" %}" alt="Hi!" /> 引用JS文件时使用: {% load static %} <script src="{% static "mytest.js" %}"></script> 某个文件多处被用到能够存为一个变量 {% load static %} {% static "images/hi.jpg" as myphoto %} <img src="{{ myphoto }}"></img> - get_static_prefix {% load static %} <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" /> 或者 {% load static %} {% get_static_prefix as STATIC_PREFIX %} <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" /> - 自定义simpletag 和自定义filter相似,只不过接收更灵活的参数。 定义注册simple tag @register.simple_tag @register.simple_tag(name="plus") def plus(a, b, c): return "{} + {} + {}".format(a, b, c) 使用自定义simple tag {% load app01_demo %} {# simple tag #} {% plus "1" "2" "abc" %} - inclusion_tag - 多用于返回html代码片断 - 步骤 - 在app下建立templatetags的python包 - 在包下写py文件 mytags - 编辑文件 - from django import template - register = template.Library() - 定义函数 - 可接受参数 - 返回一个字典 - 函数加装饰器 - @register.inclusion_tag('result.html') 示例: templatetags/my_inclusion.py from django import template register = template.Library() @register.inclusion_tag('result.html') def show_results(n): n = 1 if n < 1 else int(n) data = ["第{}项".format(i) for i in range(1, n+1)] return {"data": data} templates/result.html <ul> {% for choice in data %} <li>{{ choice }}</li> {% endfor %} </ul> templates/index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>inclusion_tag test</title> </head> <body> {% load my_inclusion %} {% show_results 10 %} </body> </html> - 细节 input data属性 value='是一个“-”连接的字符串'