请求和响应
-
请求和相应
- django中的请求
- 视图函数中的第一个参数即为HttpRequest对象
- django接受到http协议的请求后,会根据请求数据报文创建HttpRequest对象
- HttpRequest对象通过属性,描述了请求的所有相关信息
- HttpRequest属性:
属性名 说明 path_info URL字符串 method 字符串,表示Http请求方法:GET、POST、PUT等 GET QueryDict查询字典的对象,包含get请求方式的所有数据 POST QueryDict查询字典的对象,包含post请求方式的所有数据 FILES 类似于字典的对象,包含所有的上传文件信息 COOKIES python字典,包含所有的cookie,键和值都为字符串 session 类似于字典对象,表示当前的会话 body 字符串请求体的内容 scheme 请求协议(http或者https) request.get_full_path() 请求的完整路径,会将查询字符串一并取出 request.META 请求中的元数据(消息头) requset.META[‘REMOTE_ADDR’] 客户端IP地址
- HttpRequest属性:
- django中的响应对象
- 构造函数:
- HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
- 作用:
- 向客户端浏览器返回响应,同时携带响应体类容
- 参数:
- content: 表示返回的内容
- status_code: 返回的HTTP响应状态码(默认为200)
- content_type: 指定返回数据的MIME类型(默认为text/html),浏览器会根据这个属性来显示数据
- 常见content_type:
- ‘text/html’: 默认的,HTML文件
- ‘text/plain’: 纯文本
- ‘text/css’: css文件
- ‘text/javascript’: js文件
- ‘multipart/form-data’: 文件提交
- ‘application/json’: json传输
- ‘application/xml’: xml文件
- 常见content_type:
- HttpResponse子类
类型 作用 状态码 HttpResponseRedirect 重定向 302 HttpResponseNotModified 未修改 304 HttpResponseBadRequest 错误请求 400 HttpResponseNotFound 没有对应的资源 404 HttpResponseForbidden 请求被禁止 403 HttpResponseServerError 服务器错误 500
- 构造函数:
- django中的请求
-
GET请求和POST请求
-
定义:
-
无论是GET还是POST,统一都由视图函数接收,通过判断request.method区分具体的请求动作
-
样例
if request.method == 'GET': 处理get请求时的业务逻辑 elif request.method == 'POST': 处理POST请求时的业务逻辑 else: 处理其他请求业务的逻辑
-
-
GET处理
- GET请求动作一般用于向服务器获取数据
- 能够产生GET请求的场景
- 浏览器地址栏输入URL回车后
- <a href = “地址?参数=值&参数=值”>
- form表单中的method为get
- GET请求中,如果有数据需要传递给服务器,通常会用查询字符串(Query String)传递,注意不要传递敏感数据
-
URL格式:XXX?参数名1=值&参数名2=值(如:http://127.0.0.1:8000?a=100&b=200)
-
服务器端接收参数:获取客户端请求GET提交的数据方法示例
request.GET['参数名'] #得到该参数名的值 request.GET.get('参数名',’默认值‘) #得到该参数名的值,如果该参数名不存在则返回默认值 request.GET.getlist(’参数名‘) #如果该参数名存在多个返回值,则用getlist来接收```
-
-
POST 处理
-
POST请求动作一般用于向服务器提交大量/隐私数据
-
客户端通过表单等POST请求将数据传递给服务器端;如:
<form method='post' action="/login"> #action指明post请求发给哪个路由 姓名:<input type="text" name="username"> <input type='submit' value='登陆'> </form>
-
服务器端接收参数:通过request.method来判断是否为post请求
-
使用post方式接收客户端数据
request.POST['参数名'] #得到该参数名的值 request.POST.get('参数名',’默认值‘) #得到该参数名的值,如果该参数名不存在则返回默认值 request.POST.getlist(’参数名‘) #如果该参数名存在多个返回值,则用getlist来接收
-
注意:发送POST请求时,django需要取消csrf验证,否则django会拒绝客户端发来的POST请求,报403响应
-
取消csrf验证:注释掉settings.py文件中的MIDDLEWARE中的csrfviewsmiddleware的中间件
-
-
-
Django的设计模式(MTV)
- 设计模式:MVC和MTV
- MVC(model-view-controller)模型-视图-控制器模式
- M 模型层,主要用于对数据库层的封装
- V 视图层,用于向用户展示结果
- C 控制层,用于处理请求、获取数据、返回结果
- 优点:降低模块间的耦合度
- MTV (model-template-view) 模型-模版-视图模式
- M 模型层,负责与数据库交互
- T 模板层,负责呈现内容到浏览器(html)
- V 视图层,负责接收请求、获取数据、返回结果
- 优点:降低模块间的耦合度
- MVC(model-view-controller)模型-视图-控制器模式
- 设计模式:MVC和MTV
-
模板层
-
模板定义:
- 模板是可以根据字典数据动态变化的HTML网页
- 模板可以根据视图中传递的字典数据动态生成相应的HTML网页
-
模板配置
- 创建模板文件夹<项目名>/templates
- 在settings.py中TEMPLATES配置项
- BACKEND:指定模板的引擎
- DIRS:模板的搜索目录,可以是一个或多个
- APP_DIRS:是否要在子应用中的templates文件夹中搜索模板文件
- OPTIONS:有关模板的选项
-
配置中需修改的部分
- 设置DIRS - ‘DIRS’:[os.path.join(BASE_DIR,‘templates’)],
-
模板的加载方式
-
方案一:通过loader获取模板,通过HttpResponse进行响应,在视图函数中进行如下配置:
from django.template import loader t = loader.get_template("模板文件名") #通过loader加载模板,得到一个loader对象 html = t.render(字典数据) #将t(loader对象)转换成HTML字符串 return HttpResponse(html) #用响应对象的方式将转换的字符串内容返回给浏览器
-
方案2:使用render()直接加载并响应模板,在函数视图中进行如下配置
from django.shortcuts import render return render(request,'模板文件名',字典数据)
-
-
视图层与模板层之间的交互
-
视图函数中可以将python变量封装到字典中传递到模板;样例:
def xxx_view(request): dic = { "变量1":"值1", "变量2":"值2", } return render(request,'xxx.html',dic)
-
在模板中,我们可以使用 {{变量名}} 的语法调用视图传进来的变量
-
-
模板层-变量
- 模板层可接收的数据类型
类型名 注释 str 字符串 int 整型 list 列表 tuple 元组 dict 字典 func 方法 obj 类实例化对象
- 模板层可接收的数据类型
-
在模板中使用变量语法
- {{ 变量名 }}
- {{ 变量名.index }} #传入的变量为列表、元组等,可用.index方法取出其中的元素
- {{ 变量名.key }} #传入的变量为字典,可用.key方法获取key所对应的值
- {{ 对象.方法 }} #调用对象的方法
- {{ 函数名 }} #调用函数
-
模板标签
-
作用:将一些服务器端的功能嵌入到模板中,例如流程控制等
-
语法:
{% 标签 %} ………… {% 结束标签 %} #django中大部分标签都需要使用结束标签封口
-
IF标签
-
语法
{% if 条件表达式1 %} …… {% elif 条件表达式2 %} …… {% else %} …… {% endif %} #必须使用endif标签进行结束
-
注意:
- if条件表达式例可以用的运算符==,!=,<,>,<=,>=,in.not in,is,is not,not,and,or;
- 在if标记中使用实际括号是无效的语法,如果需要他们指示优先级,则应使用嵌套的if标记
- if语句中,运算符两侧不能紧挨变量或常量,必须用空格隔开
- 关于if标签的语法参考官方文档
-
样例
<form action='/text' method="post"> <input type="text" name="x" value='{{ x }}'> <select name="op"> <option value="add" {%if op == 'add' %}selected{%endif%}> +加</option> <option value="sub" {%if op == 'sub' %}selected{%endif%}> -减</option> <option value="mul" {%if op == 'mul' %}selected{%endif%}> *乘</option> <option value="div" {%if op == 'div' %}selected{%endif%}> /除</option> </select> <input type="text" name="y" value='{{ y }}'> = <span>{{ result }}</span> <div><input type="submit" value="开始计算"> </div> </form>
-
for 标签
- 语法:
{% for 变量 in 可迭代对象 %} …… 循环语句 {% empty %} …… 可迭代对象为空时显示的语句 {% endfor %}
- 可迭代对象的传递,从视图函数以字典形式传递给模板文件,需要保证模板文件中的可迭代对象名与视图函数中定义的键名相同
<h3>{% for i in x %}{{ forloop.counter }}this is in for {{i}} {%endfor%}</h3> # x由视图函数传入
- 关于for标签的语法参考官方文档
-
内置变量 - forloop
变量 描述 forloop.counter 返回当前循环的索引(从1开始索引) forloop.counter0 返回当前循环的索引(从0开始索引) forloop.revcounter 返回当前循环的索引(从1开始索引counter值的倒序) forloop.revcounter0 返回当前循环的索引(从0开始索引counter值的倒序) forloop.first 如果当前循环是第一次循环,则返回True forloop.last 如果当前循环是最后一次循环,则返回True forloop.parentloop 如果为嵌套循环,parentloop则表示外层循环 -
模板过滤器
- 定义:在变量输出时,对变量的值进行处理
- 作用:可以通过使用过滤器来改变变量的输出显示
- 语法:{{变量|过滤器1:‘参数值1’ | 过滤器2:‘参数值2’}}
- 关于过滤器的语法参考官方文档
- 常用过滤器
过滤器 说明 lower 将字符串转换为全部小写 upper 将字符串转换为全部大写 safe 禁用转义,告诉模板这个变量是安全的,可以解释执行 add:“n” 将value的值增加n default:“默认值” 变量不存在时,返回默认值 truncatechars:‘n’ 如果字符串的字符多余指定的字符数量,那么会被截断,截断的字符串将以可翻译的省略号序列("…")结尾 forloop.parentloop 如果为嵌套循环,parentloop则表示外层循环
-
模板的继承
-
定义:模板的继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块
-
语法 - 父模板中:
- 定义父模板中的块block标签
- 标识出哪些在子模块中是允许被修改的(block标记的继承时都是可以进行修改的)
- block标签:在父模板中定义,可以在子模板中覆盖
-
语法 - 子模板中:
-
继承模板extends标签(写在模板文件的第一行)
- 例如
{% extends 'base.html '%}
#继承父模板base.html
- 例如
-
子模板重写父模板中的内容块
{% block block_name %} 子模板块用来覆盖父模板中 block_name 块的内容 {% endblock block_name %} #block_name可省略
-
-
重写的覆盖规则:
- 不重写,将按照父模板的效果显示
- 重写,则按照重写效果显示
-
注意:模板继承时,服务器端的动态内容无法继承,例如:视图给父模板传递的变量,在子模板中无法拿到
-
例:
-
父模板中
{% block block_name %} <h4>this is in parent</h4> {% endblock %}
-
子模板中
{% extends 'test_html.html' %} {% block block_name %} <h3> this is in base.html </h3> {% endblock %}
-
-
-
-
-
-
URL反向解析
- URL:
- 代码中常出现URL的位置:
- 模板【HTML中】:
<a href='url'>超链接</a>
#点击后页面跳转至url
<form action='URL' method='post'>
#form表单中的数据用post方法提交值URL - 视图函数中 - 302跳转 HttpResponseRedirect(‘url’) #将用户地址栏中的地址跳转到URL
- 模板【HTML中】:
- 代码中URL书写规范:
- 绝对地址:
http://127.0.0.1:8000/page1
(将协议、域名、端口、path全部写出) - 相对地址:
- ‘/page/1’ : '/'开头的相对地址,浏览器会把当前地址栏里的协议、IP、端口加上这个path,作为最终访问地址。如:
http://127.0.0.1:8000 + /page/1
- ‘page/1’ : 没有’/‘开头的相对地址,浏览器会根据当前URL的最后一个’/'之前的内容加上这个path最为最终访问地址。如:
http://127.0.0.1:8000/topic/detail
,加上相对地址后的访问地址为:http://127.0.0.1:8000/topic/page/1
- ‘/page/1’ : '/'开头的相对地址,浏览器会把当前地址栏里的协议、IP、端口加上这个path,作为最终访问地址。如:
- 绝对地址:
- 代码中常出现URL的位置:
- URL反向解析
- 定义:URL反向解析是指在视图或模板中,用path定义的名称来动态查找或计算出相应的路由
- 语法:
- path(route,views,name=‘别名’)
- 例:path(‘page’,views.page_view,name = ‘page_url’)
- 根据path中的name关键字传参给URL确定了唯一的名字,在模板或视图中,可以通过这个名字反向推断出此URL信息
- 模板中 - 通过URL标签实现地址的反向解析
-
{% url ‘别名’ %}
-
{% url ‘别名’ ‘参数值1’ ‘参数值2’ %},参数值1:向路由中传入的参数
-
例
{% url 'page1' '100' %}
#解析name=page1的路由,并传入参数100
{% url 'page2' key1='1' key2='2' %}
#解析name=page2的路由,并关键字传参key1,key2 注意 路由解析时传递的参数均为字符串方式传入 -
在视图函数中 - 通过调用django中的reverse方法进行反向解析
from django.urls import reverse reverse('别名', args=[ ], kwargs={ }) # 例 : reverse('page1',args=[100]) #解析name=page1的路由,并传入参数100 reverse('page2',kwargs={key1=1,key2=2})
-
- URL: