今日内容回顾(django 视图层 )

今日内容回顾

网页伪静态

将动态伪装成静态网页,从而提升网页被搜索引擎收录的概率

表现形式就是网址看着像一个具体的文件路径

直接添加后缀即可

path("index.html",view.index)

视图层

视图函数的返回值问题

在视图函数中,其返回值必须返回的是一个HttpResponse对象

def func(request):
    pass
# 报错!!!
The view app01.views.func didn't return an HttpResponse object. It returned None instead.

# HttpResponse是一个类,在使用视图函数中它必须要返回一个HttpResponse对象

    class HttpResponse(HttpResponseBase):
        """
        An HTTP response class with a string as content.

        This content that can be read, appended to, or replaced.
        """
        streaming = False
# 关于三板斧
    def func(request):
        # 1.return HttpResponse("返回值")
        # 2.return render(request,"路由","xxx")
        # 3.redirect("路由")
 """
 在视图函数的使用中,HttpResponse,redirect,render
 它们都是HttpResponse本身或者间接调用或继承了HttpResponse,
 所以它们符合上述,视图函数中它必须要返回一个HttpResponse对象
 """
  
# 源码中的,render、redirect。
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))

视图函数返回json格式数据

需求让视图函数返回一个json格式数据

def func(request)
	user_dict = {'name': 'jason老师', 'pwd': 123,
                 'hobby': ['read', 'run', 'music']}
    # 方式1,使用json模块先序列化在返回
   	json_str = json.dumps(user_dict, ensure_ascii=False)
   return HttpResponse(json_str)
	# 方式2,直接使用JsonResponse,相对于方式1更加便捷。
   return JsonResponse(user_dict)

"""
JsonResponse默认只序列化字典类型的数据
	如果序列非字典类型的数据还需要指定safe参数为False
"""
from django.http import JsonResponse
   class JsonResponse(HttpResponse):
    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        if json_dumps_params is None:
            json_dumps_params = {}
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        
   JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})

form表单携带文件数据

"""
form表单需要具备的条件
1. menthod属性值必须是	post
2.entype属性值必须是		multipart/form-data
"""
# 格式如下:
	<form action="" method="post"   enctype="multipart/form-data"></form>
		
# 后端获取文件
	def func(request):
    	print(request.FILES)  # 需要用点FILES的方式才能够获取到文件数据
		return render(request,'xxx.html')
    
<MultiValueDict: {'file': [<InMemoryUploadedFile: image-20220614222152619.png (image/png)>]}>

    
    

FBV与CBV

基于函数的视图

FBV(function base views) 就是在视图里使用函数处理请求

# urls.py下
	path('index/', views.index)
# views.py下
def index(request):
    return HttpResponse()
基于类的视图

CBV(class base views) 就是在视图里使用类处理请求。

# urls.py下
	path('func/', views.MyView.as_view())
# views.py下
from django import views

class MyView(views.View):
     def get(self, request):
         return HttpResponse('我是CBV里面的get方法')
     def post(self, request):
         return HttpResponse('我是CBV里面的post方法')
# CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
CBV源码分析
# urls.py下
	path('func/', views.MyView.as_view())
# views.py下
from django import views

class MyView(views.View):
     def get(self, request):
         return HttpResponse('我是CBV里面的get方法')
     def post(self, request):
         return HttpResponse('我是CBV里面的post方法')
# CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行


源码分析入口
    	path('func/', views.MyView.as_view())
    
1. 首先分析自己定义的类中并没有as_view,那么在父类View中找方法as_view
2. 父类中有as_view并且在其 中又定义view并且将view当作返回值返回出去
3. 那么CBV路由匹配的本质也就相当于path('func/', views.view)
		父类中的view方法
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)   # cls就等于我们自己定义的类
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *view, **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)
       
4. 调用vie函数返回的是self.dispatch(request, *args, **kwargs)
5. 相当于MyView.dispatch(request, *args, **kwargs)
6. 从MyView自身查找dispatch,没有就从父类查找
	父类中的 http_method_names列表
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
	父类中的dispatch方法
    def dispatch(self, request, *args, **kwargs):
        # (当前请求方法转为小写字母,假设当前是post请求)判断post在不在http_method_names列表中
        if request.method.lower() in self.http_method_names:
            # 如果在 从MyView中找到与post对应的功能方法并获取其数据与方法
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
            # 然后返回出去
        return handler(request, *args, **kwargs)

模板层

模板语法传值

