二、基础知识
2.1 url和视图函数
URL - 结构
-
定义 - 统一资源定位符Uniform Resource Locator
-
作用 - 用来表示互联网上某个资源的地址
-
URL的一般语法格式为(注:[]代表其中的内容可省略):
protocol://hostname[:port]/path[?query][#fragment]
-
protocol(协议) **http://**tts.tmooc.cn
http通过HTTP访问该资源。格式http://
https通过安全的HTTPS访问该资源。格式https://
file资源是本地计算机上的文件。格式file:///
-
hostname(主机名)http://tts.tmooc.cn
指存放资源的服务器的域名系统(DNS)主机名、域名或IP地址
-
port(端口号)http://tts.tmooc.cn:80
整数,可选,省略时使用方案的默认端口
各种传输协议都有默认的端口号,如http的默认端口为80
-
path(路由地址)http://tts.tmooc.cn/video/showVideo
又零活多个"/"符号隔开的字符串,一般用来表示主机的一个目录或文件地址。路由地址决定了服务器端如何处理这个请求
-
query(查询)
/video/showVideo?menuId=657421&version=AID999
可选,用于给动态网页传递参数,可有多个参数,用"&“符号隔开,每个参数的名和值用”="符号隔开
-
fragment(信息片段)
version=AID999#subject
字符串,用于指定网络资源中的片段。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释
处理URL请求
-
浏览器 地址栏 -> http://127.0.0.1:8000/page/2003/
1.Django从配置文件中根据ROOT_URLCONF找到主路由文件;默认情况下,该文件在项目同名目录下的urls;例如mysite1/mysite1/urls.py
2.Django加载主路由文件中的urlpatterns变量[包含很多路由的数组]
3.因此匹配urlpatterns中的path,匹配到第一个合适的中断后续匹配
4.匹配成功 - 调用对应的视图函数处理请求,返回响应
5.匹配失败 - 返回404响应
-
主路由 - urls.py样例
from django.urls import path
from . import views
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘page/2003/’, views.page_2003),
path(‘page/2004/’, views.page_2004),
]
-
视图函数
视图函数是用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应的函数。此函数可以接收浏览器请求并根据业务逻辑返回相应的响应内容
def xxx_view(request[, 其他参数…])
return HttpResponse对象
2.2 路由配置
settings.py中的ROOT_URLCONF
指定了主路由配置列表urlpatterns的文件位置
file: <项目同名文件夹下>/urls.py
urlpatterns = [
path(‘page/2003/’, views.page_2003_view),
… # 此处配置主路由
]
path()函数
导入 - from django.urls import path
语法 - path(route, views, name=None)
参数:
route:字符串类型,匹配的请求路径
views:指定路径所对应的视图处理函数的名称
name:为地址起别名,在模板中地址反向解析时使用
转换器
练习:小计算器
定义一个路由的格式为:
http://127.0.0.1:8000/整数/操作字符串[add/sub/mul]/整数
从路由中提取数据,做相应的操作后返回给浏览器
效果如下:
输入127.0.0.1:8000/100/add/200
页面显示结果:300
re_path()函数
在url的匹配过程中可以使用正则表达式进行精确匹配
语法:
- re_path(reg, view, name=xxx)
- 正则表达式为命名分组模式(?P<name>pattern);匹配提取参数后用关键字传参数方式传递给视图函数
样例
-
可匹配 http://127.0.0.1:8000/20/mul/40
-
不可匹配 http://127.0.0.1:8000/200/mul/400
-
urlpatterns = [
path(‘admin/’, admin.site.urls),
re_path(r’^(?P<x>\d{1,2})/(?P<op>\w+)/(?P<y>\d{1,2})$’, views.cal_view)
]
练习
访问地址
http://127.0.0.1:8000/birthday/四位数字/一到两位数字/一到两位数字
http://127.0.0.1:8000/birthday/一到两位数字/一到两位数字/四位数字
最终输出:生日为xxxx年xx月xx日
2.3 请求和响应
-
请求是指浏览器端通过HTTP协议发送给服务端的数据
-
响应是指服务器端收到请求后做相应的处理后再回复给浏览器端的数据
-
根据HTTP标准,HTTP请求可以使用多种请求方法
-
HTTP1.0定义了三种请求方法:GET,POST和HEAD方法(最常用)
-
HTTP1.1新增了五种请求方法:OPTIONS,PUT,DELETE,TRACE和CONNECT方法
- 请求在Django中实则就是视图函数的第一个参数,即HttpRequest对象- Django接收到http协议的请求后,会根据请求数据报文创建HttpRequest对象- HttpRequest对象通过属性描述了请求的所有相关信息
-
Django中的请求
path_info:URL字符串
method:字符串,表示HTTP请求方法,常用值:‘GET’、‘POST’
GET:QueryDict查询字典的对象,包含get请求方式的所有数据
POST:QueryDict查询字典的对象,包含post请求方式的所有数据
FILES:类似于字典的对象,包含所有的上传文件信息
COOKIES:Python字典,包含所有的cookie,键和值都为字符串
session:似与字典的对象,表示当前的会话
body:字符串,请求体的内容(POST或PUT)
scheme:请求协议(‘http’/‘https’)
request.get_full_path():请求的完整路径
request.META:请求中的元数据(消息头)
- request.META[‘REMOTE_ADDR’]:客户端IP地址
HTTP状态码的英文是HTTP Status Code
下面是常见的HTTP状态码:
-
200 - 请求成功
-
301 - 永久重定向 - 资源(网页等)被永久转移到其他URL
-
302 - 临时重定向
-
404 - 请求的资源(网页等)不存在
-
500 - 内部服务器错误
构造函数格式:
HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
作用:向客户端浏览器返回响应,同时携带响应体内容
-
GET请求和POST请求
无论是GET还是POST,统一都由视图函数接收请求,通过判断request.method区分具体的请求动作
if request.method == 'GET': 处理GET请求时的业务逻辑 elif request.method == 'POST': 处理POST请求时的业务逻辑 else: 其他请求业务逻辑
GET请求动作,一般用于向服务器获取数据
能够产生GET请求的场景:
1.浏览器地址栏输入URL,回车后
2.<a href = “地址?参数=值&参数=值”>
3.form表单中的method为get
使用GET方法示例:
request.GET[‘参数名’] # QueryDict
request.GET.get(‘参数名’, ‘默认值’)
request.GET.getlist(‘参数名’)
# mypage?a=100&b=200&c=300&b=400
# request.GET = QueryDict({‘a’: [‘100’], ‘b’: [‘200’, ‘400’], ‘c’: [‘300’]})
# a = request.GET[‘a’]
# b = request.GET[‘b’]
POST请求动作,一般用于向服务器提交大量隐私数据
客户端通过表单等POST请求将数据传递给服务器端,如:
<form method='post' action="/login"> 姓名:<input type="text" name="username"> <input type="submit" value='登陆'> </form>
使用post方式接收客户端数据:
request.POST[‘参数名’]
request.POST.get(‘参数名’, ‘’)
request.POST.getlist(‘参数名’)
取消csrf验证,否则Django将会拒绝客户端发来的POST请求,报403响应
2.4 Django设计模式和模板层
传统的MVC
MVC代表Model-View-Controller(模型-视图-控制器)模式
M模型层(Model),主要用于对数据库层的封装
V视图层(View),用于向用户展示结果(WHAT+HOW)
C控制(Controller),用于处理请求、获取数据、返回结果
Django的MTV模式
MTV代表Model-Template-View(模型-模板-视图)
M模型层(Model)负责与数据库交互
T模板层(Template)负责呈现内容到浏览器(HOW)
V视图层(View)是核心,负责接收请求、获取数据、返回结果(WHAT)
模板层
模板是可以根据字典数据动态变化的html网页
模板可以根据视图中传递的字典数据动态生成相应的HTML网页
模板配置
创建模板文件夹<项目名>/templates
在settings.py中TEMPLATES配置项
1.BACKEND:指定模板的引擎
2.DIRS:模板的搜索目录
3.APP_DIRS:是否要在应用的templates文件夹中搜索模板文件
4.OPTIONS:有关模板的选项
配置项中需要修改部分
设置DIRS - ‘DIRS’:[os.path.join(BASE_DIR, ‘templates’)]
模板的加载方式
方案1 - 通过loader获取模板,通过HttpResponse进行响应
在视图函数中
from django.template import loader
# 1.通过loader加载模板
t = loader.get_template("模板文件名")
# 2.将t转换成HTML字符串
html = t.render(字典数据)
# 3.用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
方案2 - 使用render()直接加载并响应模板
在视图函数中
from django.shortcuts import render
return render(request,'模板文件名',字典数据)
视图层与模板层之间的交互
1.视图函数中可以将Python变量封装到字典中传递到模板样例
def xxx_view(request):
dic = {
"变量1":"值1",
"变量2":"值2",
}
return render(request, 'xxx.html', dic)
2.模板中,我们可以用{{变量名}}的语法调用视图传进来的变量
模板层-变量和标签
模板层的变量
能传递到模板中的数据类型
str - 字符串 int - 整型
list - 数组 tuple - 元组
dict - 字典 func - 方法
obj - 类实例化的对象
在模板中使用变量语法
{{ 变量名 }}
{{ 变量名.index }}
{{ 变量名.key }}
{{ 对象.方法 }}
{{ 函数名 }}
模板层的标签
作用:将一些服务器端的功能嵌入到模板中,例如流程控制等
标签语法
{% 标签 %}
...
{% 结束标签 %}
例如if标签
{% if 条件表达式1 %}
...
{% elif 条件表达式2 %}
...
{% elif 条件表达式3 %}
...
{% else %}
...
{% endif %}
注意:
1.if条件表达式里可以用的运算符==,!=,<,>,<=,>=,in,not in,is,is not,not,and,or
2.在if标记中使用实际括号是无效的语法。如果您需要它们指示优先级,则应使用嵌套的if标记
官方文档:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#if
模板标签 - if标签 - 练习
写一个简单的计算器页面,能够在服务器端进行简单加减乘除计算
<form action='/mycal' method='post'>
<input type='text' name="x" value="1">
<select name='op'>
<option value="add">+加</option>
<option value="sub">-减</option>
<option value="mul">*乘</option>
<option value="div">/除</option>
</select>
<input type='text' name="y" value="2">=<span>3</span>
<div>
<input type="submit" value='开始计算'>
</div>
</form>
for标签
{% for 变量 in 可迭代对象 %}
...
循环语句
{% empty %}
...
可迭代对象无数据时填充的语句
{% endfor %}
官方文档:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#for
内置变量 - forloop
变量 | 描述 |
---|---|
forloop.counter | 循环的当前迭代(从1开始索引) |
forloop.counter0 | 循环的当前迭代(从0开始索引) |
forloop.revcounter | counter值的倒序 |
forloop.revcounter0 | revcounter值的倒序 |
forloop.first | 如果这是第一次通过循环,则为真 |
forloop.last | 如果这是最后一次循环,则为真 |
forloop.parentloop | 当嵌套循环,parentloop表示外层循环 |
模板层-过滤器和继承
定义:在变量输出时对变量的值进行处理
作用:可以通过使用过滤器来改变变量的输出显示
语法:{{ 变量 | 过滤器1:‘参数值1’ | 过滤器2:‘参数值2’ … }}
官方文档:https://docs.djangoproject.com/en/2.2/ref/templates/builtins
常用过滤器
过滤器 | 说明 |
---|---|
lower | 将字符串转换为全部小写 |
upper | 将字符串转换为大写形式 |
safe | 默认不对变量内的字符串进行html转义 |
add: “n” | 将value的值增加n |
truncatechars:‘n’ | 如果字符串字符多于指定的字符数量,那么会截断。截断的字符串将以可翻译的省略号序列("…")结尾。 |
… |
模板的继承
模板继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块
语法 - 父模板中:
定义父模板中的块block标签
标识出哪些在子模块中是允许被修改的
block标签:在父模块中定义,可以在子模块中覆盖
语法 - 子模板中:
继承模板extends标签(写在模板文件的第一行)
例如{% extends ‘base.html’ %}
子模板 重写父模板中的内容块
{% block block_name %}
子模板块用来覆盖父模板中block_name块的内容
{% endblock block_name %}
重写的覆盖规则
- 不重写,将按照父模板的效果显示
- 重写,则按照重写效果显示
注意:模板继承时,服务器端的动态内容无法继承
参考文档:https://docs.djangoproject.com/en/2.2/ref/templates/language/#for-template-blocks
url反向解析
1.模板【html中】
<a href=‘url’>超链接</a>
点击后,页面跳转到url
<form action=‘url’ method=‘post’>
form表单中的数据,用post方法提交到url
2.视图函数中 - 302跳转 HttpResponseRedirect(‘url’)
将用户地址栏中的地址跳转到url
url书写规范
绝对地址:http://127.0.0.1:8000/page/1
相对地址:
1.’/page/1’ - '/'开头的相对地址,浏览器会把当前地址栏里的协议,ip和端口加上这个地址,作为最终访问地址,即如果当前页面地址栏为http://127.0.0.1:8000/page/3;当前相对地址最终结果为http://127.0.0.1:8000 + /page/1
2.‘page/1’ - 没有’/'开头的相对地址,浏览器会根据当前url的最后一个/之前的内容加上该相对地址作为最终访问地址,例如当前地址栏地址为http://127.0.0.1:8000/topic/detail;则该相对地址最终结果为http://127.0.0.1:8000/topic/ + page/1
url反向解析
url反向解析是指在视图或模板中,用path定义的名称来动态查找或计算出相应的路由
path函数的语法
-
path(route, views, name=“别名”)
-
path(‘page’, views.page_view, name=“page_url”)
根据path中的
name=
关键字传参给url确定了唯一确定的名字,在模板或视图中,可以通过这个名字反向推断出此url信息
模板中 - 通过url标签实现地址的反向解析
{% url ‘别名’ %}
{% url ‘别名’ ‘参数值1’ ‘参数值2’ %}
ex:
{% url ‘pagen’ ‘400’ %}
{% url ‘person’ age=‘18’ name=‘gxn’ %}
在视图函数中 -> 可调用django中的reverse方法进行反向解析
from django.urls import reverse
reverse('别名', args=[], kwargs = {})
ex:
print(reverse('pagen', args=[300]))
print(reverse('person', kwargs={'name':'xixi', 'age':18}))