文章目录
前言
视图函数的返回值
为什么视图函数需要返回一个HttpResponse对象?
可以用一个例子来看看:(前提先配置好路由)

	def index(request):
		return None
然后我们直接开启服务,访问这个路由地址
 
三板斧源码大概注解
而其中HTML的三种响应方式返回的都是一个HttpResponse对象(可以查看源码)
	'''源码大概注解展示'''
	
	class HttpResponse(HttpResponseBase):
		'''括号内直接跟一个具体的字符串作为响应体'''
	    streaming = False  # 表示是否支持流式传输
	    
	    # 初始化HttpResponse实例,设置响应的内容
	    def __init__(self, content=b'', *args, **kwargs):
	        super(HttpResponse, self).__init__(*args, **kwargs)
	        # Content is a bytestring. See the `content` property methods.
	        self.content = content
	    ......
	====================================================================================
	
	def render(request, template_name, context=None, content_type=None, status=None, using=None):
	'''
		request:用于生成响应的请求对象
		template_name:要使用的模版的完整名称,可选的参数
		context:添加到模版上细纹的一个字典。默认是空字典。如果字典中的某一个值是可调用的,视图将在渲染模版之前调用它。
		render方法就是将一个模版页面中的模版语法进行渲染,最终渲染成一个html页面作为响应体
	'''
		# 使用Django的模版引擎加载和渲染模版
	    content = loader.render_to_string(template_name, context, request, using=using)
	    # 返回一个HttpResponse对象加括号调用HttpResponse的类
	    return HttpResponse(content, content_type, status)
	====================================================================================
	
	def redirect(to, *args, **kwargs):
		'传递要重定向的一个硬编码的URL或者路由'
	    if kwargs.pop('permanent', False):
	    '如果参数中包含 'permanent',并且其值为 True,则使用 HttpResponsePermanentRedirect 类'
	        redirect_class = HttpResponsePermanentRedirect
	    else:
	    	'否则使用默认的 HttpResponseRedirect 类'
	        redirect_class = HttpResponseRedirect
	        
		'''
		这里返回一个HttpResponse对象加括号调用HttpResponse的类
		创建相应的重定向对象,将重定向目标设置为 to
		'''
	    return redirect_class(resolve_url(to, *args, **kwargs))
	'''
		这样的设计使得 redirect 函数能够支持两种类型的重定向:
		临时重定向(HttpResponseRedirect)和永久重定向(HttpResponsePermanentRedirect),
		具体取决于 'permanent' 参数的值。
	'''
三板斧的使用
HttpResponse
示例:
	from django.shortcuts import HttpResponse
	
	def my_custom_response(request):
	    # 一些逻辑处理后,生成自定义的响应内容
	    content = 'This is a custom response.'
	    # 使用HttpResponse类创建HTTP响应
	    response = HttpResponse(content, content_type='text/plain', status=200)
	    # 可以添加自定义的头部信息
	    response['Custom-Header'] = 'Some value'
	    return response

	from django.shortcuts import HttpResponse
	
	def index(request):
    response = HttpResponse()  # 实例化产生一个对象
    response.content = 'Lucky'  # 设置响应内容
    response.status_code = 404  # 设置响应状态码
    # 直接写出文本
    response.write('777777')
    # 一次性读取剩余字节,冲刷缓存区
    response.flush()
    return response

redirect
示例:
	from django.shortcuts import redirect
	def my_redirect_view(request):
	    # 某些逻辑处理后,决定重定向到另一个URL
	    new_url = '/index/'
	
	    # 使用redirect函数生成重定向响应
	    return redirect(new_url)

render
示例:
	from django.shortcuts import render
	def my_view(request):
	    # 从数据库获取数据或进行其他逻辑处理
	    data = {'foo': 'bar'}
	
	    # 使用render函数渲染模板,并将数据传递给模板
	    return render(request, 'my_template.html', {'data': data})
总结:
JsonResponse对象
视图函数返回json格式的数据
- 方法一
 json序列化形式
	import json
	def Myjson(request):
	    user_dict = {'name':'oscar','age':18,'hobby':['唱','跳','rap']}
	    '''如果数据中有中文会进行编码,如果不想它编码就直接设置ensure_ascii=False即可'''
    	data = json.dumps(user_dict,ensure_ascii=False)
	    return HttpResponse(data)

- 方法二
 JsonResponse序列化形式
	'需要先导入JsonResponse模块'
	from django.http import JsonResponse
	
	def js(request):
	    user_dict = {'name': 'oscar', 'age': 18, 'hobby': ['唱', '跳', 'rap']}
	    return JsonResponse(user_dict)






 
 
form表单携带文件数据
注意事项:
-  enctype属性需要由默认的urlencoded变成form/data(enctype=“multipart/form-data”) 
-  method属性需要由默认的get变成post 
 (目前还需要考虑的是 提交post请求需要将配置文件中的csrf中间件注释)
-  如果form表单上传文件 后端需要在request.FILES获取文件数据 而不再是POST里面 
首先需要建立一个HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="" method="post" enctype="multipart/form-data">
    	<input type="text" name="text" placeholder="请输入文字">
        <input type="file" name="myfile">
        <input type="submit" value="提交">
    </form>
</body>
</html>
然后再建立路由和视图函数
	'路由文件'
	from app import views
	urlpatterns = [
	    url(r'^func/', views.func),
	]
	'视图文件'
	def func(request):
	    print(request.POST)
	    return render(request,'index.html')
配置后这些后,直接访问对应的路由,然后点击选择文件后提交

结果发现仅仅只是接收到了普通文本数据,并没有接收到文件数据
 
