【三板斧介绍】
1 用来处理请求的视图函数都必须返回HttpResponse对象-----完全正确!!! 2 diango视图函数里面返回值不用三板斧必报错 HttpResponse,render,redirect 3 查看3个的源码发现 HttpResponse是一个类 render是一个函数 4 5 --------------------------------------------- 6 class HttpResponse: 7 pass 8 ---------------------------------------------- 9 def render(): 10 return HttpResponse() 11 ---------------------------------------------- 12 def redirect(): 13 redirect_class = 类(祖先有个类是HttpResponse) 14 return redirect_class()
==============================
看三者的源码
。
。
【JsonResponse对象】
返回给浏览器一个json格式的字符串
1 路由 2 3 urlpatterns = [ 4 # json相关 5 path('ab_json/',views.ab_json), 6 7 ] 8 9 10 ---------------------- 11 views.py 12 13 def ab_json(request): 14 # 没有中文字符情况下,用返回json格式没有问题 15 user_dict = {'username': 'jason', 'password': '123', 'hobby': 'run'} 16 # 如果有中文字符,前端会给我们展示uncode编码格式 17 user_dict = {'username': 'jason讲课讲的真的好', 'password': '123', 'hobby': 'run'} 18 # 把user_dict发到前端去,然后以json格式展示 19 # 先转成json格式字符串,ensure_ascii=False 有中文字符也正常显示 20 json_str = json.dumps(user_dict, ensure_ascii=False) 21 # 将该字符串返回 22 return HttpResponse(json_str) 23 24 ensure_ascii=False 作用是取消在序列化的时候给中文编码,不然在页面上显示的时候就会将文字变成乱码了!!! 25 ==================== 26 上述需要手动去序列化, 27 但django给我们提供了一种更简介的模块:JsonResponse 28 29 JsonResponse主要序列化字典 针对非字典的其他可以被序列化的数据需要修改safe参数为False 30 31 return JsonResponse(user_dict) 32 ---- 33 ps:以后写代码很多时候可能需要参考源码及所学知识扩展功能,见下面的图 34 最终版,解除中文乱码 35 return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
序列化一个列表,会发现报错,默认只能序列化字典,序列化其他类型需要加safe=False参数
1 l = [111, 222, 333] 2 return JsonResponse(l, safe=False)
。
。
。
【form表单上传文件】
form表上传文件类型的时候,一定要是POST请求,然后enctype="multipart/form-data"
【request方法补充】
1 # request方法补充 2 print(request.path) # /ab_file/ 只能拿到路由 3 4 print(request.path_info) # /ab_file/ 5 6 print(request.get_full_path()) # /ab_file/?username=jason 可以获得完整的url 7 8 print(request.body) # 空的,原生的浏览器发过来的二进制数据
。
。
【CBV与FBV源码】
1 funtion 函数和路由之间的映射关系 2 class 类和路由之间的映射关系 3 4 5 FBV 基于函数的视图 6 7 def index(request):return HttpResponse对象 8 9 views.View 是个类!!! 10 --------------------------------------------------- 11 --------------------------------------------------- 12 CBV 基于类的视图比基于函数的视图 更加的灵活 13 在类里面只需要写跟请求方法相同的函数名,当路由触发了该类的视图函数的运行时,会根据请求方式的不同,自动触发对应的函数名函数的运行!!!函数的视图它是要在函数体代码里面自己加if判断请求方式是什么,然后才能去执行对应的函数!!! 14 15 会自动根据请求方法的不同自动匹配对应的方法并执行!!!
。
。
【CBV源码解析】
CBV特点:
能够直接根据请求方式的不同直接匹配到对应的方法执行
1 1.从CBV的路由匹配切入 2 path('login/', views.MyLoginView.as_view()) 3 1.类名点名字(名字的查找问题,先自身,再到类里找,再到父类里找!!) 4 2.类名点名字并加括号调用(两种情况静态方法staticmethod、绑定给类的方法classmethod) 5 ------------------------------------------------------------- 6 7 2.函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法 8 path('login/', views.Myloginview.as_view()) 变成了 9 path('login/', view) # CBV路由本质还是FBV 10 ------------------------------------------------------------- 11 12 3.浏览器地址栏访问login路由需要执行view函数!!! 13 view() 执行view函数 14 15 对象调用dispatch方法(注意查找顺序先自己的,再到产生对象的类里面,最后再到父类里面找!!一定要记住!!!!!!!!!!) 16 ------------------------------------------------------------- 17 18 4.研究父类中的dispatch方法 19 获取当前请求方法并转小写 20 之后利用反射获取类中对应的方法并执行 21 22 dispatch 发货,派遣,分派(v) 23 ------------------------------------------------------------- 24 25 class View: 26 @classmethod 27 def as_view(cls, **initkwargs): 28 def view(request, *args, **kwargs): 29 self = cls(**initkwargs) 30 return self.dispatch(request, *args, **kwargs) 31 32 self.dispatch() 这个地方注意: 33 查找顺序先自己的,再到产生对象的类里面,最后再到父类里面找 34 现在我们用的是父类里面的dispatch方法 如果在我们自己的类里面定义一个dispatch方法 35 那么这个地方self.dispatch()就运行自己类里面的dispatch方法!!! 36 后面经常在该出变换花招!!! 37 --------------------------- 38 39 def dispatch(self, request, *args, **kwargs): 40 handler = getattr(self, request.method.lower()) 41 return handler(request, *args, **kwargs)
。
。
。
【模板语法传值】
1 """ 2 {{ }}:主要与数据值相关 3 {% %}:主要与逻辑相关 4 5 django的模板语法是自己写的 跟jinja2不一样 6 7 1.针对需要加括号调用的名字, django模板语法会自动加括号调用你只需要写名字就行 8 2.模板语法的注释前端浏览器是无法查看的 {##} 9 3. 10 """ 11 ------------------------------------------------------------ 12 1.模板语法传值给模板层方法 13 def index(request) 14 name='jason' 15 age=18 16 return render(request, 'demo02.html', {'n1': name, 'a1': age}) 17 html页面 {{n1}} {{a1}} 这样拿值 18 # 传值方式1:精准传值 不浪费资源 针对多资源的传递书写麻烦 19 20 return render(request,'demo02.html', locals()) 21 html页面 {{name}} {{age}} 这样拿值 22 # 传值方式2:将函数名称空间中所有的名字全部传递 名字过多并且不使用的情况下比较浪费资源 23 ------------------------------------------------------------ 24 2.模板语法传值特性 25 1.基本数据类型正常展示 26 2.文件对象也可以展示并调用方法 27 3.函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参) 28 4.类名也会自动加括号调用 29 5.对象则不会 30 6.模板语法的注释,前端是识别不出来的,因为页面要先经过后端代码的处理,然后再发送给前端,经过后端代码的处理后,模板语法的注释直接就被去掉了,所以前端是看不到后端的模板语法的注释的!! 31 ps:总结针对可以加括号调用的名字,模板语法都会自动加括号调用!!! 32 -------------------------------------------------------------- 33 3.模板语法之过滤器(内置函数)
(传python基本数据类型)
1 views.py 2 3 def index(request): 4 # 模板语法可以传递的后端python数据类型 5 # 字典 6 my_dict = {'name': '张三', 'age': 18, 'gender': '男', 'hobby': ['篮球', '足球', '游泳']} 7 # 列表 8 my_list = ['apple', 'banana', 'orange', 'pear', 'grape', 'watermelon'] 9 # 字符串 10 my_str = 'hello world' 11 # 整数 12 my_int = 100 13 # 浮点数 14 my_float = 3.14 15 # 布尔值 16 my_bool = True 17 # 集合 18 my_set = {1, 2, 3} 19 # 元组 20 my_tuple = (1, 2, 3) 21 22 return render(request, 'index.html', locals()) 23 24 ------- 25 ------ 26 模板层 27 28 <body> 29 <p>{{ my_dict }}</p> 30 <p>{{ my_list }}</p> 31 <p>{{ my_str }}</p> 32 <p>{{ my_int }}</p> 33 <p>{{ my_float }}</p> 34 <p>{{ my_bool }}</p> 35 <p>{{ my_set }}</p> 36 <p>{{ my_tuple }}</p> 37 <p>{{ func }}</p> 38 </body> 39 40 41 路由:path('index/', views.index),
(函数传值)
1 <p>{{ func }}</p> #传递函数名会自动+()调用,但是模板语法不支持给函数传额外的参数:{{ func }} 2 3 <p>传类名的时候也会自动加括号调用(实例化){{ MyClass }}</p> 4 5 <p>{{ obj }}</p> #django内部能够自动判断当前的变量名是否可以加括号调用,如果可以就会自动执行,针对的是函数名和类名 6 7 {#<h1>也可以直接调用函数里面的三个方法</h1>#} 8 9 <p>{{ obj.get_class }}</p> 10 <p>{{ obj.get_func }}</p> 11 <p>{{ obj.get_self }}</p> 12 13 14 ---------------------- 15 views.py 16 17 def func(): 18 print('这是一个函数类型') 19 return '也有返回值,但是不支持有参数' 20 21 class MyClass(object): 22 def get_self(self): 23 return 'self' 24 25 @staticmethod 26 def get_func(): 27 return 'func' 28 29 @classmethod 30 def get_class(cls): 31 return 'cls' 32 33 # 对象被展示到html页面上,就类似于执行了打印操作,也会触发__str__方法 34 def __str__(self): 35 return '这是一个对象' 36 37 obj = MyClass() # 传对象
。
。
(模板语法的取值:固定的格式,只能采用“句点符” .)
1 <body> 2 <p>拿到字典里的第二个爱好:{{ my_dict.hobby.1 }}</p> 3 4 <p>取列表里面的第一个值,0是索引:{{ my_list.0 }}</p> 5 {#<h1>过滤器</h1>#} 6 <p>统计长度:{{ my_str|length }}</p> 7 8 {#如果布尔值为True,返回给我们的就是True,如果为False,返回给我们的就是default后面的值:这是啥啊#} 9 <p>默认值:{{ my_bool|default:'这是啥啊' }}</p> 10 11 </body> 12 13 14 ------------------ 15 -------------------
。
。
。
【模板语法之过滤器】
过滤器就类似于模板语法内置的内置方法,django内置有60多个过滤器
1 基本语法: 2 3 {{变量名|过滤器:参数}} 4 5 6 <p>统计长度:{{ my_str|length }}</p> 7 8 {#如果布尔值为True,返回给我们的就是True,如果为False,返回给我们的就是default后面的值:这是啥啊#} 9 <p>默认值:{{ my_bool|default:'这是啥啊' }}</p> 10 11 <P>文件大小:{{ file_size|filesizeformat }}</P> 12 <p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p> 13 <p>切片操作:{{ my_list|slice:'0:3:1' }}</p> 14 <p>切取字符(文章摘要,包括3个点):{{ info|truncatechars:9 }}</p> 15 <p>切取单词:不包含3个点,按照空格切{{ egl| truncatewords:9}}</p> 16 <p>移除特定的字符:切空格{{ msg|cut:' ' }}</p> 17 <p>拼接操作:{{ my_list|join:'$' }}</p> 18 <p>加法操作:{{ my_int|add:10 }}</p> 19 <p>加法操作:{{ my_str|add:msg }}</p> 20 <p>取消转义(不转是正确的):{{ h }}</p> 21 <p>转义(不转是正确的):{{ h|safe }}</p> 22 {#<p>转义(为什么不转义:容易崩掉):{{ s|safe }}</p>#} 23 <p>后端转义:{{ res }}</p> 24 25 26 27 28 ------------------ 29 ------------------ 30 views.py 31 32 # 文件的大小,转为我们认识的KB,MB,GB 33 file_size = 1243 34 35 # 日期格式化 36 import datetime 37 current_time = datetime.datetime.now() 38 39 # 文章摘要 40 info = ('由于两个月的奋战,导致很久没更新了。就是上回老周说的那个产线和机械手搬货的项目,好不容易等到工厂放假了,我就偷偷乐了 ...') 41 42 # 切取英文 43 egl = 'my name is xxx my age is 18 and i am a student' 44 45 # 移除字符 46 msg = 'I Love you but just only' 47 48 # 取消转义 49 h = '<h1>刘亦菲</h1>' 50 # s='<script>alert(123)</script>' 51 # 后端转义:以后再写全栈项目的时候前端代码不一定在前端页面书写,可以在后端写好,传给前端页面 52 from django.utils.safestring import mark_safe 53 hh = '<h1>小龙女</h1>' 54 res = mark_safe(hh) # 后端转义
。
。
。
【模板语法之标签】
(for标签)
1 <body> 2 3 {% for list in my_list %} 4 <p>{{ forloop }}</p> 5 {% endfor %} 6 7 </body> 8 9 forloop内置的模块,标记for循环是第几次 10 -------- 11 -------- 12 views.py 13 14 my_list = ['apple', 'banana', 'orange', 'pear', 'grape', 'watermelon']
==================================
for循环的用法:
<p>{{ list }}</p> # for出来的是一个个元素,相当于for i in
。
。
(if标签)
1 <body> 2 # if和else连用 3 4 {% if my_bool %} 5 <p>是真的</p> 6 {% elif my_str %} 7 <p>傻子,这是字符串</p> 8 {% else %} 9 <p>都是骗子</p> 10 {% endif %} 11 12 -------------------------------------------- 13 # if与for连用 14 15 {% for foo in my_tuple %} 16 {% if my_bool %} 17 <p>是真的</p> 18 {% elif my_str %} 19 <p>傻子,这是字符串</p> 20 {% else %} 21 <p>都是骗子</p> 22 {% endif %} 23 {% empty %} 24 {# <p>for循环的对象是空,根本没办法循环</p>#} 25 {% endfor %} 26 27 ----------------------------------------------- 28 # with起别名 29 30 <p>{{ my_dict.hobby.1 }}</p> 31 {% with my_dict.hobby.1 as zq %} 32 <p>{{ zq }}</p> 33 {% endwith %}
。
。
【自定义过滤器、标签、inclusion_tag】
1 如果想要自定义一些模板语法 需要先完成下列的三步走战略 2 1.在应用下创建一个名字必须叫templatetags的目录!!! 3 2.在上述目录下创建任意名称的py文件,比如mytags.py 4 3.在上述py文件内先编写两行固定的代码: 5 from django import template 6 7 register = template.Library() 8 9 10 # 自定义过滤器(固定的 最大只能接收两个参数) 11 12 ----------------------- 13 自定义的py文件 14 15 from django import template 16 17 register = template.Library() 18 19 20 # 自定义过滤器 21 @register.filter(name='baby') 22 def my_sum(v1, v2): 23 return v1 + v2 24 25 26 # 自定义标签(参数可以有多个) 27 @register.simple_tag(name='oldbaby') 28 def name(a, b, c, d): 29 return '%s-%s-%s-%s' % (a, b, c, d) 30 31 32 # 自定义inclusion_tag 33 @register.inclusion_tag('left_menu.html') 34 def left(n): 35 data = ['第{}项'.format(i) for i in range(n)] 36 return locals() # 将data传递给left_menu.html 37 # 第二种传值方式 38 # data={'data':data} 39 40 --------------------------- 41 --------------------------- 42 自定义过滤器的使用 43 44 <body> 45 46 {% load mytage %} 47 <p>{{ my_int|baby:666 }}</p> 48 49 {#<h2>自定义标签,标签多个参数之间用空格隔开</h2>#} 50 <p>{% oldbaby '王俊凯' '王源' '易烊千玺' '杨洋' %}</p> 51 52 <h2>inclusion_tag的使用</h2> 53 {% left 5 %} 54 55 </body>
(自定义inclusion_tag内部原理)
总结!!!
1 总结: 2 3 当html页面需要某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面上都需要使用到该局部,那么就考虑将该局部页面做成inclusion_tag形式
。
。
【模板的继承】
母板的继承(重要) 多个页面有很多相似的地方,只有,某一些局部在变化,可以采取下列方式: 方式1:传统的复制粘贴 ---------------------------------------------- 方式2:母板的继承: 1.在母板中提前使用block划定子板以后可以修改的区域 {% block 区域起个名称 %} 子模版可以修改的代码 {% endblock %} 2.子板继承模板(子模版要首先把系统自带的代码全部删掉) {% extends 'home.html' %} # 完全继承模板的代码 {% block 模板申明的可改区域名称 %} 子板自己的内容 {% endblock %} ---------------------------------------------- 母板中至少应该用block划定三个区域:页面内容区、css样式区、js代码区 母板中应该预留出给子版编写页面的区域,也应该预留出可以给子板编写css代码与js代码的区域 --------------------------------------------- 补充:子板也可以继续使用模板的内容 {{ block.super }} ---------------------------------------------- 模板的导入(了解) 将某个html的部分提前写好 之后很多html页面都想使用就可以导入 {% include 'myform.html' %}
(用到了导航条,巨幕,列表,面板)
1 views.py 2 3 # 模板的继承:主模板 4 def home(request): 5 return render(request, 'home.html') 6 7 8 # 模板继承里的loginn 9 def login(request): 10 return render(request, 'loginn.html') 11 12 13 # 模板继承里的reg 14 def reg(request): 15 return render(request, 'reg.html') 16 17 18 =============================================== 19 主模板:home.html 20 21 <!DOCTYPE html> 22 <html lang="en"> 23 <head> 24 <meta charset="UTF-8"> 25 <title>Title</title> 26 <script src="../static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script> 27 <script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script> 28 <link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css"> 29 <script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script> 30 {% block css %} 31 {% endblock %} 32 </head> 33 <body> 34 {#导航条#} 35 <nav class="navbar navbar-inverse"> 36 <div class="container-fluid"> 37 <!-- Brand and toggle get grouped for better mobile display --> 38 <div class="navbar-header"> 39 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" 40 data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> 41 <span class="sr-only">Toggle navigation</span> 42 <span class="icon-bar"></span> 43 <span class="icon-bar"></span> 44 <span class="icon-bar"></span> 45 </button> 46 <a class="navbar-brand" href="#">Brand</a> 47 </div> 48 49 <!-- Collect the nav links, forms, and other content for toggling --> 50 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> 51 <ul class="nav navbar-nav"> 52 <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> 53 <li><a href="#">Link</a></li> 54 <li class="dropdown"> 55 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" 56 aria-expanded="false">Dropdown <span class="caret"></span></a> 57 <ul class="dropdown-menu"> 58 <li><a href="#">Action</a></li> 59 <li><a href="#">Another action</a></li> 60 <li><a href="#">Something else here</a></li> 61 <li role="separator" class="divider"></li> 62 <li><a href="#">Separated link</a></li> 63 <li role="separator" class="divider"></li> 64 <li><a href="#">One more separated link</a></li> 65 </ul> 66 </li> 67 </ul> 68 <form class="navbar-form navbar-left"> 69 <div class="form-group"> 70 <input type="text" class="form-control" placeholder="Search"> 71 </div> 72 <button type="submit" class="btn btn-default">Submit</button> 73 </form> 74 <ul class="nav navbar-nav navbar-right"> 75 <li><a href="#">Link</a></li> 76 <li class="dropdown"> 77 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" 78 aria-expanded="false">Dropdown <span class="caret"></span></a> 79 <ul class="dropdown-menu"> 80 <li><a href="#">Action</a></li> 81 <li><a href="#">Another action</a></li> 82 <li><a href="#">Something else here</a></li> 83 <li role="separator" class="divider"></li> 84 <li><a href="#">Separated link</a></li> 85 </ul> 86 </li> 87 </ul> 88 </div><!-- /.navbar-collapse --> 89 </div><!-- /.container-fluid --> 90 </nav> 91 <div class="container-fluid"> 92 <div class="row"> 93 <div class="col-md-3"> 94 {# 列表组#} 95 <div class="list-group"> 96 <a href="/home/" class="list-group-item active"> 97 首页 98 </a> 99 <a href="/loginn/" class="list-group-item">登录</a> 100 <a href="/reg/" class="list-group-item">注册</a> 101 102 </div> 103 </div> 104 <div class="col-md-9"> 105 {# 面板#} 106 <div class="panel panel-primary"> 107 <div class="panel-heading"> 108 <h3 class="panel-title">Panel title</h3> 109 </div> 110 <div class="panel-body"> 111 {# 主页巨幕#} 112 {% block content %} 113 <div class="jumbotron"> 114 <h1>Hello, world!</h1> 115 <p>...</p> 116 <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> 117 </div> 118 {% endblock %} 119 </div> 120 </div> 121 </div> 122 </div> 123 </div> 124 {% block js %} 125 {% endblock %} 126 </body> 127 </html> 128 129 130 --------------------------- 131 子模板loginn.html 132 133 {% extends 'home.html' %} 134 135 {% block css %} 136 {# 可以在这里写自己的样式#} 137 <style> 138 h1 { 139 color: darkred; 140 } 141 </style> 142 {% endblock %} 143 {#home.html页面告诉我有一个区域叫content可以被修改,要修改么#} 144 {% block content %} 145 <h1 class="text-center">登录页面</h1> 146 <form action=""> 147 <p>username:<input type="text" class="form-control"></p> 148 <p>password:<input type="password" class="form-control"></p> 149 <input type="submit" class="btn btn-success"> 150 </form> 151 <p>模板的导入</p> 152 {% include 'wasai.html' %} 153 {% endblock %} 154 155 {% block js %} 156 <script>alert('登录页面')</script> 157 {% endblock %} 158 159 ----------------------------------- 160 子模板re.html 161 162 {% extends 'home.html' %} 163 164 {% block css %} 165 {# 可以在这里写自己的样式#} 166 <style> 167 h1 { 168 color: bisque; 169 } 170 </style> 171 {% endblock %} 172 home.html页面告诉我有一个区域叫content可以被修改,要修改么 173 {% block content %} 174 <h1 class="text-center">注册页面</h1> 175 <form action=""> 176 <p>username:<input type="text" class="form-control"></p> 177 <p>password:<input type="password" class="form-control"></p> 178 <input type="submit" class="btn btn-danger"> 179 </form> 180 <p>模板的导入</p> 181 {% include 'wasai.html' %} 182 {% endblock %} 183 184 {% block js %} 185 <script>alert('注册页面')</script> 186 {% endblock %} 187 188 === 189 总结:模板继承可以继承三个部分:css样式,js样式和主样式 190 子模板中可以有自己单独的样式 191 192 路由: 193
path('home/', views.home),
path('loginn/', views.login),
path('reg/', views.reg)
(一般情况下的补充:点击登录,跳转到登录的页面)
【模板的导入】
将页面的某一个局部当成模块的形式,哪个地方需要就可以直接导入使用即可
分类:
django
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)