序列化、CBV源码分析、模版层
一、
主要就是实现跨语言数据传输
py中:
1 2 | json.dumps 序列化 json.loads 反序列化 |
js中:
1 2 | JSON.stringify() # json.dumps JSON.parse() # json.loads |
django中:
1 2 3 4 5 | from django.http import JsonResponse def index(request): d = { 'username' : 'kevin哈喽' , 'age' : 18 } return JsonResponse(d, safe = False ,json_dumps_params = { 'ensure_ascii' : False }) |
通过设置safe=False
,Django将允许序列化非字典类型的数据。这在您返回的数据不仅限于字典结构时非常有用,例如,您可以返回一个列表作为JSON响应。
1、form表单能上传文件的前提
1 2 3 4 5 | <form action = " " method=" post " enctype=" multipart / form - data"> 1. 请求方式必须是post 2. enctype必须是form - data |
注:
enctype是编码类型的意思。
enctype="multipart/form-data" 是 HTML 表单元素中的一个属性,用于指定在提交表单时,浏览器要使用哪种编码类型来进行数据传输。它的作用是允许在表单中传输包含二进制数据(例如文件上传)的内容。
2、views代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def sc_file(request): # 接收提交的文件数据 # POST只能获取到post请求的普通数据,文件数据拿不到 print (request.POST.get( 'username' )) # <QueryDict: {'username': ['jack']}> print (request.FILES) # 接收的是文件数据 # <MultiValueDict: {'my_file': [<InMemoryUploadedFile: 10056.jpg (image/jpeg)>]}> if request.method = = 'POST' : file_obj = request.FILES.get( 'my_file' ) with open (file_obj.name, 'wb' ) as f: for line in file_obj: f.write(line) return render(request, 'ff.html' ) |
注:
1. 接收文件使用的是 request.FILES
2. with open(file_obj.name, 'wb') as f: 处file_obj.name改为file_obj就会报错:
1 2 | TypeError at / sc_file / expected str , bytes or os.PathLike object , not InMemoryUploadedFile |
3、html文件
1 2 3 4 5 6 7 | <form action = " " method=" post " enctype=" multipart / form - data"> < input type = "text" name = "username" > <br> 上传文件:< input type = "file" name = "my_file" > <br> < input type = "submit" value = "提交" > < / form> |
1、request.FILES
1 2 3 4 5 6 7 8 | 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 request.body # 它能够接收浏览器发过来的二进制数据 |
1、CBV - Class-Based Views(基于类的视图)
CBV 是一种使用基于类的方式来实现视图的方法。它允许你将视图逻辑封装在类中,并通过类的方法来处理不同的 HTTP 请求方法(如 GET、POST 等)。
CBV 提供了很多内置的通用视图类,用于快速实现常见的 CRUD(创建、读取、更新、删除)操作。
2、FBV - Function-Based Views(基于函数的视图)
FBV 是一种使用函数的方式来实现视图的方法。在 FBV 中,每个视图都是一个独立的 Python 函数,根据不同的 HTTP 请求方法来处理请求。
在函数内部编写视图逻辑,可以通过请求对象获取用户提交的数据,然后返回 HTTP 响应。
比较两者,CBV 提供了更多的面向对象特性和可重用性,因为它可以利用类的继承和方法重写来实现视图的复用。而 FBV 相对来说更加简单,适合处理简单的视图逻辑。
在 Django 中,你可以根据项目需求和个人偏好选择使用 CBV 或 FBV 来实现视图功能。
3、CBV视图函数的书写方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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" ) |
4、在postman中提交form表单测试
注意:url要加完整的路径,后面的/浏览器回自动添加,postman不会
1、看源码先找到源码的入口
1 | path( 'login/' , views.MyLogin.as_view()), |
注:MyLogin是自定义的类(视图层)
MyLogin.as_view() 即类调用方法
类名可以调用哪些方法:
1. 方法被@classmethod装饰器修饰的方法
类名来调用类方法有什么特殊之处:
会把类名自动当成第一个参数传递给方法的第一个形参cls
2. 被@staticmethod装饰器修饰的方法
2、第一步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @classonlymethod def as_view( cls , * * initkwargs): # cls:MyLogin def view(request, * args, * * kwargs): self = cls ( * * initkwargs) if hasattr ( self , 'get' ) and not hasattr ( self , 'head' ): self .head = self .get self .setup(request, * args, * * kwargs) if not hasattr ( self , 'request' ): raise AttributeError( "%s instance has no 'request' attribute. Did you override " "setup() and forget to call super()?" % cls .__name__ ) return self .dispatch(request, * args, * * kwargs) return view |
3、第二步
上一步 return 返回view
1 | path( 'login/' , View.view), |
4、第三步
1 | 当请求来的时候,开始匹配路由login,就会调用View.view() |
5、第四步
1 2 3 4 5 6 7 | def view(request, * args, * * kwargs): # self = MyLogin(**initkwargs) self = cls ( * * initkwargs) """ self: MyLogin() """ return self .dispatch(request, * args, * * kwargs) # 这句话是最重要的 |
6、第五步
1 | self .dispatch(request, * args, * * kwargs) |
7、第六步
1 | 找到了View类里面的dispatch方法 |
8、第七步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def dispatch( self , request, * args, * * kwargs): # getattr: 反射 # 反射 # getattr setattr delattr hasattr # handler = getattr(self, 'get', self.http_method_not_allowed) # handler = getattr(self, 'post', self.http_method_not_allowed) # handler就是方法名,对象 # hander = get # hander = post # hander = self.http_method_not_allowed 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) |
9、如何让我写的CBV类只支持get请求或者只支持post请求?
方法重写
1 2 3 4 5 6 7 8 | class MyLogin(View): http_method_names = [ 'get' ,] # 类里面的方法名字不能够随便写,目前只能写get post等 # 访问这个地址必须是get请求方式 def get( self , request): # get() takes 1 positional argument but 2 were given print ( "get" ) return HttpResponse( "get" ) |
模板过滤器是一种用于在模板中对数据进行处理和格式化的工具。它们以管道符(|)后跟过滤器名的形式出现,用于对模板变量进行修改或转换。
过滤器能够帮助你在模板中进行一些简单的数据处理,例如格式化日期、字符串截断、转换大小写等。
1、
模板中取值一定使用的是句点符.
模板中的函数一定不能够加括号,他们会自动帮你加括号调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # views def func(request): d = { 'username' : 'zjz' , 'age' : 18 , 'hobby' : [ '喝酒' , '抽烟' , '打牌' ]} def index(): return ( 'from index' ) return render(request, 'temp.html' , context = locals ()) # html文件 <div> <p> {{ d.hobby. 1 }} # 1是列表的下标 {{ index }} < / p> < / div> |
2、
1 2 | 语法: {{ obj | 过滤器名称:参数 }} 变量名字|过滤器名称:变量 |
date
过滤器:用于格式化日期。
1 2 | <! - - 将日期对象格式化为 'Y年m月d日' 的形式 - - > {{ my_date_variable|date: 'Y-m-d' }} |
default
过滤器:在变量值不存在时,使用默认值。
1 2 | <! - - 如果 my_variable 不存在,将显示 "Not available" - - > {{ my_variable|default: "Not available" }} |
length
过滤器:获取列表或字符串的长度。
1 2 | <! - - 显示 my_list 列表的长度 - - > {{ my_list|length }} |
truncatechars
过滤器:截断字符串到指定长度,并在末尾添加省略号。
1 2 | <! - - 将 my_string 截断到 30 个字符,并添加省略号 - - > {{ my_string|truncatechars: 30 }} |
lower
和 upper
过滤器:将字符串转换为小写或大写。
1 2 3 4 5 | <! - - 将 my_string 转换为小写 - - > {{ my_string|lower }} <! - - 将 my_string 转换为大写 - - > {{ my_string|upper }} |
slice
过滤器:对列表进行切片。
1 2 3 4 5 | <! - - 获取 my_list 列表的前 5 个元素 - - > {{ my_list| slice : ":5" }} <! - - 获取 my_list 列表的第 2 到第 5 个元素 - - > {{ my_list| slice : "1:5" }} |
3、模版之标签
相比于模板中的变量,标签更为复杂一些,如
1 2 3 | 1 、一些标签用来在输出中创建文本 2 、一些标签用来进行流程控制(执行循环或者 if 判断) 3 、一些标签用来将外部信息加载到模板中以供以后的变量使用 |
模板中的标签的格式为
1 2 3 4 5 6 7 8 9 10 | # 1、 { % 标签名 % } # 2、大多数标签都需要接收参数 { % 标签名 参数 1 参数 2 % } # 3、一些标签需要有开始{% tag %}和结束标记{% endtag %} { % 标签名 % } ...内容... { % end标签名 % } |
常用标签之for标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #1、遍历每一个元素: { % for person in person_list % } <p>{{ person.name }}< / p> { % endfor % } #2、可以利用{% for obj in list reversed %}反向循环。 #3、遍历一个字典: { % for key,val in dic.items % } <p>{{ key }}:{{ val }}< / p> { % endfor % } #4、循环序号可以通过{{ forloop }}显示 forloop.counter 当前循环的索引值(从 1 开始) forloop.counter0 当前循环的索引值(从 0 开始) forloop.revcounter 当前循环的倒序索引值(从 1 开始) forloop.revcounter0 当前循环的倒序索引值(从 0 开始) forloop.first 当前循环是第一次循环则返回 True ,否则返回 False forloop.last 当前循环是最后一次循环则返回 True ,否则返回 False forloop.parentloop 本层循环的外层循环 #5、for标签可以带有一个可选的{% empty %} 从句,在变量person_list为空或者没有被找到时,则执行empty子句 { % for person in person_list % } <p>{{ person.name }}< / p> { % empty % } <p>sorry,no person here< / p> { % endfor % } 了解:Django框架的 for 循环,没有 break 和 continue 方法,可以使用自定义过滤器实现forloop | continue 和forloop | break ,参考:https: / / djangosnippets.org / snippets / 2093 / |
常用标签之if标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # 1、注意: { % if 条件 % }条件为真时 if 的子句才会生效,条件也可以是一个变量, if 会对变量进行求值,在变量值为空、或者视图没有为其传值的情况下均为 False # 2、具体语法 { % if num > 100 or num < 0 % } <p>无效< / p> { % elif num > 80 and num < 100 % } <p>优秀< / p> { % else % } <p>凑活吧< / p> { % endif % } #3、if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。 #4、判断条件中可以引入过滤器 { % if athlete_list|length > 1 % } Team: { % for athlete in athlete_list % } ... { % endfor % } { % else % } Athlete: {{ athlete_list. 0.name }} { % endif % } 过滤器length返回的数字可用于与数字进行比较,除此之外大多数过滤器返回的都是字符串并不能用于与数字比较 #5、补充标签firstof 针对下述多分支 { % if var1 % } {{ var1 }} { % elif var2 % } {{ var2 }} { % elif var3 % } {{ var3 }} { % endif % } 可以简写为一行 { % firstof var1 var2 var3 % } 也可以定义一个备用值,当var1、var2、var3均无值的时使用 { % firstof var1 var2 var3 "fallback value" % } |
常用标签之with标签
1 2 3 4 5 6 7 | d = { 'username' : 'kevin' , 'age' : 18 , 'info' : '这个人有点意思' , 'hobby' :[ 111 , 222 , 333 ,{ 'info' : 'NB' }]} { % with d.hobby. 3.info as nb % } <p>{{ nb }}< / p> 在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式 <p>{{ d.hobby. 3.info }}< / p> { % endwith % } |
常用标签之csrf_token标签
1 2 3 4 5 6 7 8 9 10 11 12 | # 当用form表单提交POST请求时必须加上标签{% csrf_token%},该标签用于防止跨站伪造请求 <form action = " " method=" POST"> { % csrf_token % } <p>用户名:< input type = "text" name = "name" >< / p> <p>密码:< input type = "password" name = "pwd" >< / p> <p>< input type = "submit" value = "提交" >< / p> < / form> # 具体工作原理为: # 1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如<input type="hidden" name="csrfmiddlewaretoken" value="dmje28mFo...OvnZ5"> # 2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份 # ps:什么是跨站请求伪造(英语:Cross-site request forgery)详见附录2 |
继承:继承之后的页面跟被继承的页面一模一样
继承之后,要自己在基础html页面中划分要修改的区域,继承一方进行修改
1、关键字 extends
在子页面书写,xxx.html为父页面
1 | { % extends 'xxx.html' % } |
2、关键字 block
block可以包裹任意一个块,也可以是一个空的地方
content为某一个块的名字
1 2 3 4 5 | { % block content % } <h1>日子常新,未来可期!< / h1> <p>人间烟火,山河远阔,无一是你,无一不是你< / p> <p><a class = "btn btn-primary btn-lg" href = "#" role = "button" >诗和远方< / a>< / p> { % endblock % } |
3、子页面为某一个标签设置css(js 也一样)
在主页面划分一个空的block,子页面中使用block写css
1 2 3 | { % block css % } { % endblock % } |
4、模板的导入
在一个页面导入另一个页面
1 | { % include 'hello.html' % } |
5、bootstrap扣组件案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >Title</ title > < link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> < script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></ script > < script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></ script > </ head > < body > < nav class="navbar navbar-inverse"> < div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> < div class="navbar-header"> < button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> < span class="sr-only">Toggle navigation</ span > < span class="icon-bar"></ span > < span class="icon-bar"></ span > < span class="icon-bar"></ span > </ button > < a class="navbar-brand" href="#">Brand</ a > </ div > <!-- Collect the nav links, forms, and other content for toggling --> < div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> < ul class="nav navbar-nav"> < li class="active">< a href="#">Link < span class="sr-only">(current)</ span ></ a ></ li > < li >< a href="#">Link</ a ></ li > < li class="dropdown"> < a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown < span class="caret"></ span ></ a > < ul class="dropdown-menu"> < li >< a href="#">Action</ a ></ li > < li >< a href="#">Another action</ a ></ li > < li >< a href="#">Something else here</ a ></ li > < li role="separator" class="divider"></ li > < li >< a href="#">Separated link</ a ></ li > < li role="separator" class="divider"></ li > < li >< a href="#">One more separated link</ a ></ li > </ ul > </ li > </ ul > < form class="navbar-form navbar-left"> < div class="form-group"> < input type="text" class="form-control" placeholder="Search"> </ div > < button type="submit" class="btn btn-default">Submit</ button > </ form > < ul class="nav navbar-nav navbar-right"> < li >< a href="#">Link</ a ></ li > < li class="dropdown"> < a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown < span class="caret"></ span ></ a > < ul class="dropdown-menu"> < li >< a href="#">Action</ a ></ li > < li >< a href="#">Another action</ a ></ li > < li >< a href="#">Something else here</ a ></ li > < li role="separator" class="divider"></ li > < li >< a href="#">Separated link</ a ></ li > </ ul > </ li > </ ul > </ div > <!-- /.navbar-collapse --> </ div > <!-- /.container-fluid --> </ nav > < div class="container-fluid"> < div class="row"> < div class="col-md-3"> < div class="list-group"> < a href="#" class="list-group-item active"> 起点 </ a > < a href="/login/" class="list-group-item">登录</ a > < a href="/register/" class="list-group-item">注册</ a > < a href="/bq/" class="list-group-item">回原点</ a > </ div > </ div > < div class="col-md-9"> < div class="panel panel-primary"> < div class="panel-heading">Panel heading without title</ div > < div class="panel-body"> < div class="jumbotron"> {% block content %} < h1 >永远十八,永远热泪盈眶!</ h1 > < p >人间烟火,山河远阔,无一是你,无一不是你</ p > < p >< a class="btn btn-primary btn-lg" href="#" role="button">诗和远方</ a ></ p > {% endblock %} < div class="row"> < div class="col-sm-6 col-md-4"> < div class="thumbnail"> < img src="https://th.bing.com/th/id/R.1363fff14ac660729966b15ed3ad0613?rik=Clu%2bvv4ZhfF3xA&riu=http%3a%2f%2fimg.ts.cn%2f003%2f523%2f914%2f00352391449_110e6504.jpg&ehk=pAoDU5Z5PM%2bAGGTi%2fjFpRneEpsghtBugLhmPAgZ%2fYMg%3d&risl=&pid=ImgRaw&r=0" alt="..."> < div class="caption"> < h3 >海棠未雨</ h3 > < p >...</ p > < p >< a href="#" class="btn btn-primary" role="button">Button</ a > < a href="#" class="btn btn-default" role="button">Button</ a > </ p > </ div > </ div > </ div > < div class="col-sm-6 col-md-4"> < div class="thumbnail"> < img src="https://th.bing.com/th/id/R.373fa8856674ed20fdbcc32548f907b4?rik=Xm0QJfBfZEhuDQ&riu=http%3a%2f%2fimg.mp.itc.cn%2fupload%2f20160908%2f9856d4f910aa40588853e64d5123521d_th.jpg&ehk=HCDdYJ5YRQTkxi4wiVKU36n9ssllHBEE0qyZrk9y%2bwo%3d&risl=&pid=ImgRaw&r=0" alt="..."> < div class="caption"> < h3 >梨花先雪</ h3 > < p >...</ p > < p >< a href="#" class="btn btn-primary" role="button">Button</ a > < a href="#" class="btn btn-default" role="button">Button</ a > </ p > </ div > </ div > </ div > < div class="col-sm-6 col-md-4"> < div class="thumbnail"> < img src="https://image.scol.com.cn/data/attachment/forum/202006/22/162921a691l373kgvlgqkb.jpg" alt="..."> < div class="caption"> < h3 >一半春休</ h3 > < p >...</ p > < p >< a href="#" class="btn btn-primary" role="button">Button</ a > < a href="#" class="btn btn-default" role="button">Button</ a > </ p > </ div > </ div > </ div > </ div > </ div > </ div > </ div > </ div > </ div > </ div > </ body > </ html > |