Django之--視圖層

視圖層

三板斧

"""
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())

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章