视图是Django框架的核心之一,它接收处理URLconfs分发的HTTP请求,返回响应。
视图的功能决定了它的基本结构,结构示意如下:
def view_name(request, *arg=None, **kwargs=None):
代码段
return HttpResponse(response)
#request必选参数,用于接收请求对象(HttpRequest类的实例)
#arg, kwargs为可选参数,用于接收URL中的额外参数
#返回值用于返回响应对象HttpResponse类或其子类的实例
实例1:
在views.py文件中定义一个返回当前日期和时间的视图curr_time(),具体代码如下:
from django.http import HttpResponse
import datetime
def curr_time(request):
now = datetime.datetime.now()
response = "It is %s." % now
return HttpResponse(response)
为了方便代码维护和防止视图臃肿,根据MTV模式,Django提倡将页面样式放在模板文件之中,在试图文件中使用上下文字典向模板传递数据。
实例2:
提取视图curr_time()中的样式代码,将其放在HTML文件time.html中。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>当前时间title>
head>
<body>
It is {
{now}}.
body>
html>
以上变量now表示当前时间,它接收从视图函数中传来的数据。以下为view.py文件中视图函数代码:
from django.http import HttpResponse
from django.template import loader
import datetime
def curr_time(request):
t = loader.get_template("time.html") #加载模板
now = datetime.datetime.now() #获取当前时间
context = {
#上下文字典
'now':now,
}
response = t.render(context, request) #渲染模板
return HttpResponse(response)
过程:视图函数curr_time()先使用django.template.loader模块的get_template()函数加载模板文件time.html,生成模板对象,然后获取当前时间,将当前时间存储到上下文字典中,之后使用模板对象的render()函数结合请求消息request和上下文字典渲染模板,最后返回响应对象。
请求对象由Django自动创建,由视图的requests参数接收,Django项目中所有请求的处理都离不开请求对象。
请求对象是HttpRequest类的实例,其中封装了HTTP请求。通过HttpRequest类内定义的属性和方法可以访问与HTTP请求相关的信息。
HttpRequest.body #包含原始HTTP请求的请求体信息,属性为bytes
HttpRequest.path #包含请求页面的完整路径,即文件的访问路径"/index.html/13",属性为字符串
HttpRequest.method #包含本次请求所用的方法
HttpRequest.GET #包含GET请求的所有参数,属性为QueryDict对象 HttpRequest.GET.get('name')取name参数的值
HttpRequest.POST
HttpRequest.COOKIES #包含所有Cookie信息,属性为一个字典数据,其中的键和值为字符串类型
HttpRequest.session #包含当前会话信息,属性为QueryDict对象
HttpRequest.site #包含由get_current_site()返回的Site或RequestSite实例,表示当前站点。
HttpRequest.user #包含当前登录用户的相关信息,属性为一个User对象
HttpRequest.META #包含HTTP请求的头部信息,该属性为dict类型
HttpRequest.get_host()
HttpRequest.get_port()
HttpRequest.get_full_path()
HttpRequest.build_absolute_uri(location=None) #返回location的绝对URI
HttpRequest.get_signed_cookie()
HttpRequest.is_ajax() #判断当前请求是否由AJAX发送,若是则返回True
最基础的响应类
HttpResponse的常用属性
HttpResponse.content #设置响应消息的内容,值为字节类型
HttpResponse.charset #设置响应消息的编码方式
HttpResponse.status_code #用于设置相应的状态码
HttpResponse.reason_phrase #用于设置相应的HTTP原因短语
HttpResponse的常用方法
HttpResponse.__init__()
HttpResponse.set_cookie() #用于设置Cookie信息
HttpResponse.set_signed_cookie()
HttpResponse.del_cookie() #使用给定密钥删除Cookie
使用HttpResponse类
使用HttpResponse类创建响应对象的简单方式是传递一个字符串(这个字符串将作为页面的内容呈现)到HttpResponse类的构造函数。
response1 = HttpResponse("Here's the text of the Web page.")
response2 = HttpResponse("Text only, please.", content_type="text/plain")
response3 = HttpResponse(b'Bytestrings are also accepted.')
可用write()方法向其中追加内容:
response = HttpResponse()
response.write("Here's the text of the web page
")
response.write("Here's another paragraph
")
HttpResponse类的构造函数也可以接收一个可迭代对象,HttpResponse()接收到可迭代对象后,立刻以字符串形式存储可迭代对象中的内容,当数据存储完成后销毁可迭代对象(如接收一个文件对象,内容存储完毕后立刻调用close()方法关闭文件对象)
HttpResponseRedirect
HttpResponseRedirect类接收的响应信息是URL。
return HttpResponseRedirect("http://example.com") #链接
return HttpResponseRedirect("/search/") #绝对路径
return HttpResponseRedirect("search") #相对路径
注:该类只支持硬编码链接,不能直接使用URL名称,若要使用URL名称,需要先使用反向解析方法reverse()解析URL,例如使用命名空间blog下名为article_list()的URL,实例:
return HttpResponseRedirect(reverse('blog:article_list'))
JsonResponse
返回json类型的响应
from django.http import JsonRespone
def json_view(request):
response = JsonResponse({
'foo':'bar'}, safe=False)
return response
当调用json_view()视图时,页面会显示JSON数据“{‘foo’:‘bar’}”.
将safe设置为False时,不止可转存dict类型数据,还可以转存非dict类型数据。比如下面:
from django.http import JsonResponse
def json_view(request):
response = JsonResponse(['coding', 'fish'], safe=False)
return response
异常响应处理:
HttpResponseNotModified #304 页面在上次请求后未改变,无参数
HttpResponseBadRequest #400 表示错误的请求
HttpResponseNotFound #404 表示页面不存在
HttpResponseForbidden #403 表示禁止访问
HttpResponseNotAllowed #405 表示禁止访问
HttpResponseGone #410
HttpResponseServerError #500 表示服务器错误
from django.shortcuts import loader
from django import http
from .models import Goods
from django.views.generic.base import TemplateView, RedirectView
from django.shortcuts import get_object_or_404,redirect,reverse
from django.forms import ModelChoiceField
from django.views import View
from django.shortcuts import render
#from django.views.decorators.csrf import csrf_exempt
'''
class GoodView(TemplateView):
template_name = "goods.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['goods'] = Goods.objects.all()
return context
class DeleteGood(RedirectView):
url = '/goods/'
# pattern_name = 'goods:good'
permanent = True
#query_string = True
def get_redirect_url(self, *args, **kwargs):
good = get_object_or_404(Goods, id=kwargs['gid'])
good.delete()
# kwargs={}
print(args)
print(kwargs)
return super().get_redirect_url(*args, **kwargs)
def get_goods(request):
"""展示商品"""
t = loader.get_template('goods.html') #加载模板
goods = Goods.objects.all() #获取数据
context = {
'goods':goods, #构造上下文字典
}
response = t.render(context, request) #结合上下文和请求对象生成响应信息
return http.HttpResponse(response)
def del_good(request, gid):
"""删除指定商品"""
good = Goods.objects.get(id=gid) #获取待删除商品的id
good.delete() #删除该商品
return http.HttpResponseRedirect('/goods/') #重定向到首页,展示新的商品列表
# Create your views here.
'''
class GoodView(View):
'''商品视图类'''
def get(self, request):
'''展示商品'''
goods = Goods.objects.all()
context = {
'goods':goods,
}
return render(request, 'goods.html', context)
def post(self, request):
"""添加商品"""
good = Goods()
try:
"""参数不能少,少的话会出错"""
good.name = request.POST.get('good_name') #获取post传递的参数
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
#print("hello boy
")
# return redirect('/') # 快捷方式
return redirect(reverse('goods:info'))
except Exception as e:
return http.HttpResponseForbidden('数据错误')
class UpdateDestoryGood(View):
'''编辑或删除商品'''
def get(self, request, gid):
'''删除商品数据'''
try:
good = Goods.objects.get(id=gid)
good.delete()
except Exception as e:
return http.HttpResponseForbidden('删除失败')
return redirect(reverse('goods:info')) #反向解析
def post(self, request, gid=0):
'''编辑商品'''
goods = Goods.objects.all()
count = goods.count()
try:
num = request.POST.get('good_num')
for i in range(1, count + 1):
if i == int(num): #找出要修改的那一行
good = goods[i - 1] #将那一行的数据赋值给good
good.name = request.POST.get('good_name')
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
break
except Exception as e:
return http.HttpResponseForbidden('编辑失败')
return redirect(reverse('goods:info'))
效果:
urls.py中路由匹配错误导致404
解决:对照模板,分析路由匹配过程,不断调试
数据无法插入数据库:
解决:有可能是参数有缺失(加上就行),也有可能用户的输入与数据库字段类型不符(处理好报错,设置好数据库字段类型)。
AttributeError: ‘str’ object has no attribute ‘tzinfo’
参考文章:传送门