# 方式1 指明道姓传参,减少资源消耗。
return render(request, 'modal.html', {'name':name})
# 方式2 关键字locals(),将整个局部名称空间中的名字全部传入。
 return render(request,'modal.html',locals())

模板语法传值范围

  • 基本数据类型

    可以直接传递使用

  • 函数

    函数名的传递会自动加括号执行并返回值展示到页面上,

    函数如果又参数则不会执行也不会展示,模板语法不支持有参函数

  • 类和对象

    类名的传递会自动加括号产生对象并展示到页面上

    对象传递则直接使用即可

模板语法会判断每一个名字是否可调用,如果可以,则直接调用

django的模板语法在操作容器类型的时候只允许使用句点符

模板语法过滤器

# 类似于python中的内置函数。
1. length,统计长度
	<p>统计长度:{{ 数据|length }}</p>	
2. add,加法运算还可以将字符串相加进行拼接
	<p>加法运算:{{ 整型|add:123 }}、加法运算:{{ 字符串|add:'heiheihei' }}</p>
3. date,日期转换
	<p>日期转换:{{ 时间|date:'Y-m-d H:i:s' }}</p>
4. filesizeformat,统计文件大小,自动做单位换算处理
	<p>文件大小:{{ file_size|filesizeformat }}</p>
5. slice,数据切片,超出范围取全部
	<p>数据切片:{{ l|slice:'0:10' }}</p>
6. truncatechars,字符截取,最后三个点也算在其中
	<p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p>
7. truncatewords,单词截取,以空格为标准
	p>单词截取(空格):{{ s1|truncatewords:6 }}</p>
8. p>语法转义:{{ script_tag|safe }}</p>
    <p>语法转义:{{ script_tag1|safe }}</p>
        from django.utils.safestring import mark_safe
        script_tag1 = '<script>alert(666)</script>'
        res = mark_safe(script_tag1)
        ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
            '''django模板语法中的符号就两个 一个{{}} 一个{%%}
        需要使用数据的时候 {{}}
        需要使用方法的时候 {%%}
    '''  

模板语法标签

# 类似于python的流程控制
	# if 判断
	{% if 条件 %}	条件一般是模板语法传过来的数据,直接写名字使用即可
    	条件成立执行的代码
    {% elif 条件1 %}
    	条件1成立执行的代码
    {% else %}
    	条件都不成立执行的代码
    {% endif %}
    
    # for循环
    {% for i in xxx %}
    	{{i}}
    	{{i}}
    {% endif %}
    
    # for循环结合if判断一起使用
    {% for i in s %}
        {% if forloop.first %}
            <p>这是第一次哟~</p>
        {% elif forloop.last %}
            <p>这是最后一次!</p>
        {% else %}
            <p>{{ i }}</p>
        {% endif %}
  		# 判断是否为空
        {% empty %}
        	  <p>你给我的是个空 怎么for循环呢</p>
    {% endfor %}

自定义标签函数、过滤器、inclusion_tag

想要自定义,需要先在应用下创建一个名为templatetags文件夹

在该文件夹创建任意名称的py文件,在文件下编写自定义相关的代码

from django.template import Library
register = Library()

自定义过滤器
# 在自定义过滤器上添加 @register.filter(name='myfilter')

@register.filter(name='myfilter')
    def my_add(a, b):
        return a + b
# 自定义过滤器只能添加俩个形参
自定义标签函数
# 在自定义标签函数上添加 @register.simple_tag(name='mt')

@register.simple_tag(name='mt')
    def func(a, b, c, d):
        return a + b + c + d

# 函数的形参不做限制
自定义inclusion_tag
# 在自定义inclusion_tag上添加 @register.inclusion_tag(filename='it.html')

    @register.inclusion_tag(filename='it.html')
    def index(n):
        html = []
        for i in range(n):
            html.append('第%s页'%i)
        return locals()



模板的继承

	{% extends 'html文件名' %}
   	{% block 名字 %}
    	模板内容
	{% endblock %}
    
    
   	{% block 名字 %}
    	子板内容
    {% endblock %}
 	一般情况下母板中至少应该有三个区域使得扩展性更高!!!
    	css content js
    {% block css %}
	{% endblock %}
    {% block content %}
	{% endblock %}
    {% block js %}
	{% endblock %}
   	'''子板中还可以使用母板的内容  {{ block.super }} '''
  
7.模板的导入(了解)
	将html页面的某个部分当做模块的形式导入使用
    	{% include 'menu.html' %}
posted @ 2022-09-05 08:14  瓮小辉  阅读(29)  评论(0)    收藏  举报