Django-视图函数(控制器)
Django中的视图主要用来接收Web请求,并作出响应。视图本质就是一个Python函数。
视图的响应分为两大类:
- 以Json数据形式进行返回
- 以网页形式返回
- 重定向到另一个网页
- 错误视图(40X,50X)
视图的响应过程:
浏览器输入——> Django获取信息并去掉ip:端口,剩下路径——>URL路由匹配——>视图响应——>回馈到浏览器
1 URL配置
URL组成:
配置流程:
- settings中指定根级URL配置文件,对应的属性是
ROOT_URLCONF
。 - urlpatterns:一个URL实例列表。
# 导入
url(r'^index/',views.index),
# 导入其他app中的路由
from django.conf.urls import url, include
urlpatterns = [
url(r'^one/',include('one.urls')), # one是app的名称
]
url正则匹配注意事项:
(1)正则匹配时从上到下进行遍历,匹配到就不会向后寻找了,没有最优匹配的概念。
(2)匹配的正则前方不需要加反斜线\
(3)正则前需要加(r
)表示字符串不转义
(4)路由规则编写:以^
开头,以\
终止。
1.1 获取URL路径上的参数
1.1.1 位置参数:按书写顺序进行匹配
如果需要从url中获取一个值,需要对正则添加小括号
url(r'^grade/(\d+)$',views.getStudents)
注意,url参数中添加了()
取参,在请求调用的函数中必须接收:
def getStudents(request,classId): # 第二个参数即接收的参数
pass
如果需要获取url路径上的多个参数,那就添加多个括号,默认按照顺序匹配路径名字。
url(r'^grade/(\d{4})/(\d+)/(\d+)$/',views.getNews)
匹配年月日
def getNews(request,year,month,day):
pass
1.1.2 关键字参数:按照参数名称进行匹配
参数也可以使用关键字的形式
url(r'^grade/(?P<year>\d{4})/(?P<month>\d+)/(?P<day>\d+)/$',views.getNews)
1.1.3 示例:根据url参数获取不同班级的学生列表
- 创建模型类
class Grade(models.Model):
g_name = models.CharField(max_length=16)
class Child(models.Model):
c_name = models.CharField(max_length=16)
c_grade = models.ForeignKey(Grade)
-
数据准备
Grade:
Child:
-
定义路由
url(r'^getgradeofchild/(\d+)/$', views.getgradeofchild) # 根据参数获取不同班级学生
- 视图函数
def getgradeofchild(request,grade_name): # 第二个参数用来接收班级
childs = Child.objects.filter(c_grade__g_name=str(grade_name))
context = {
'childs':childs
}
return render(request,'getgradeofchild.html',context=context)
也可以使用locals()函数
:
def getgradeofchild(request,grade_name): # 第二个参数用来接收班级
childs = Child.objects.filter(c_grade__g_name=str(grade_name))
return render(request,'getgradeofchild.html',context=locals()) #
local()函数
的作用:
(1)内置函数。
(2)将局部变量使用字典的方式进行打包。
(3)key是变量名,value是变量中存储的数据。
- 模板html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for child in childs %}
<li>{{ child.c_name }}</li>
{% endfor %}
</ul>
</body>
</html>
- 访问不同的grade_name返回不同结果
1.2 反向解析
简单来说就是可以给我们的URL匹配规则起个名字,一个URL匹配模式起一个名字。
这样我们以后就不需要写死URL代码了,只需要通过名字来调用当前的URL
- 根据根路由中注册的
namespace
和子路由中注册的name
,这两个参数在模板中动态获取路径。 - 在模板中使用
{% url 'namespace:name' %}
- 如果带有位置参数,使用
{% url 'namespace:name' value1 value2 ...... %}
- 如果带有关键字参数,使用
{% url 'namespace:name' key1=value1 key2=value2 ...... %}
1.2.1 关键字参数示例
- 定义路由
# 根路由
urlpatterns = [
url(r'^one/',include('one.urls',namespace='second')),
]
# 子路由
urlpatterns=[
# 直接访问
url(r'^home/', views.home),
# 点击访问
url(r'^getdate/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/$', views.getdate,name='getDate'),
]
- 视图函数
# 直接访问
def home(request):
return render(request,'home.html')
# 点击访问
def getdate(request,year,month,day):
return HttpResponse('%s-%s-%s' % (year,month,day)) # 接收到的参数变成str了。
- 模板
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Employees</title>
</head>
<body>
<a href="{% url 'second:getDate' year=2019 month=09 day=08 %}">getDate</a> # 超链接,访问def getdate(request,year,month,day)
</body>
</html>
- 访问
点击,跳转到第二个视图函数
2 错误页面控制
在模板中重写对应错误状态码页面。
关闭Debug就能看到,在settings中修改:
DEBUG = False
实现原则:就近原则
,如果我们自定义之后,就优先查找自定义的错误页面。
3 请求和响应
两大类:Request、Response。
3.1 HttpRequest
内置属性:
- method
- path
- GET:(1)类字典结构(2)一个key允许对应多个值(3)get取单个值、getlist取多个值。
- POST
- META:(1)各种客户端的元信息(2)REMOTE_ADDR
GET和POST都是QueryDict
的对象,类似字典的数据结构,与字典有区别,可以存在相同的键。
QueryDict数据获取方式:
- 获取单个值。
dict['uname'] 或 dict.get('uname')
- 获取多个值。
dict.getlist('uname')
3.2 HttpResponse
服务器返回数据给客户端。
HttpResponse由程序员自己创建:
(1)不使用模板,直接HttpResponse()
(2)调用模板,进行渲染:
- 先loader模板,再渲染。
- 直接使用render一步到位。
属性:
(1)content
:返回的内容
(2)charset
:编码格式
(3)status_code
:响应状态码(200,3XX,404,5XX)
(4)content-type
:MIME类型
什么是MIME类型:
- 作用:指定传输数据用那种形式打开(类似于后缀名)
- 格式:大类型/小类型(
image/jpg
、image/png
)
方法:
(1)init
:初始化内容
(2)write(XXX)
:直接写出文本
(3)flush()
:冲刷缓冲区
(4)set_cookies()
:设置cookie
(5)delete_cookies(key)
:删除cookie
3.3 重定向、Json
HttpResponse子类:HttpResponseRedirect
、JsonResponse
3.3.1 重定向-HttpResponseRedirect
响应重定向:可以实现服务器内部跳转
- 重定向:暂时的
- 响应码:302
- 该类可以简写为
redirect()
return HttpResponseRedirect('/grade/2017')
使用的时候推荐反向解析
。
示例:访问home,跳转hellotemplate
(1)URL配置
# 根路由
urlpatterns = [
url(r'^one/',include('one.urls',namespace='second')),
]
# 子路由
urlpatterns=[
url(r'^home/', views.home),
url(r'^hellotemplate/',views.hellotemplate,name='myTemplate'),
]
(2)视图函数
- 硬编码
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
def home(request):
return HttpResponseRedirect('/one/hellotemplate/') # 硬编码
def hellotemplate(request):
template = loader.get_template('HelloTemplate.html')
content = template.render()
return HttpResponse(content)
- 反向解析
在视图函数中使用别名,需要使用revers()
函数
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
def home(request):
url = reverse('second:myTemplate') # 反向解析,写的是反向解析的规则。
return HttpResponseRedirect(url)
def hellotemplate(request):
template = loader.get_template('HelloTemplate.html')
content = template.render()
return HttpResponse(content)
HttpResponseRedirect
的简写形式redirect()
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
def home(request):
url = reverse('second:myTemplate') # 反向解析,写的是反向解析的规则。
return redirect(url) # 简写
def hellotemplate(request):
template = loader.get_template('HelloTemplate.html')
content = template.render()
return HttpResponse(content)
(3)模板HelloTemplate.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloTemplate</title>
</head>
<body>
<p>我来自helloTemplate</p>
</body>
</html>
(4)访问
3.3.2 JsonResponse
常用于前后端分离
,或者ajax异步请求
。
重写了__init__
,序列化Json的数据,指定content_type
为application/json
源码:
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if safe and not isinstance(data, dict):
raise TypeError(
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False.'
)
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json') # 指定content_type为application/json
data = json.dumps(data, cls=encoder, **json_dumps_params) # 手动json.dumps
super(JsonResponse, self).__init__(content=data, **kwargs)
Json组成:
(1)JsonObject:
- 标识符:
{}
- key-value
(2)JsonArray:
[]
- 列表中可以是普通数据类型,也可以是JsonObject
JsonObject和JsonArray可以嵌套使用
使用方式:
(1)给移动端的Json
(2)给Ajax:
- 前后端分离
- DRF框架
示例:返回json数据
# URL配置
url(r'^getJson/',views.getJson,name='jsonData')
# 视图函数
def getJson(request):
data = {
'status':200,
'msg':'ok'
}
return JsonResponse(data=data)
访问