这时我们可以使用request.FILES来获取文件数据
	def func(request):
	    print(request.POST)
	    print(request.FILES)
	    return render(request,'index.html')

然后我们可以通过对获取到的文件数据进行写入文件中
- 首先我们从上述过程中,可以知道,得到的数据格式是字典格式,所以我们可以通过字典的方式取出数据
	def func(request):
	    if request.method == 'POST':
	        file_info= request.FILES.get('myfile')
	        print(res)
	    return render(request,'index.html')

- 拿到名字后就可以通过写入文件的方式写入文件数据了,但是要注意需要使用wb模式写入,因为wb模式可以把二进制数据转换成str格式。
	def func(request):
	    if request.method == 'POST':
	        # print(request.FILES)
	        file_info = request.FILES.get('myfile')
	        
	        with open(file_info.name,'wb')as f: 
	        '避免文件数据过大,使用一行一行的写入'
	            for line in file_info:
	                f.write(line)
	
	    return render(request,'index.html')

request对象方法
1.获取请求方式POST/GET
request.method
一个字符串,表示请求使用的HTTP 方法。必须使用大写。
2.request.POST
获取POST请求提交普通的键值对数据 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成
3.获取GET请求
request.GET
获取GET请求	一个类似于字典的对象,包含 HTTP GET 的所有参数
4.获取文件
request.FILES
一个类似于字典的对象,包含所有的上传文件信息。
FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。
5.原生的浏览器发过来的二进制数据
request.body  
一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,
  例如:二进制图片、XML,Json等。
6.拿到路由
request.path 
个字符串,表示请求的路径组件(不含域名)
7.拿到路由
request.path_info
8.能过获取完整的url及问号后面的参数 
request.get_full_path() 
FBV与CBV
FBV
CBV
Python是一个面向对象的编程语言,如果只用函数来开发,很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:
- 提高代码的复用性,可以使用面向对象的技术。
- 根据不同的类方法处理不同的HTTP请求,而不是通过很多if判断,提高代码可读性。
如果要写一个处理GET请求的view,FBV是这样写的
	路由文件
	from app import views
	urlpatterns = [
    	url(r'^test/',views.test)
	]
	视图文件
	from django.shortcuts import HttpResponse
	def test(request):
	    if request.method == 'GET':
	        return HttpResponse('this is test')
使用CBV是这样写的
	路由文件
	from app import views
	urlpatterns = [
    	url(r'^Mytest/',views.My_test.as_view()),
	]
	视图文件
	from django.shortcuts import HttpResponse
	from django.views import View
	class My_test(View):
	    def get(self,request):
	        return HttpResponse('this is test')
CBV类中的不能随意的定义函数,只能使用八大请求方式
	'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'
	'所有的类必须继承django的view类'
	from django.views import View
	
	class MyLogin(View):
	    # 类里面的方法名字不能够随便写,目前只能写get post等
	    # 访问这个地址必须是get请求方式
	    def get(self, request):
	        # get() takes 1 positional argument but 2 were given
	        print("get")
	        return HttpResponse("get")
	
	    # 访问这个方法必须是psot请求方式
	    # 通过form表单发送post请求
	    # 出了form表单,我们还可以使用工具来模拟
	    def post(self,request):
	        print("post")
	        return HttpResponse("post")
	postman的官网地址:https://www.postman.com/downloads/
	apizza的挂网地址:http://www.apizza.net/
CBV的源码解析

	urlpatterns = [
	    url('^index/', views.index.as_view())
	    # 手动调用后会拿到view方法的返回值。变成了以下的样子
	    url('^index/', views.index.view)
	    # 那么此时Django会帮助我们调用一次这个方法,并且传递一个request请求过去。
	]
view方法解析
 那么我们再看看view方法干了些什么事情:只看红框内容即可
 
- 首先是根据cls实例化出一个对象了(这cls就是我们在视图内定义的类)
- 将request请求给这个对象作为属性
- 而args、kwargs则是防止有名分组或无名分组,用于接收分组产生的值。也一同赋给这个对象。
- 调用这个对象下面的dispatch方法,并将Django传递的参数一并传递过去了
dispatch方法解析
 再分析一下dispatch方法的作用:只关注红框内容即可
 
request.method.lower()将请求的方法变成小写的字符串
主要就是判断:发送请求的方法是否符合正常HTTP请求
	http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
如果符合的话:使用反射通过拿到的字符串去对象里查找相同名称的函数。比如:
	class index(View):
		def get(self,request):
			return HttpResponse('from GET')
	self = index类实例化的对象,并且拥有request、args、kwargs等属性
	# 等同于:如果request.method.Lower()是get的话,拿到get方法的函数对象
	handle = getattr(self,'get',None) # 地三个参数则是没有找到get方法或属性返回的
	handle = get函数对象
	handle(request,*args,**kwargs) # 等同于:get(self,request,*args,**kwargs)
调用时将request请求、一些额外参数都传递给了我们定义的类里面的get方法
演示:不定义人任何处理请求的函数
	class index(View):
    	pass

 浏览器得不到Django响应的任何数据!
get方法需要返回一个HttpResponse对象,没有返回的话,则页面报错
	class index(View):
		def get(self,request):
			print('......')

 注意:如果类里面没有定义处理对应请求的函数,浏览器得不到响应,专门处理某个请求的函数名一定要与请求名一致。
总结
而CBV的实现通过上述源码的分析也可以看出来,大致就是通过URL执行类里面的view方法,再通过其内部的dispatch方法进行分发处理,将浏览器请求交给我们的类里面对应的方法进行处理。









