視圖層
三板斧
""" HttpResponse 返回字符串類型 render 返回html頁面 並且在返回給瀏覽器之前還可以給html文件傳值 redirect 重定向 """ # 視圖函數必須要返回一個HttpResponse對象 正確 研究三者的源碼即可得處結論 # The view app01.views.index didn't return an HttpResponse object. It returned None instead. # render簡單內部原理 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)
JsonResponse對象
""" json格式的數據有什麼用? 前後端數據交互需要使用到json作爲過渡 實現跨語言傳輸數據 ensure_ascii=False 前端序列化 JSON.stringify() json.dumps() JSON.parse() json.loads() """ import json from django.http import JsonResponse def ab_json(request): user_dict = {'username':'jason好帥哦,我好喜歡!','password':'123','hobby':'girl'} # 先轉成json格式字符串 # json_str = json.dumps(user_dict,ensure_ascii=False) # 將該字符串返回 # return HttpResponse(json_str) # 讀源碼掌握用法 # return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False}) # 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參數
form表單上傳文件及後端如何操作
""" form表單上傳文件類型的數據 1.method必須指定成post 2.enctype必須換成formdata request.FILES request.FILES.get('file') """ 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 # 獲取POST請求數據 request.GET # 獲取GET請求數據 request.FILES # 獲取文件 request.body # 原生的瀏覽器發過來的二進制數據 後面詳細的講 request.path # 只能拿到路由無法拿到路由後面的參數 request.path_info # 和path一樣 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(function based view)與CBV(class based view)(重點)
- 視圖函數既可以是函數也可以是類
#CBV
#CBV路由層:
url(r'^login/',views.MyLogin.as_view())
視圖層:
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'')
def post(self,request):
return HttpResponse('post方法')
- CBV內部執行流程
# CBV本質上也是FBV,同樣也是views.函數內存地址 #CBV #路由 url(r'^login/', views.MyLogin.as_views()) ''' as_views()是類MyLogin所繼承的父類View下的一個類方法 views.MyLogin.as_views()會優先執行as_views()方法並將MyLogin作爲第一個參數傳入 as_views()方法是一個閉包函數,內部嵌套了函數view,並將view的內存地址作爲返回值返回 ''' # 路由層可變形爲:url(r'^login/', views.view) # 由此可以判斷出CBV與FBV在路由匹配上本質是一樣的,都是路由對應函數內存地址 # 後端 from django.views import View class MyLogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('post請求') ''' view函數在當瀏覽器訪問login時被觸發,此時會先產生一個MyLogin的對象綁定給變量self self.屬性,依照面向對象的查找順序先找自己再找對象所在的類,再找父類依次往上,直到找到爲止。 view方法最終會返回一個self.dispatch方法的執行結果 很顯然對象本身以及產生對象的MyLogin類中都沒有dispatch方法,只有MyLogin繼承的父類View中有 執行父類View下的dispatch方法,會先判斷瀏覽器的請求是否合法。 如果合法,就會通過getattr反射到MyLogin中對應的方法, handler = getattr(self, request.method.lower(), self.http_method_not_allowed) getattr(自定義類生成的對象self, 瀏覽器請求方式的小寫, 如果請求不合法就執行第三個參數) 假設請求爲get,handler = MyLogin下的get方法 假設請求爲post,handler = MyLogin下的post方法 return handler(request, *args, **kwargs) handler加括號,自動調用對應的方法執行,也就是實現了與FBV相同的展示效果 ''' # 結合源碼,細品 class View(object): http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] @classonlymethod def as_view(cls, **initkwargs): def view(request, *args, **kwargs): self = cls(**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) return view def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) 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())