视图层:三板斧问题,JsonResponse序列化,form表单上传文件,request对象的其他几个方法,CBV的书写和FBV的写法,CBV的源码分析.模板层:变量之分配,过滤器

视图层

三板斧问题

"""
httpResponse
	返回字符串
render
	返回html文件
redirect
	重定向
        return redirect('https:www.baidu.com/')  跳转别人的网址
        return redirect('/home/')   跳转自己的网址
"""

# 在视图函数中写函数跟普通函数不太一样
# djagno中使用的局部的request
def index(request):
    pass

def func(request):
    pass

'''所有的视图函数不能够没有返回值,并且返回值还必须是HttpResponse对象'''

The view app01.views.index didn't return an HttpResponse object.
It returned None instead.


# 其实我们的三板斧方法返回的都是HttpResponse对象

# 在flask中request使用的是全局的request
from ... import request
def index():
    pass

def func():
    pass

# 所有的视图函数都使用全局的request对象,会不会乱套? 不会乱套,如何做到不乱套的? 在源码中揭晓.

JsonResponse序列化

# json格式的数据?
主要就是实现跨语言数据传输

# 现在实现跨语言数据的传输使用的都是json,在以前使用的是xml

# 微信支付朝微信的后端发送参数的时候,使用的就是xml

json格式的数据特点:
{"username":"kevin","age":18}
{"username":"kevin","age":18}

# 之前学的是如何序列化的?
import json
json.dumps     -------------》 JSON.stringify()
json.loads		-----------》JSON.parse() 

# 在js中是如何做的
JSON.stringify()
JSON.parse()  # 对象

# 在Django中又该如何去序列化


# js中的对象
obj = new Object() # {}
obj = {} # {}

obj.username = 'kevin' # {'username':'kevin'}

consolo.log(obj.username)
------------------------------------------------------------------------

import json

from django.http import JsonResponse
from django.shortcuts import HttpResponse


# Create your views here.


def index(request):

    user_dict = {'username': '小红帽', 'password': 123, 'hobby': 'looking TV'}
    json_str = json.dumps(user_dict, ensure_ascii=False)
    # 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.
    # 列表
    # list = [1, 2, 3, 4]
    # 默认只能序列化字典 序列化其他需要加safe参数
    # return JsonResponse(list, safe=False)
  1. 列表形式

  2. 字典形式

form表单上传文件

# form表单上传文件的前提:
1. 请求方式必须是post
2. enctype必须是form-data

request对象的其他几个方法

request.GET
request.POST
request.FILES

request.path_info  #  /ab_request/ 
reqeust.path       #  /ab_request/ 
request.get_full_path() # /ab_request/  /ab_request/?username=kevin&age=11
# get_full_path()会接收路径后面的参数
request.body # 现在先不学,它能够接收浏览器发过来的二进制数据,BBS项目中学

C(class)BV的书写和F(function)BV的写法

# 目前写的都是FBV:function based view 基于函数的视图
# 在视图文件中书写类 CBV:class based view 基于类的视图

postman的官网地址:https://www.postman.com/downloads/
apizza的挂网地址:http://www.apizza.net/

# 所有的类必须继承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")

CBV的源码分析

# 我们第一次看Django的源码,面试题:你都看过Django的哪些源码,简单说说?

# CBV的源码、settings的源码、权限、频率、认证的、签发token的源码

一、CBV源码分析
准备工作:
新建一个Django项目
写一个基于类的视图


继承,写get,post方法

from django.shortcuts import render, HttpResponse

from django.views import View
from django.http import JsonResponse


# Create your views here.


class Test(View):

    def dispatch(self, request, *args, **kwargs):
        # codes
        obj = super().dispatch(self, request, *args, **kwargs)
        # codes
        return obj

    def get(self, request, *args, **kwargs):
        return HttpResponse('cbv_get')

    def post(self, request, *args, **kwargs):
        return HttpResponse('cbv_post')

视图写好之后写路由
把views导过来,

类名.as_view()  直接执行

from django.conf.urls import url
from django.contrib import admin
from appp01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 在这里写的 views.Test.as_view(),实际上就是as_view()里面view的内存地址
    url(r'^test/', views.Test.as_view()),

]
 

分析一下执行的流程:
1. 如果当初放的是函数内存地址不会去执行,请求来了经过路由做分发。
但是如果放的是函数加括号直接就执行了(程序一点一运行立马这里就执行),
执行Test.as_view的方法,

2. Test里面没有as_view,所以执行的是父类View里面的as_view方法

3. 打开父类的View找到as_view方法,类来调用就把类传入,定义了一个view函数,
最后返回了这个view,所以在路由层写的实际上就是view(as_view()内部的)
这个函数的内存地址。

