序列化、CBV源码分析、模版层
一、
主要就是实现跨语言数据传输
py中:
json.dumps 序列化 json.loads 反序列化
js中:
JSON.stringify() # json.dumps JSON.parse() # json.loads
django中:
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表单能上传文件的前提
<form action="" method="post" enctype="multipart/form-data"> 1. 请求方式必须是post 2. enctype必须是form-data
注:
enctype是编码类型的意思。
enctype="multipart/form-data" 是 HTML 表单元素中的一个属性,用于指定在提交表单时,浏览器要使用哪种编码类型来进行数据传输。它的作用是允许在表单中传输包含二进制数据(例如文件上传)的内容。
2、views代码
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就会报错:
TypeError at /sc_file/ expected str, bytes or os.PathLike object, not InMemoryUploadedFile
3、html文件
<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
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视图函数的书写方式
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、看源码先找到源码的入口
path('login/', views.MyLogin.as_view()),
注:MyLogin是自定义的类(视图层)
MyLogin.as_view() 即类调用方法
类名可以调用哪些方法:
1. 方法被@classmethod装饰器修饰的方法
类名来调用类方法有什么特殊之处:
会把类名自动当成第一个参数传递给方法的第一个形参cls
2. 被@staticmethod装饰器修饰的方法
2、第一步
@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
path('login/', View.view),
4、第三步
当请求来的时候,开始匹配路由login,就会调用View.view()
5、第四步
def view(request, *args, **kwargs): # self = MyLogin(**initkwargs) self = cls(**initkwargs) """ self: MyLogin() """ return self.dispatch(request, *args, **kwargs) # 这句话是最重要的
6、第五步
self.dispatch(request, *args, **kwargs)
7、第六步
找到了View类里面的dispatch方法
8、第七步
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请求?
方法重写
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、
模板中取值一定使用的是句点符.
模板中的函数一定不能够加括号,他们会自动帮你加括号调用
# 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、
语法: {{ obj | 过滤器名称:参数 }} 变量名字|过滤器名称:变量
date
过滤器:用于格式化日期。
<!-- 将日期对象格式化为 'Y年m月d日' 的形式 --> {{ my_date_variable|date:'Y-m-d' }}
default
过滤器:在变量值不存在时,使用默认值。
<!-- 如果 my_variable 不存在,将显示 "Not available" --> {{ my_variable|default:"Not available" }}
length
过滤器:获取列表或字符串的长度。
<!-- 显示 my_list 列表的长度 --> {{ my_list|length }}
truncatechars
过滤器:截断字符串到指定长度,并在末尾添加省略号。
<!-- 将 my_string 截断到30个字符,并添加省略号 --> {{ my_string|truncatechars:30 }}
lower
和 upper
过滤器:将字符串转换为小写或大写。
<!-- 将 my_string 转换为小写 --> {{ my_string|lower }} <!-- 将 my_string 转换为大写 --> {{ my_string|upper }}
slice
过滤器:对列表进行切片。
<!-- 获取 my_list 列表的前5个元素 --> {{ my_list|slice:":5" }} <!-- 获取 my_list 列表的第2到第5个元素 --> {{ my_list|slice:"1:5" }}
3、模版之标签
相比于模板中的变量,标签更为复杂一些,如
1、一些标签用来在输出中创建文本 2、一些标签用来进行流程控制(执行循环或者if判断) 3、一些标签用来将外部信息加载到模板中以供以后的变量使用
模板中的标签的格式为
# 1、 {% 标签名 %} # 2、大多数标签都需要接收参数 {% 标签名 参数1 参数2 %} # 3、一些标签需要有开始{% tag %}和结束标记{% endtag %} {% 标签名 %} ...内容... {% end标签名 %}
常用标签之for标签
#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、注意: {% 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标签
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标签
# 当用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为父页面
{% extends 'xxx.html' %}
2、关键字 block
block可以包裹任意一个块,也可以是一个空的地方
content为某一个块的名字
{% 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
{% block css %} {% endblock %}
4、模板的导入
在一个页面导入另一个页面
{% include 'hello.html' %}
5、bootstrap扣组件案例
<!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>