Django中的视图主要用来接收Web请求,并作出响应。视图本质就是一个Python函数。

视图的响应分为两大类:

  • 以Json数据形式进行返回
  • 以网页形式返回
    • 重定向到另一个网页
    • 错误视图(40X,50X)

视图的响应过程:

浏览器输入——> Django获取信息并去掉ip:端口,剩下路径——>URL路由匹配——>视图响应——>回馈到浏览器

1 URL配置

URL组成:

配置流程:

  1. settings中指定根级URL配置文件,对应的属性是ROOT_URLCONF
  2. 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参数获取不同班级的学生列表
  1. 创建模型类
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)
  1. 数据准备
    Grade:

    Child:

  2. 定义路由

url(r'^getgradeofchild/(\d+)/$', views.getgradeofchild)		# 根据参数获取不同班级学生
  1. 视图函数
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是变量中存储的数据。

  1. 模板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>
  1. 访问不同的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 关键字参数示例
  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'),
]
  1. 视图函数
# 直接访问
def home(request):
    return render(request,'home.html')
# 点击访问
def getdate(request,year,month,day):
    return HttpResponse('%s-%s-%s' % (year,month,day))	# 接收到的参数变成str了。
  1. 模板
    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>
  1. 访问

    点击,跳转到第二个视图函数

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/jpgimage/png

方法
(1)init:初始化内容
(2)write(XXX):直接写出文本
(3)flush():冲刷缓冲区
(4)set_cookies():设置cookie
(5)delete_cookies(key):删除cookie

3.3 重定向、Json

HttpResponse子类:HttpResponseRedirectJsonResponse

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_typeapplication/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)

访问