View视图层概述
Django中的视图层,负责处理用户的请求并返回响应。
一个视图,简单来说就是一个Python函数(View类更高级),用户接受web请求,同时返回web响应。响应可以是文本、HTML页面、图像…视图定义可以在项目的任意一个模块中,但是Django中一般在views.py中定义。或者可以说每个应用的views.py
的主要功能就是创建视图。
如何创建一个视图并当用于输入url时展示在页面呢?由以下两步就可以搞定
第一步.创建视图
创建视图基本格式如下,在任意应用的views.py中:
from django.http import HttpRequest,HttpResponse
def helloword(request):
return HttpResponse("Hello,Django!")
第二步.映射URL
创建好视图之后,需要提供一个url在浏览器中访问。首先有一个疑问:Django如何处理一个请求?
1.一般情况下,Django通过配置文件settings.py中ROOT_URLCONF
配置的值来决定根URLConfig。如果请求的HttpRequest中带有urlconf属性,则会使用该urlconf。
2.Django加载根URLConfig中指定的模块中urlpatterns
的值,这些值是django.urls.path()或django.urls.re_path()中的list.
3.Django依次匹配根URLConfig中每个urlpatterns
,在与请求的URL匹配的第一个模式停下来.
4.一旦匹配到合适的urlpatterns,Django就会导入并且调用给定view的函数。并且传入HttpRequest作为第一个参数。
5.如果没有匹配到urlpatterns,Django会引入一个合适的错误处理视图,如404、400…
知道url匹配原理后,就可以为这个视图配置一个url了,首先寻找根URLConf,在Settings.py中:
ROOT_URLCONF = 'mysite.urls'
一般每个项目的根UrlConf默认为该项目的urls.py,因此mysite.urls.py为根URLConf,在mysite.urls.py中:
"""mysite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from polls import views
urlpatterns = [
path('admin/', admin.site.urls),
]
在这个文件注释中对三种方式创建url进行了说明。首先导入对应的views模块,然后在urlpatterns
列表中通过path()来指定一个url,如:
from polls import views
path('hello/', views.helloword, name='helloword'),
根据匹配原理,当匹配到hello时,就会导入views并调用helloword函数,现在就可以在浏览器中访问该视图了,输入http://127.0.0.1:8000/hello.
这是使用第一种方式进行url创建的,但是并不推荐这种方式,因为如果将每个应用的url全部配置在根UrlConf中,随着项目越来越庞大,url会变得非常混乱。应该使用第三种方式,在根UrlConf中,通过include()函数来引入每个应用的UrlConf,这样当根UrlConf中匹配成功后,会通过include()在对应的应用中进行匹配。使用这种方式创建url如下:
path('hello/', include('polls.urls')),
引入了polls.urls.py,在polls.urls.py中:
from . import views
path('', views.helloword),
处理请求错误
Django中,除200外,每个响应码都有对应的一个类,这些类都是HttpResponse的子类,如:
- HttpResponsePermanentRedirect:301
- HttpResponseNotModified:304
- HttpResponseBadRequest:400
- HttpResponseNotFound:404
- HttpResponseForbidden:403
- HttpResponseServerError:500
因此在请求时如果需要处理错误,返回这些HttpResponse的子类即可,如:
def get_student(requset):
try:
stu1 = Student.objects.get(name='Little.Hong')
except Student.DoesNotExist:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse("name:{0},age:{1}".format(stu1.name, stu1.age))
此外,对于常见的404错误,除了使用HttpResponseNotFound以外,还可以抛出Http404异常进行处理:
from .models import Student, classRoom
from django.http import Http404
def get_student(requset):
try:
stu1 = Student.objects.get(name='Little')
except Student.DoesNotExist:
raise Http404("page not found")
else:
return HttpResponse("name:{0},age:{1}".format(stu1.name, stu1.age))
View装饰器
Django中提供了几个用于视图的装饰器函数,以支持Http请求:
修饰HTTP请求方式:
以下装饰器是django.views.decorators.http中的,用于限制view的请求方式,如果请求方式不符合条件,返回django.http.HttpResponseNotAllowed。
@require_http_methods():表示该视图只能用该方法中提供的请求方式。
@require_GET():表示该视图只能使用GET请求。
@require_POST():表示该视图只能使用POST请求。
@require_safe(): 表示该视图只能使用GET和HEAD。
view快捷工具
在django.shortcuts包中,提供了四个快捷方法,可以用于HTTP请求和响应时。
render(Request,templatename,[options args]):将view和模板进行绑定,返回一个HttpResponse。
在实际开发中,views中仅仅处理请求和响应,不应该将页面的代码也写在view中,而是将页面设计交给模板,使用该方法将view和模板进行绑定即可。
1参:request对象
2参:模板名
可选参数:
1.已dict形式传入需要传入到template的对象
2.其他参数以关键字形式传入,有context,content_type,status,using.
如:
def get_student(request):
try:
stu1 = Student.objects.get(name='Little.Hong')
except Exception:
raise Http404("page not found")
else:
return render(request, 'student_show.html', {'stu': stu1})
redirect():重定向。有以下几种参数:
1.redict(model):传入一个model,这种情况下,将会回调model中的get_absolute_url()
方法,因此,要在传入的model中定义该方法。
2.redict(viewname):传入一个view,这种情况下,会通过reverse()
方法进行反向解析得到url,还可以显式调用reverse()
传入参数。
如:
# urls.py中配置url
urlpatterns = [
path('time', views.get_date_time, name='get_date_time')
]
# views.py中定义视图
from django.shortcuts import reverse
def get_date_time(request):
now = datetime.now()
return HttpResponse("now:{0}".format(now))
def get_student(request):
try:
stu1 = Student.objects.get(name='Little.Hong')
except Exception:
raise Http404("page not found")
else:
return redirect("get_date_time")
# or
return redirect(reverse("get_date_time"))
3.redict(‘http://…’):直接传入一个硬编码格式的url
get_object_or_404():调用model.Manager的get()方法,如果没有指定项,抛出Http404异常,而不是model.DoesNotExist异常
在查询时,model.Manager.get()如果没有查询结果,则会出现models.DoesNotExist异常,如果使用get_object_or_404()
,则没有查询结果时抛出Http404异常,如:
使用get():
def get_student(request):
try:
stu1 = Student.objects.get(name='Little')
except Student.DoesNotExist:
raise Http404("Page not found")
return render(request, "student_show.html", {"stu": stu1})
等价于使用get_object_or_404():
def get_student(request):
stu1 = get_object_or_404(Student, name='Little')
return render(request, "student_show.html", {"stu": stu1})
get_list_or_404():将model.Manager的filter()结果强制转换为list,如:
def get_student(request):
stu1 = list(Student.objects.filter(name='Little.Hong'))
等价于:
from django.shortcuts import get_list_or_404
def get_student(request):
stu1 = get_list_or_404(Student, name='Little.Hong')