HttpResponse,render,redirect
## HttpResponse()
括号内直接跟一个具体的字符串作为响应体
## render()
"""
render(request, template_name[, context])
参数:
1、request:用于生成响应的请求对象,固定必须传入的第一个参数
2、template_name:要使用的模板的完整名称,必须传入,render默认会去templates目录下查找模板文件
3、context:可选参数,可以传入一个字典用来替换模块文件中的变量
render:返回html页面 并且在返回给浏览器之前还可以给html文件传值。
"""
## render简单内部原理
from django.shortcuts import render,redirect,HttpResponse,reverse
def index(request):
from django.template import Template,Context
res = Template('<h1>{{ user }}</h1>')
con = Context({'user':{'username':'jason','password':123}})
ret = res.render(con)
print(ret)
return HttpResponse(ret)
## redirect()
"""
返回重定向信息
"""
def my_view(request):
...
return redirect('/some/url/')
# 重定向的地址也可以是一个完整的URL:
def my_view(request):
...
return redirect('http://www.baidu.com/')
JsonResponse对象
## 向前端返回json数据第一种方式
import json
def my_view(request):
data=['egon','kevin']
return HttpResponse(json.dumps(data, ensure_ascii=False) )
## 向前端返回json数据第二种方式
from django.http import JsonResponse
def ab_json(request):
# 读源码掌握用法(JsonResponse内部调用json.dumps())
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
# 当数据不是字典时要加safe
# 不加safe报错信息:In order to allow non-dict objects to be serialized set the safe parameter to False.
# l = [111,222,333,444,555]
# return JsonResponse(l,safe=False)
#默认safe=True代表只能序列化字典对象,safe=False代表可以序列化字典以外的对象
form表单上传文件
"""
form表单上传文件类型的数据
1.method必须指定成post
2.enctype必须换成multipart/form-data
## form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<p>username:<input type="text" name="username"></p>
<p>file:<input type="file" name="file"></p>
<input type="submit">
</form>
</body>
</html>
"""
def ab_file(request):
if request.method == 'POST':
# print(request.POST) # 只能获取普通的简直对数据 文件不行
print(request.FILES) # 获取文件数据
# <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}>
file_obj = request.FILES.get('file') # 文件对象
print(file_obj.name)
with open(file_obj.name,'wb') as f:
for line in file_obj.chunks(): # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取
f.write(line)
return render(request,'form.html')
request对象方法
"""
request.method
request.POST
request.GET
request.FILES # 获取文件数据
request.body # 原生的浏览器发过来的二进制数据 后面详细的讲
request.path # 获取完整的url路径
request.path_info # 获取完整的url路径
request.get_full_path() # 能过获取完整的url及问号后面的参数
"""
print(request.path) # /app01/ab_file/
print(request.path_info) # /app01/ab_file/
print(request.get_full_path()) # /app01/ab_file/?username=jason
FBV与CBV
视图函数既可以是函数也可以是类
# FBV(function base view)
## 我们平常在写django时一直使用的都是FBV
def index(request):
return HttpResponse('index')
# CBV(class base view)
## urls.py
urlpatterns = [
# CBV路由
url(r'^login/',views.MyLogin.as_view()) # 必须调用类下的方法as_view
]
## views.py
from django.views import View
## 能够直接根据请求方式的不同直接匹配到对应的方法执行
class MyLogin(View):
def get(self,request):
return render(request,'form.html')
def post(self,request):
return HttpResponse('post方法')
CBV源码剖析
## urls.py
urlpatterns = [
# CBV路由
url(r'^login/',views.MyLogin.as_view())
## 相当于 url(r'^login/',views.view)
]
"""
as_view()
要么是被@staicmethod修饰的静态方法
要么是被@classmethod修饰的类方法
"""
## views.py
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'form.html')
def post(self,request):
return HttpResponse('post方法')
## 源码
class View(object):
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
@classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.
"""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs) # self = MyLogin(**initkwargs)
## 反射机制
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
"""
对象属性查找顺序:先从对象自己找--->再去产生对象的类里面找--->之后再去父类找
"""
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
## 反射机制
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
"""
handler = getattr(自己写的类产生的对象,要获取的属性或方法,当属性或方法没有的时候就会用第三个参数)
"""
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return http.HttpResponseNotAllowed(self._allowed_methods())