• Django视图层模版层全面解析全网最细的教程


    一、网页伪静态

    		什么是伪静态网页呢 ?
    			我们之前写的接口后缀都是正常网址(https://blog.csdn.net/MeiJin_)而伪静态后缀像是一个文件(https://blog.csdn.net/MeiJin_.html)
    			搜索引擎一看到后缀是一个文件会认为是一个具体的文件 就回收录下来 后续不用更改的 被收录的也意味着被查询的概率越大
    			将动态网页伪装成静态网页 从而提升网页被搜索引擎收录的概率 表现形式就是网址看着想一个具体的文件路径
    	
    		那我们需要怎样去实现这个操作呢 ?
    			把路由设置成	Path('index.html', view.index)		# 那么访问的时候就需要使用index.html去访问了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    二、视图层

    1.视图函数的返回值问题

    		我们都知道视图函数会返回一个值但是我们这种情况呢?
    			def index(request):
    				return None
    			报错信息是ValueError at /index/
    			The view app01.views.test didn't return an HttpResponse object. It returned None instead.
    			
    		翻译过来意思就是视图函数必须返回一个HttpResponse对象
    		但是我们三板斧总共有三个 HttpResponse、render、redirect
    		我们通过源码去查看这三个都是类 类名加括号产生一个对象 所以返回的都是对象
    			
    			'''源码大概展示'''
    	    	class HttpResponse(HttpResponseBase):
    	            pass
    	   		def render():
    	            return HttpResponse(...)
    	        def redirect(to, *args, permanent=False, **kwargs):
    		        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    		        return redirect_class(resolve_url(to, *args, **kwargs))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    2.视图函数返回Json格式数据

    		视图函数返回Json格式的数据怎么操作呢 ?
    		有两种方法:
    			1.直接通过json模块
    				import json
    				def index(request):
    					user_dict = {'name':'Like', 'Age':'20','hobby':['篮球','音乐','学习']}
    					json_str = json.dumps(user_dict,ensure_ascii=False)		# 如果数据中有中文会进行编码 如果不想编码需要使用ensure_ascii
    					return HttpResponse(json_str)
    					
    			2.使用Django的中JsonResponse 独立于三板斧之外
    				from django.http import JsonResponse
    				def index(request):
    					user_dict = {'name':'Like', 'Age':'20','hobby':['篮球','音乐','学习']}
    					return JsonResponse(user_dict)		
    				# 但是这个时候也会自动编码中文 这个时候我们不需要 就需要去查看源码了
    					
    				'''源码大概展示'''
    			    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
    		                 json_dumps_params=None, **kwargs):
    		        if safe and not isinstance(data, dict):
    		            raise TypeError(
    		                'In order to allow non-dict objects to be serialized set the '
    		                'safe parameter to False.'
    		            )
    		        if json_dumps_params is None:
    		            json_dumps_params = {}
    		        kwargs.setdefault('content_type', 'application/json')
    		        data = json.dumps(data, cls=encoder, **json_dumps_params)
    		        super().__init__(content=data, **kwargs)
    		        
    			我们发送的数据都会被data接受 后面的encode没有接受任何参数 再往下看**json_domps_params中的**是干嘛的呢?
    		    **在这调用一个函数就是 **在实参中起作用 将字典打散成关键词参数 但是现在字典是空的 我们现在把上面的None改成
    		  	ensure_ascill = False 也就意味着不走if分支 就回把这个添加到字典中就成了json.dumps(ensure_ascii':False)
    			这个时候我们就知道了 把他添加一个False不走分支就好了
    			
    			序列化非字典类型的数据还需要指定safe参数为False
    			如果没有修改则报错 In order to allow non-dict objects to be serialized set the safe parameter to False.
    
    		    所以最终解法:
    		    	def test(request):
    		    		user_dict = {'name': 'Like', 'Age': '20', 'hobby': ['篮球', '音乐', '学习']}
    		    		user_dict = ['name', 'like', 'Age', '疯了呀!!']
    		    		return JsonResponse(user_dict, json_dumps_params={'ensure_ascii': False}, safe=False)	
    		    		# 即可兼容中文了 也可以兼容列表了
    
    • 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

    在这里插入图片描述

    3.Form表单携带文件数据

    我们在后台想接收到文件数据 那么会使用到From表单但是From表单使用之前的方法只会拿到名字 获取不到文件信息 这是因为在Django里面还需要设置一个参数才会有效

    在这里插入图片描述

    		form表单需要具备的条件
    			1.首先From的method属性值必须是POST发送数据
    			2.表单必须有属性 enctype="multipart/form-data"
    		后端获取文件数据的操作
    			不再是request.post 而是request.FILES
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    4.FBV与CBV

    		FBV基于函数视图 现在我们VIEWS里面写的都是函数 这个就是FBV
    		        def index(request):
    		            return HttpResponse()
    		            
    		        path('index/', views.index)
    			        
    		CBV基于类的视图 CBV就是使用类来写了
    				from django import views
    				class MyView(views.View):
    					def get(self, request):					# get post 两个方法是固定的 !
    		                return HttpResponse('我是CBV里面的get方法')
    		            def post(self, request):
    		                return HttpResponse('我是CBV里面的post方法')
    		                
    		         path(test/', views.MyView.as_view())		# CBV路由匹配 不再是点一个函数名而是一个类名加方法名
    		         
    		当发送一个get请求会自动触发get 发送一个post也会自动触发post
    		CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    5.CBV源码分析

    		为什么不同方法来能够触发不同的代码呢 ? 我们一起来看看源码!!!
    
    		首先是源码分析入口
    			path('test/', views.MyView.as_view())		# 类点一个名字相当于一个对象点一个名字并且还加了括号 应该是方法了
    			
    			'''源码大概展示'''
    			1.研究绑定给类as_view的方法 只做了一件事 定义了view方法又给view返回出去了
    				def as_view(....):
    					def view(...):
    						pass
    					return view
    			2.所以到此我们就知道了调用方法之后就会产生一个结果viewCBV最终的本质就是
    				path('test/', views.view)		# 最终还是回到FBV一摸一样的形式 只是这个VIew不是我们写的
    			3.访问test触发view执行
    				def view(...):			
    					obj = cls()					# 现在cls是我们自己定义的类 myView() 产生一个对象
    					return obj.dispath()		# 涉及到对象点名字 一定要确定对象是谁 再确定查找顺序 我们没有写 就要去找dispath发现是view的
    			4.研究dispatch方法
    			   	def dispatch(...):				# 判断当前请求方法在不在当前请求方法里面 
    		          func_name = getattr(obj,request.method.lower())	
    		          func_name(...)				# getattr拿到自己的写的对象 找自己有没有请求方法 我们有写则直接执行 这就是CBV
    		          								# 这八个请求方法 
    		     # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    三、模版层

    1.模版语法传值

    		方式1:	指定名称	不浪费资源空间 但是不能传很多
    			def name(request):
    				name = 'LIke'
    				return render(request, 'name.html',{'name':name})			
    				
    		方式2: 关键字locals()		将整个局部名称空间中的名字去全部传入简单快捷 如果很少的话则浪费资源空间		
    			def name(request):
    				name='LIke' age=20 gender='male'
    				return render(request, 'name.html', locals())		# 前端页面使用 {{ name }}就可以使用了 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    2.模版语法传值范围

    		关于模版语法传值的范围是很大的 我们的八大数据类型都可以传值还有函数以及类
    		1.函数名的传递会自动加括号执行并将返回值展示到页面上 需要写上return返回值才可以返回到页面
    			注意函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
    			
    		2.类名的传递也会自动加括号产生对象内存地址并展示到页面上
    			如果想使用的话可以通过对象句点符的方式点出来
    			
    		ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    3.模版语法过滤器

    		模版语法其实在页面上也有像Python一样内置方法 模版语法也提供了 就是为了操作数据 可以看成Python内置函数
    		模版语法 	{{ 变量名| 语法方法 }}
    					{% 变量名| 语法方法 %}
    
    	    

    格式化时间:{{ res | date:'Y-m-d H:i:s' }}

    加法运算:{{ f | add:123 }}

    统计长度:{{ str| length }}

    统计文件大小:{{ font_size | filesizeformat }}

    数据切片:{{ list | slice:"0:2" }}

    字符截取:{{ b | truncatechars:16 }}

    单词截取:{{ b | truncatewords:3 }}

    语法转义:{{ se | safe }}

    {{ scr | safe}}

    # 运行html

    {{ res }}

    # 运行script 有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入 from django.utils.safestring import mark_safe # 导入模块 scr1 = '' # 通过后台写好 前端直接使用 查看下图 res = mark_safe(scr1)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    4.模版语法标签(类似于Python流程控制)

    	if elif else
    	
    			{% if 条件 %}  条件一般是模板语法传过来的数据  直接写名字使用即可
    		        条件成立执行的代码
    		    {% elif 条件1 %}
    		 		  条件1成立执行的代码	
    		    {% else %}
    		       	 条件都不成立执行的代码
    		    {% endif %}
    		    
    	for循环(html页面输入for Tab后面会自动补全)需要用到一个关键字 forloop 用来记录循环第几次的
    			{% for i in str %}
    			    {% if forloop.first %}
    			        

    这是我循环第一次!!

    {% elif forloop.last %}

    这是我最后一次循环!!

    {% else %}

    {{ i }}

    {% endif %} {% empty %}

    我是判断当前标签是否有值的哦! 如果是空我就运行啦!!

    {% endfor %}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    5.自定义标签函数、过滤器、Inclusion_tag

    		如果想自定义 必须先做以下三件事
    			1.在应用下创建一个名为templatetags文件夹
    			2.在该文件夹创建任意名称的py文件
    			3.在该py文件内编写自定义相关代码
    				from django.template import Library
    				register = Library()		# 这两行代码在py文件中固定格式
    
    	    自定义过滤器			
    		    @register.filter(name='myfilter')	# 过滤器最多最多只能有两个参数 不能有三个 
    		    def my_add(a, b):
    		        return a + b
    
    	  	自定义标签函数							# 可以穿任意个数参数
    		    @register.simple_tag(name='mt')		
    		    def func(a, b, c, d):
    		        return a + b + c + d
    		        
    		自定义inclusion_tag
    		    @register.inclusion_tag(filename='it.html')		# it.html页面里面放index需要添加的内容样式 需要自己创建it.html
    		    def index(n):
    		        html = []
    		        for i in range(n):
    		            html.append('第%s页'%i)
    		        return locals()
    		  
    		  	it.html里面的内容:
    				
      {% for i in html %}
    • {{ i }}
    • {% endfor %}
    三个方法调用方式 {% load mytag %} # 加载自定义的标签 {{ i | myfilter:1 }} {% mt 1 2 3 4 %} {% index 10 %} # 可以通过传参产生几个标签
    • 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

    在这里插入图片描述

    6.模版继承

    		{% extends 'html文件名' %}			# 新建一个页面 第一行写入继承代码
    	   	{% block 名字 %}						# 可以通过这个方式定位到页面的位置
    	    	模板内容							# 这个地方填写新的代码
    		{% endblock %}
    	   	{% block 名字 %}
    	    	子板内容
    	    {% endblock %}
    	 	一般情况下母板中至少应该有三个区域使得扩展性更高!!!
    	    	css content js
    	    {% block css %}
    		{% endblock %}
    	    {% block content %}
    		{% endblock %}
    	    {% block js %}
    		{% endblock %}
    		
    	   	'''子板中还可以使用母板的内容  {{ block.super }} 	让他使用之前原主页的内容'''	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述
    在这里插入图片描述

    7.模版导入

    		将html页面的某个部分当做模块的形式导入使用
    	    {% include '网页名称.html' %}
    
    • 1
    • 2

    在这里插入图片描述

    技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点点赞收藏+关注谢谢支持 !!!

  • 相关阅读:
    RGB格式
    C++学习 --vector
    Java进阶篇--LockSupport
    Pose Animator:使用实时TensorFlow.js模型的SVG动画工具
    计算机网络复习03——数据链路层
    电源车3d虚拟元宇宙展厅方便用户随时看车买车
    如何快速将txt类型的日志文件转换为excel表格并进行数据分析报表统计图(如:饼图、折线图、柱状图)?
    原画设计邀约话术
    全部售罄!1,000 多个Sports Land NFT 在 24 小时内被抢空!
    【狂神】MyBatisPlus笔记
  • 原文地址:https://blog.csdn.net/MeiJin_/article/details/126667627