目录
- Django
- HTTP协议:
- HTTP工作原理(重要):
- web框架
- Django安装简单使用
- orm-增删改查:
- ORM一对多关系:
- 外键的设计
- 增删改查
- ORM 多对多关系:
- 多对多关系创建
- 多对多-增删改查
- 模板使用:
- MVC 和 MTV
- 变量
- 过滤器-Filters
- for 循环
- if 判断
- with和csrf_token
- 母板和继承
- 组件
- 静态文件相关
- 定义 filter simple_tag inclusion_tag
- 视图
- CBV的流程
- 视图加装饰器
- request:
- response
- 路由
- 正则表达式
- 分组和命名分组
- 路由分发include:
- 命名URL和URL反向解析
- namesapce 名称空间
- 示例:
- ORM
- admin
- ORM 常用字段
- 字段参数
- 表的参数
- 必会13条查询语句:
- 外键查询:
- 多对多
- 聚合
- 分组
- F和Q
- 事务
- Cookie
- cookies和session区别:
- 原理
- django中操作cookies
- 参数:
- Cookie应用示例:
- session
- django中的操作:
- session代码示例:
- 中间件
- 定义中间件
- process_request
- process_response
- process_view
- process_exception
- process_template_response
- 中间件示例
Django
HTTP协议:
Socket和Tcp协议关系:
socket本身并不是协议而是一个调用的接口,socket的出现使我们更方便的使用tcp协议,如socket的基本接口,listen send recv
HTTP协议概述:
HTTP存在应用层的超文本传输协议,协议规定了客户端和服务器之间的通信标准,采用的是请求和响应模型,客户端发送一个请求报文,服务端进行响应
请求格式和响应格式:
HTTP工作原理(重要):
第一步:客户端连接web服务端
客户端连接服务端,会建立一个TCP套接字连接,(套接字就是socket,客户端通常是浏览器)
第二步:发送http请求
通过TCP套接字,客户端向web服务端发送一个文本的请求报文,一个请求报文由请求行,请求头部,和请求数据组成
第三步:服务器接收请求并返回HTTP响应
响应就是服务端分析发送过来的请求,通过解析请求定位到资源,服务器将资源写到tcp套接字中,返回给客户端
第四步:释放tcp连接
如果connection模式为close时,服务端主动关闭tcp连接,客户端被动关闭连接,释放tcp,若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求
第五步:客户端浏览器解析HTML内容
客户端浏览器首先解释状态行,查看请求的状态码是否成功,然后解析每一个响应头,客户端浏览器读取响应数据的HTML,在根据HTML语法在浏览器窗口中进行展示
浏览器地址栏输入URL,流程:
浏览器向DNS服务器请求解析该URL中的域名对应的IP地址
解析出IP地址,根据IP地址和默认端口,和服务器建立TCP连接
浏览器发送HTTP请求(包含url后面对应的文件路径),该请求报文由TCP第三次握手发送给服务器
服务器对浏览器做出相应,将对应的html返回给浏览器
释放TCP连接
浏览器将该html文本进行展示
HTTP 请求方法
HTTP/1.1协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源:
GET:
- 向指定资源发出显示请求,使用GET方法只用在读取数据,
POST:
- 向指定资源提交数据,请求服务器进行处理(如提交表单或者上传文件),数据被包含在请求文本中
HEAD:
与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据
其余请求:
put 向指定资源位置上传其最新内容
delete 请求服务器删除Request-URI所标识的资源。
trace 回显服务器收到的请求,主要用于测试或诊断
options 使服务器传回该资源所有http请求方法
connect HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
请求注意事项:
方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)
HTTP 状态码
1xx消息——请求已被服务器接收,继续处理
2xx成功——请求已成功被服务器接收、理解、并接受
3xx重定向——需要后续操作才能完成这一请求
4xx请求错误——请求含有词法错误或者无法被执行 404:没有内容 403:没有权限
5xx服务器错误——服务器在处理某个正确请求时发生错误
URL
超文本传输协议,统一资源定位获取五个基本元素,
https://www.sogou.com/web?query=新闻&_asf=www.sogou.com&_ast=&w=0 # http 传送协议 # // 层级URL表示符号,固定格式 # www.sogou.com 域名,服务器和:端口号 #/ 区分每个路径的的目录 #/web 页面路径 #?query=新闻 GET模式查询的窗口参数(?字符为起点,每个参数以&隔开,再以=分开参数名称和数据) # 锚点 请求(浏览器发给服务器的数据 request0 请求方法,路径,协议版本\r\n #请求行 k1:v1\r\n k2:v2\r\n #请求头 \r\n 请求数据 #get请求美哦与请求体 响应(服务端返回给浏览器的数据 respons) 格式: "协议版本" 状态码 状态描述 \r\n k1:v1\r\n k2:v2\r\n \r\n 响应数据(响应体)"html文本"
web框架
web框架的本质都是一个socket服务端,而用户浏览器就是一个socket客户端部,这样就实现了web框架
web框架的功能:
使用socket收发消息 (wsgiref wsgi模块也可以收发消息,uwsgi线上使用)
根据不同路径返回不同的内容
返回动态的数据(字符串的替换 模板的渲染 jinja2)
分类:
Django 2 3
Flask 2
tornado 1 2 3
自己写web框架:
框架示例:
import socket import time sk = socket.socket() # 创建一个socket对象 sk.bind(('127.0.0.1',667)) # 绑定ip和端口 sk.listen() # 监听 def index(url): with open('index.html', 'rb') as f: #读取index标签 return f.read() def home(url): ret = '欢迎回家! - {}'.format(url) return ret.encode('utf-8') def help_me(url): ret = '再等30年,你又是条好汉! - {}'.format(url) return ret.encode('utf-8') def timer(url): now = time.time() with open('time.html','r',encoding='utf-8') as f: ret = f.read() ret = ret.replace('@@time@@',str(now)) #将获取的时间在time中替换展示在页面上 return ret.encode('utf-8') list1 = [ ('/index', index), ('/home', home), ('/help_me', help_me), ('/time', timer),] while True: conn, addr = sk.accept() # 等待连接 data = conn.recv(1024) url = data.decode('utf-8').split()[1] func = None for i in list1: if url == i[0]: func = i[1] break if func: ret = func(url) else: ret = '被查办了!'.encode('utf-8') conn.send(b'HTTP/1.1 200 OK\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') conn.send(ret) conn.close() # index页面:
Title 欢迎光临!
# time页面:Title 当前时间是:@@time@@
Django安装简单使用
安装Django:
命令行方法:
使用django必须是专业版
pip3 install django==1.11.23 -i https://pypi.tuna.tsinghua.edu.cn/simple (清华源速度快)
查看是否安装成功:
查看此目录是否有django-admin.exe
D:\Program Files (x86)\python3.6.8\Scripts
创建项目:
命令行创建:
- django-admin startproject 项目名称
pycharm创建:
flie _ new_project _ django _ 项目路径 选解释器
创建后的项目目录:
xiangmu/ ├── idea # pycharm环境 ├── manage.py # 管理文件 ├─— templates # html css样式目录 └── xiangmu # 项目目录 ├── __init__.py ├── settings.py # 配置 ├── urls.py # 路由 --> URL和函数的对应关系 └── wsgi.py # runserver命令就使用wsgiref模块做简单的web server settings.py配置文件: ALLOWED_HOSTS = ['*'] #设置可以访问的主机,*=所有 TEMPLATES-->DIRS #关联html css文件位置 urls.py URL路径地址:
启动项目:
命令行:
#进入python目录进行启动 python manage.py runserver 127.0.0.1:8000 python manage.py runserver 127.0.0.1:80 python manage.py runserver 0.0.0.0:80
pycharm:
pycharm 点绿三角, 不要右键运行文件
Django项目创建步骤:
下载
命令行:
pip install django==1.11.23
pip install django==1.11.23 -i 源的地址
pycharm
file——》 settings ——》解释器 ——》 点+号 ——》 输入django ——》 选择版本 ——》下载
创建项目
命令行:
切换到存项目的目录下
django-admin startproject 项目名
pycharm:
file ——》 new project ——》 django ——》 输入项目的路径 ——》 选择解释器 ——》 写一个APP的名字 ——》 create
启动项目
命令行:
切换进去到项目的根目录 manage.py
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80
pycharm:
点绿三角 启动 确定是django项目
可配置ip和端口
配置settings
静态文件
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,’static‘),
os.path.join(BASE_DIR,’static1‘),
]
中间件
csrf 中间件注释掉 可以提交POST请求
INSTALLED_APPS app相关
数据库
模板 DIRS
APP
创建app
命令行:
python manage.py startapp app名称
pycharm:
tools ——》 run manage.py task ——》 startapp app名称
注册app
INSTALLED_APPS = [ # 'app01', 'app01.apps.App01Config', ]
urls.py
urlpatterns = [ url(r'^index/', views.index), url(r'^home/', views.home), url(r'^login/', views.login), ]
views.py
from django.shortcuts import HttpResponse, render, redirect def index(request,): return HttpResponse()
HttpResponse('字符串') 返回字符串
render(request,'html文件名') 返回一个html页面
redirect(’重定向的地址‘) 重定向
form表单
form标签的属性 action ='' 提交的地址 method=’post‘ 请求方式 novalidate 不校验
input标签要有name 有些需要value
有一个类型为submit的input或者 button
get 和post的分别
get 获取一个页面
没有请求体
?k1=v1&k2=v2
django 中获取 request.GET request.GET['k1'] request.GET.get('k1','xxxx')
post 提交数据 数据隐藏
django 中获取 request.POST request.POST['k1'] request.POST .get('k1','xxxx')
orm-增删改查:
__str__和__repr__区别
:有时候我们想让屏幕打印的结果不是对象的内存地址,而是它的值或者其他可以自定义的东西,以便更直观地显示对象内容,可以通过在该对象的类中创建或修改__str__()或__repr__()方法来实现(显示对应方法的返回值) # 两种触发方式: 使用print()时 使用%s和f'{}'拼接对象时 使用str(x)转换对象x时 在上述三种场景中,会优先调用对象的__str__()方法;若没有,就调用__repr__()方法;若再没有,则显示其内存地址。 # 特别地,对于下面两种场景: 用%r进行字符串拼接时 用repr(x)转换对象x时 则会调用这个对象的__repr__()方法;若没有,则不再看其是否有__str__()方法,而是显示其内存地址
创建表数据
from django.db import models class Publisher(models.Model): # Publisher:表名,继承models.Model类 pid = models.AutoField(primary_key=True) # 自增、主键 name = models.CharField(max_length=32,unique=True) def __str__(self): return "{}{}".format(self.pid,self.name) # 返回给调用者内容
查询展示数据:
#查询所有数据 all_publisher = models.Publisher.objects.all() #将数据返回到前端 return render(request,'publisher_list.html',{'all_publisher':all_publisher}) #展示数据 from django.shortcuts import render,HttpResponse,redirect from app import models #从数据库中展示数据 #从数据库中查询出所有的出版社 #从数据库中查询的数据展示到前端页面 def publisher_list(request): all_publisher = models.Publisher.objects.all().order_by('pid') return render(request,'publisher_list.html',{'all_publisher':all_publisher})
模板的语法:
{{ all_publishers }} 变量 {% for i in all_publishers %} #for循环 {{ forloop.counter }} #循环打印的内容 {{ i }} {% endfor %} #闭合
新增数据:
# 方式一:通过create将数据插入到数据库中(推荐) ret = models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list") #方式二:先创建对象在save进行保存 obj = models.Publisher(name=pub_name) obj.save() #新增出版社 def publisher_add(request): pub_name,error='','' if request.method == "POST": #判断前端是POST类型还是GET类型 pub_name = request.POST.get('pub_name') #通过POST获取前端的出版社名称 if not pub_name: error = "输入不能为空" elif models.Publisher.objects.filter(name=pub_name): error = "数据已经存在" else: #通过create将数据插入到数据库中(推荐) models.Publisher.objects.create(name=pub_name) return redirect("/publisher_list") return render(request, 'publisher_add.html', {'pub_name': pub_name, 'error': error})
删除数据
pk = request.GET.get('pk') query = models.Publisher.objects.filter(pk=pk) # 对象列表 query.delete() # 通过queryset 删除 query[0].delete() # 通过单独的对象 删除 # 删除数据 def publisher_del(request): pk_id = request.GET.get('pk') # 获取前端URL数据 query = models.Publisher.objects.filter(pk=pk_id) if not query: return HttpResponse("要删除的数据不存在") query.delete() # 参数有多个删除多个,query[0].delete()#只删除一个 return redirect("/publisher_list")
编辑数据
obj = models.Publisher.objects.filter(pk=pk).first() # 对象列表中第一个对象 obj.name = pub_name # 内存中修改 obj.save() # 提交 #编辑数据 def publisher_edit(request): error="" pk_id = request.GET.get("pk") #url地址携带的参数,first()查出多个只取一个,没有不报错 obj = models.Publisher.objects.filter(pk=pk_id).first() if not obj: return HttpResponse("编辑的对象不存在") if request.method == "POST": # 获取新提交的数据,编辑原始的对象 pub_name = request.POST.get('pub_name') if not pub_name: error = "输入不能为空" elif models.Publisher.objects.filter(name=pub_name): error = "数据已经存在" else: obj.name = pub_name obj.save() return redirect("/publisher_list") return render(request,'publisher_edit.html',{'obj':obj,'error':error})
ORM一对多关系:
外键的设计
# ForeignKey 添加的外键('Publisher' 添加字符串通过反射进行查找)
on_delete=models.set(1) 唯一
default=11,on_delete=models.DEFERRED 默认值
null=True on_delete=models.SET_NULL 设置字段可有为空
on_delete=models.DO_NOTHING 什么操作都不做
# on_delete 2.0 必填 ,关联删除后的选项
class Book(models.Model):
id = models.AutoField(primary_key=True) # 自增、主键
title = models.CharField(max_length=32)
pid = models.ForeignKey('Publisher', on_delete=models.CASCADE) #默认关联主键
增删改查
查询:
all_books = models.Book.objects.all() print(all_books) for book in all_books: print(book) print(book.pk) print(book.title) print(book.pub,type(book.pub)) # 一对多关联的是对象 print(book.pub_id,type(book.pub_id)) # 所关联的对象的pk print('*' * 32)
新增
#pub=models.Publisher.objects.get(pk=pub_id) 只能等于一个对象 models.Book.objects.create(title=title,pub=models.Publisher.objects.get(pk=pub_id)) #第二种方法,pub外键必须等于一个对象,但是都要转换成id,所以第二种方法直接添加ID也可以 models.Book.objects.create(title=title, pub_id=pub_id)
删除
pk = request.GET.get('pk') models.Book.objects.filter(pk=pk).delete()
编辑
book_obj.title = title book_obj.pub_id = pub_id #第一种方法 book_obj.pub = models.Publisher.objects.get(pk=pub_id) book_obj.save() #第二种方法 book_obj.pub_id = new_pub_id #将数据保存 book_obj.save()
ORM 多对多关系:
多对多关系创建
第一种方法:django通过ManyToManyField自动创建第三张表
# 在上下两个表中添加都可以,只是顺序不一样 class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) # authors = models.ManyToManyField('Author') # 描述多对多的关系 不生成字段 生成关系表 def __repr__(self): return self.title __str__ = __repr__ class Author(models.Model): id = models.AutoField(primary_key=True) # 自增、主键 name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 描述多对多的关系 不生成字段 生成关系表
第二种方法:自己手动创建
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField() #自己创建表可以添加多个字段(时间字段)
第三种方法:自己创建 + ManyToManyField
# 第三张表包含了第一张和第二张表的使用方法 class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) #第三种方法:to book表字段,through=指定多对多关系 books = models.ManyToManyField(Book, through='Book_Author') class Book_Author(models.Model): #创建关系表 book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
多对多-增删改查
查询:
def author_list(request): all_author = models.Author.objects.all().order_by("id") for author in all_author: print(author) print(author.name) print(author.pk) print(author.books) #多对多拿到books是关系对照表 print(author.books.all()) #通过all拿到关联的所有对象 print("*"*32) return render(request,'author_list.html',{'all_author':all_author}) # 从book表中查询author作者数据,下面是获取到author对象 book.author_set.all # 前端展示示例: {% for author in all_author %}
{{ forloop.counter }} {{ author.pk }} {{ author.name }} {% for book in author.books.all %} 《{{ book.title }}》 {% endfor %} 删除 编辑
新增:
books = request.POST.getlist('books') # 获取多个元素 author_obj = models.Author.objects.create(name=name) # 新建作者 author_obj.books.set(books) #【id,id】,给作者和书籍绑定关系 #新增示例: def author_add(request): if request.method == "POST": name = request.POST.get('name') books = request.POST.getlist('books') #列表方式获取书籍ID ['1'] author_obj = models.Author.objects.create(name=name) #作者名写入数据库 author_obj.books.set(books) #写入关联方式 return redirect("/author_list/") all_books = models.Book.objects.all() return render(request,'author_add.html',{'all_books':all_books})
删除:
def author_del(request): pk_id = request.GET.get("pk") models.Author.objects.filter(pk=pk_id).delete() return redirect('/author_list/')
编辑:
def author_edit(request): pk_id = request.GET.get("pk") obj = models.Author.objects.filter(pk=pk_id).first() if request.method == "POST": name = request.POST.get('name') books = request.POST.getlist('books') #列表方式获取书籍 obj.name = name #修改作者名称 obj.save() obj.books.set(books) #添加作者关联的书籍地址,每次都是删除后在添加 return redirect('/author_list//') all_books = models.Book.objects.all() return render(request,'author_edit.html',{'obj':obj,'all_books':all_books}) # 前端示例
模板使用:
MVC 和 MTV
MVC:
mvc是软件中一种软件架构模式,把软件系统分为三个基本部分,具有耦合性低,重用性高,生命周期成本低
- M: model 模型 和数据库交互
- V:view 视图 展示页面 HTML
- C: controller 控制器 调度 业务逻辑
MTV:
M : model 模型 操作数据库 orm、
T : template 模板 HTML
V: view 视图 业务逻辑
常用语法:
{{ 变量 }} :两个大括号 表示变量,在模板渲染的时候替换成值
{{% 逻辑%}} : 括号中带有两个百分号表示逻辑相关操作
变量
{{ 变量名. }}
- .索引 .key .属性 .方法
- 列表.索引 字典.key 类.属性 类.方法
示例:
# 模板中的变量是通过views render后端返回到前端,前端通过{{}}显示到页面 # 注意事项:在字典中创建跟字典方法相同key 会优先调用字典中的key > 对象的属性或方法 > 列表的索引 {{ name_list.1 }} 拿到列表第一个索引 {{ dic.name }} 通过字典的key取值 {{ dic.keys }} 字典的数据类型,keys {{ dic.values }} 字典的数据类型,values {{ p1 }} 类中方法,在类中定义str返回值,返回所有值 {{ p1.name }} 返回name属性 {{ p1.talk }} 调用类中方法,不用加括号 #views def index(request): class Person(): def __init__(self,name,age): self.name = name self.age = age def talk(self): return "我太难了" def __str__(self): return f"Person obj:{self.name}{self.age}" booll = True num = 666 string = "小窝窝" name_list = ["海洋","俊丽","小宝宝","大宝宝"] dic = { "name":"小明", "age":"18", "sex":"18", 'hobby':["台球","篮球","足球",'羽毛球']} p1 = Person("胡海洋",18) context = { 'booll':booll, 'num':num, 'string':string, 'name_list':name_list, 'dic':dic, 'p1':p1} return render(request,'index.html',context) # templates {{ booll }}
{{ num }}
{{ string }}
{{ name_list.1 }}
{{ dic.values }}
{{ p1}} {{ p1.name }} {{ p1.talk }}
过滤器-Filters
修改变量的显示结果
语法
{{ value|filter_name }} {{ value|filter_name:参数 }}
default: 提供默认值
# 传过来的变量不存在或者为空 使用默认值,:后面不可以有空格!!! {{ qq|default:'默认值自己设置' }} # 后端变量如果无效可以增加提示 注:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:'找不到',可以替代default的的作用。
列表切片
{{ name_list|slice:'::-1' }} 从后往前切片 {{ name_list|slice:'0:2' }} 切两个值
filesizeformat 文件大小格式化
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)
{{ filesize|filesizeformat }} 后端:'filesize':1*1024*1024
add
数字的加法 字符串的拼接 列表的合并 {{ num|add:2 }} # 给数字进行加2,如果num为字符串类型也会进行相加 {{ string|add:"haha"}} # 通过add给string字符串进行拼接 {{ name_list|add:name_list}} # 列表拼接 {{ num|add:-2 }} 减法 {% widthratio num 1 4%} 乘法 {% widthratio num 2 1%} 除法 # 1放在中间时乘法,放在后面是除法
其他内置过滤器方法:
字符串
- 变小:{{ string|lower}}
- 变大:{{ string|upper}}
- 计数:{{ string|length}}
列表
取第一个元素: {{ name_list|first}}
取最后一个元素 : {{ name_list|last}}
字符串拼接列表: {{ name_list|join:'**'}}
按字符串长度取值: {{ string|truncatechars:'10'}} ,truncatewords按照单词区分
日期格式化:
{{ now|date:'Y-m-d H:i:s' }} 年月日时分秒 {{ now|date}} 设置settings后使用方法 {{ now|time}} # 后端格式 'now':datetime.datetime.now() # settings 配置 USE_L10N = False DATETIME_FORMAT = 'Y-m-d H:i:s' DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s'
safe 告诉django不需要“”转义:
{{ js|safe }} {{ a|safe }} # 后端js,字符串在前端还是普通字符串,想要展示效果,添加safe不需要转义 'js':''' ''' 'a':'跳转'
PY文件中不转义方法
# 第二种方法mark_safe 在后端进行处理,前端直接调用: {{ a }} # 调用 from django.utils.safestring import mark_safe 'a':mark_safe('跳转')
自定义过滤器
在app下创建一个名为templatetags的python包(文件夹)
在包内创建py文件 —— 》 自定义 my_yags.py
在py文件中写入:
from django import template register = template.Library() # register不能变
定义函数 + 加装饰
@register.filter # new_upper(|后面的方法) value(原本的变量) arg最多有一个(冒号就后面的参数,可默认) def new_upper(value, arg=None): # arg 最多有一个 print(arg) return value.upper() # 不返回 前端结果为None
在模板中使用:
{% load my_yags %} # 加载写函数定义的文件 {{ string|new_upper:dic }} # string变量,new_upper函数方法,dic后端数据,可以返回到函数arg中
for 循环
forloop
# for 循环格式 {% for name in name_list %}
- {{ forloop.counter0 }} - {{ name }}
{% endfor %} {{ forloop.counter0 }} 字典中都已经定义好了一下参数 {{ forloop.counter }} 当前循环的从1开始的计数 {{ forloop.counter0 }} 当前循环的从0开始的计数 {{ forloop.revcounter }} 当前循环的倒叙计数(到1结束) {{ forloop.revcounter0 }} 当前循环的倒叙计数(到0结束) {{ forloop.first}} 当前循环是否是第一次循环 布尔值 {{ forloop.last}} 当前循环是否是最后一次循环 布尔值 {{ forloop.parentloop }} 当前循环父级循环的forloop(多层循环中才可以查看到)empty
{% for name in name_list %} {{ name }} {% empty %} 空的数据,循环过程没有数据返回此提示 {% endfor %}
if 判断
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
# 判断列表中为偶数的变颜色,if里面可以使用过滤器
{% for name in name_list2 %}
# 多层判断 {% if p1.age < 18 %} 宝宝 {% elif p1.age == 18 %} 刚成年 {% else %} 上班 {% endif %} # 不支持算数运算 {% if 1 + 2 == 3 %} {% if 1|add:2 == 3 %} 可以这样写 # 不支持连续判断 {% if 10 >5 > 1 %}{% for new in name %} {% if forloop.counter|divisibleby:2 and forloop.parentloop.counter|divisibleby:2%} {% endfor %}{{ new }} {% else %}{{ new }} {% endif %} {% endfor %}
with和csrf_token
with示例:
# 取别名两种方式 {% with alex=person_list.1.name age=person_list.1.age %} {{ alex }} {{ age }} {{ alex }} {% endwith %} {% with person_list.1.name as junli %} {{ junli }} {% endwith %}
{% csrf_token %}
# {% csrf_token %}标签放在form标签中,不安全报错403 # form表单中有一个隐藏的input标签(name ='csrfmiddlewaretoken'),后端通过这个值进行验证
母板和继承
母板就是将公共部分提取出来,不重复的定义block,之后再进行集成填充block块,减少重复代码,提高效率
母板:
html页面 提取多个页面的公共部分
定义多个block块,需要让子页面覆盖填写
# 找到重复的页面定义bolck块 # 第一种block块,设置母版