4. 当请求来了,来了执行的实际上就是view加括号执行。在执行前
这里面外层函数有个cls(这个cls就是Test这个类,产生了对象赋值给了self。),
在内部函数有个对外部作用域的引用,所以这个view就是一个闭包函数。

5. 把请求的request对象赋到了self.request里面

  return self.dispatch(request, *args, **kwargs)

7. 最后返回了一个self.dispatch函数,其实就是在执行这个函数。


8. 这个dispatch函数就是生成的Test这个类的,这个Test类里面没有这个dispatch,
所以执行的是View的dispatch。

9. 所以请求来了就是执行dispatch方法

10. 这里面取到请求的小写,判断在不在self.http_method_names中,
如果是get请求在这个列表里面

11. 通过getattr反射,self是Test对象,找到get方法,
找不到返回错误提示(self.http_method_not_allowed)

handler=test对象中get方法的内存地址,


两层判断:


--------------------------看self.http_method_names源码--------------------------------

 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 

-------------------------------------------------------------------------------------

-------------------------self.http_method_not_allowed源码-----------------------------

    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 HttpResponseNotAllowed(self._allowed_methods())

    def options(self, request, *args, **kwargs):
        """Handle responding to requests for the OPTIONS HTTP verb."""
        response = HttpResponse()
        response['Allow'] = ', '.join(self._allowed_methods())
        response['Content-Length'] = '0'
        return response

    def _allowed_methods(self):
        return [m.upper() for m in self.http_method_names if hasattr(self, m)]
--------------------------------------------------------------------------------------
总结: 
源码执行的流程?
CBV源码分析
cbv和fbv
1 在views中写一个类,继承View,里面写get方法,post方法
2 在路由中配置: url(r'^test/', views.Test.as_view()),实际上第二个参数位置,
放的还是一个函数内存地址
3 当请求来了,就会执行第二个参数(request,参数),本质上执行view()
4 view内部调用了dispatch()方法
5 dispatch分发方法,根据请求方式不同,执行的方法不同

模板层

模板变量之分配

模板中的变量格式为:{{ 变量名 }}。

# 模板中取值一定使用的是句点符.
变量名中不能有空格或者标点符号,但是有一个例外,点(".")可以出现在变量中,
点后的可以是字典相关(字典的key或者字典内置方法)、对象的属性或方法、数字索引

# 模板中的函数一定不能够加括号,他们会自动帮你加括号调用

模板之过滤器

'''常用过滤器基本使用'''

Django自带的过滤器有好几十、但是我们没必要全部记住,只需要记住几个就行了
语法:
#1、
{{ 变量名|过滤器名 }}

#2、链式调用:上一个过滤器的结果继续被下一个过滤器处理
{{ 变量名|过滤器1|过滤器2 }}

#3、有的过滤器取需要参数
{{ 变量名|过滤器名:传给过滤器的参数 }}



//常用内置过滤器//

#0、default
#作用:如果一个变量值是False或者为空、None,使用default后指定的默认值,
否则,使用变量本身的值,如果value=’‘则输出“nothing”
{{ value|default:"nothing" }}

#1、default_if_none
#作用:如果只针对value是None这一种情况来设置默认值,需要使用default_if_none
#只有在value=None的情况下,才会输出“None...”,
{{ value|default_if_none:"None..." }}

#2、length
#作用:返回值的长度。它对字符串、列表、字典等容器类型都起作用,
如果value是 ['a', 'b', 'c', 'd'],那么输出是4
{{ value|length }}

#3、filesizeformat
#作用:将值的格式化为一个"人类可读的"文件尺寸(如13KB、4.1 MB、102bytes等等),
如果 value 是 12312312321,输出将会是 11.5 GB
{{ value|filesizeformat }}

#4、date
#作用:将日期按照指定的格式输出,如果value=datetime.datetime.now(),
按照格式Y-m-d则输出2019-02-02
{{ value|date:"Y-m-d" }}  

#5、slice
#作用:对输出的字符串进行切片操作,顾头不顾尾,如果value=“egon“,则输出"eg"
{{ value|slice:"0:2" }} 

#6、truncatechars
#作用:如果字符串字符多于指定的字符数量,那么会被截断。
截断的字符串将以可翻译的省略号序列(“...”)结尾,
如果value=”hello world egon 嘎嘎“,则输出"hello...",
注意8个字符也包含末尾的3个点
{{ value|truncatechars:8 }}

#7、truncatewords
#作用:同truncatechars,但truncatewords是按照单词截断,
注意末尾的3个点不算作单词,如果value=”hello world egon 嘎嘎“,
则输出"hello world ..."
{{ value|truncatewords:2 }}

其他请参考以下链接:

https://www.yuque.com/liyangqit/lb35ya/qclygk?inner=cde6dc1c

posted @ 2023-08-01 14:56  毓见  阅读(32)  评论(0)    收藏  举报