前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django之视图层与模板层

Django之视图层与模板层

作者头像
GH
发布2019-12-16 15:45:16
9.1K0
发布2019-12-16 15:45:16
举报

一、视图层

视图函数(类)简称为视图,就是一个普通的函数(类),它的功能是接收web请求,并返回web响应.

研究视图函数需要熟练掌握请求对象(HttpRequest)和相应对象(HttpResponse)

1.1请求对象(HttpRequest)

1.1.1HttpRequest请求对象常用属性

代码语言:javascript
复制
#part1
一.HttpRequest.method
获取请求使用的方法(值为纯大写的字符串格式)。例如:"GET"、"POST"
 应该通过该属性的值来判断请求方法
二.HttpRequest.GET
值为一个类似于字典的QueryDict对象,封装了GET请求的所有参数,可通过HttpRequest.GET.get('键')获
取相对应的值

三.HttpRequest.POST
 值为一个类似于字典的QueryDict对象,封装了POST请求所包含的表单数据,可通过
HttpRequest.POST.get('键')获取相对应的值

 针对表单中checkbox类型的input标签、select标签提交的数据,键对应的值为多个,需要用:
HttpRequest.POST.getlist("hobbies")获取存有多个值的列表,同理也有HttpRequest.GET.getlist("键")
#part2
一.HttpRequest.body
 当浏览器基于http协议的POST方法提交数据时,数据会被放到请求体中发送给django,django会将接收到的请求
体数据存放于HttpRequest.body属性中,因为该属性的值为Bytes类型,所以通常情况下直接处理Bytes、并从中提
取有用数据的操作是复杂而繁琐的,好在django会对它做进一步的处理与封装以便我们更为方便地提取数据,比如
 对于form表单来说,提交数据的常用方法为GET与POST
 1:如果表单属性method='GET',那么在提交表单时,表单内数据不会存放于请求体中,而是会将表单数据按照
k1=v1&k2=v2&k3=v3的格式放到url中,然后发送给django,django会将这些数据封装到request.GET中,注意此
时的request.body为空、无用
 2:如果表单属性method='POST',那么在提交表单时,表单内的所有数据都会存放于请求体中,在发送给django
后会封装到request.body里,此时django为了方便我们提取数据,会request.body的数据进行进一步的处理,具
体如何处理呢,需要从form表单提交数据的编码格式说起:
 form表单对提交的表单数据有两种常用的编码格式,可以通过属性enctype进行设置,如下
 编码格式1(默认的编码格式):enctype="application/x-www-form-urlencoded"
 编码格式2(使用form表单上传文件时只能用该编码):enctype="multipart/form-data"
 如果form表单提交数据是按照编码格式1,那么request.body中数据的格式类似于GET方法的数据格式,如
k1=v1&k2=v2,此时django会将request.body中的数据提取出来封装到request.POST中方便我们提取
 如果form表单提交数据是按照编码格式2,那么request.body中数据的格式为b'------
WebKitFormBoundaryKtcwuksQltpNprep\r\nContent-Disposition: form-data;......',,此时django
会将request.body中的数据提取出来封装到request.POST中,将上传的文件数据专门提取出来封装到
request.FILES属性中
 强调:毫无疑问,编码格式2的数据量要大于编码格式1,如果无需上传文件,还是推荐使用更为精简的编码格式1

 我们除了可以采用form表单向django提交数据外,还可以采用ajax技术,ajax可以提交的数据格式有:1、编码
格式1 2、编码格式2 3、json,当ajax采用POST方法提交前两种格式的数据时,django的处理方案同上,但是当
ajax采用POST方法提交json格式的数据时,django会将接收到的数据存放于HttpRequest.body,此时需要我们自
己对HttpRequest.body属性值做反序列化操作,
具体的,我们在讲解ajax时再做具体介绍

二.HttpRequest.FILES
 如果使用form表单POST上传文件的话,文件数据将包含在HttpRequest.FILES属性中。
该属性值为一个类似于字典的对象,可以包含多组key:value(对应多个上传的文件),其中每个key为<input
type="file" name="" /> 中name属性的值,而value则为对应的文件数据
强调:HttpRequest.FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/formdata" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。

#part3
一.HttpRequest.path
获取url地址的路径部分,只包含路径部分
二.HttpRequest.get_full_path()
获取url地址的完整path,既包含路径又包含参数部分
如果请求地址是http://127.0.0.1:8001/order/?name=ylpb&age=10#_label3,
HttpRequest.path的值为"/order/"
HttpRequest.get_full_path()的值为"/order/?name=ylpb&age=10"

#part4
一.HttpRequest.META
 值为包含了HTTP协议的请求头数据的Python字典,字典中的key及期对应值的解释如下
 CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
 CONTENT_TYPE —— 请求的正文的MIME类型。
 HTTP_ACCEPT —— 响应可接收的Content-Type。
 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
 HTTP_HOST —— 客服端发送数据的目标主机与端口
 HTTP_REFERER —— Referring 页面。
 HTTP_USER_AGENT —— 客户端使用的软件版本信息
 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
 REMOTE_ADDR —— 客户端的IP地址。
 REMOTE_HOST —— 客户端的主机名。
 REMOTE_USER —— 服务器认证后的用户。
 REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
 SERVER_NAME —— 服务器的主机名。
 SERVER_PORT —— 服务器的端口(是一个字符串)。
 从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,HTTP协议的请求头数据转换为 META 的键
时,
 都会
 1、将所有字母大写
 2、将单词的连接符替换为下划线
 3、加上前缀HTTP_。
 所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

注意:下述常用属性暂且了解即可,待我们讲到专门的知识点时再专门详细讲解
二.HttpRequest.COOKIES
一个标准的Python 字典,包含所有的cookie。键和值都为字符串。
三.HttpRequest.session
 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
11.HttpRequest.user(用户认证组件下使用)
一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
2.HttpRequest.is_ajax()
如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部
是否是字符串'XMLHttpRequest'。
大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),

你必须手工设置这个值来让 is_ajax() 可以工作。
如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache
middleware,
 你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存

1.2响应对象(HttpResponse)

响应可以是一张HTML网页、一个404错误,一张图片,一个XML文档、重定向到其他视图等。特点:无论视图本身包含什么逻辑都必须要返回响应,另外视图函数放在views.py是约定俗成的,并不是必须要放在这里。

1.2.1HttpResponse()

括号内直接跟一个具体的字符串作为响应体。

1.2.2render()

代码语言:javascript
复制
render(request,template_name[,context])
参数:
1. request:用于生成响应的请求对象,固定必须传入的第一个参数
2.template_name:要使用模板的完整名称,必须传入,render默认回去templates目录下查找模板文件
3.context:可选参数,可以传入一个字典用来替代模板文件中的变量
render的功能可总结为:根据给定的字典渲染模板,并返回一个渲染后的HttpResponse对象。

1.2.3redirect()

重定向为指定的地址。

代码语言:javascript
复制
def home(request):
    #return redirect('/login')如果重定向为本站的其他页面则可直接写本站其他页面的后缀
    return redirect('https://www.cnblogs.com/ghylpb/')#如果重定向为其他网站则直接写其它网站的网址即可

1.3JsonResponse

JsonResponse内部使用json模块对传入的数据类型型进行序列化,它的默认数据类型只有字典,当将safe参数置为False时,可以序列化其它数据类型,它继承了HttpResponse类,可以对请求做出响应。

用json实现JsonResponse的功能:

代码语言:javascript
复制
def index(request):
    user_dic = {'name':'小张','password':'123'}
    # json内部会使用ASCII码对所有的数据进行转码,所以如果转码之后我们将无法获得中文信息处理方法如下,将json的ensure_ascii参数置为False就可以
    json_str = json.dumps(user_dic,ensure_ascii=False)
    return HttpResponse(json_str)

JsonResponse:

代码语言:javascript
复制
  def index(request):
    user_dic = {'name':'小张','password':'123'}
    return JsonResponse(user_dic,json_dumps_params={'ensure_ascii':False})

更改JsonResponse序列化的数据类型:

代码语言:javascript
复制
  def index(request):
    l = [1,2,3,4,5,6,7,]
    # JsonResponse默认只序列化字典 如果你想序列化其他数据类型(json模块能够序列化的) 你需要加一个safe参数
    return JsonResponse(l,safe=False)

1.4FBV与CBV

Django的视图层由两种形式构成:FBV基于函数的视图(Function base view)和CBV基于类的视图(Class base view)

1.4.1FBV

我们前面使用的视图函数就是FBV。

路由的书写方法:url(r'^name/',views.name)

1.4.2CBV

CBV引入面向对象的思想对数据进行更高程度的封装。如下例所示:

代码语言:javascript
复制
class MyLogin(View):
    def get(self,request):
        print('我是MyLogin里面的get方法')
        return render(request,'login.html')

    def post(self,request):
        print('我是MyLogin里面的post方法')
        return HttpResponse('post')

路由的书写方法:url(r'^login/',views.MyLogin.as_view())

从路由的书写可以看出这里执行的是类的方法,而方法的本质还是函数所以CBV在路由匹配上的本质还是FBV。

1.5CBV源码

为什么CBV能够根据不同的请求方式自动执行不同的代码呢?下面我们一起看一下CBV的源码

代码语言:javascript
复制
class View(object):
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)   
    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):#闭包函数
            self = cls(**initkwargs)#cls是我们自己定义的类Mylogin,self是我们自定义的类实例化的对象。
            if hasattr(self, 'get') and not hasattr(self, 'head'):#这里的get是干啥使的?
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # 对象查找属性和方法的顺序:先自己再自己的类再父类
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        #判断当前的请求方式在不在默认的八个方法内,以get请求为例
        if request.method.lower() in self.http_method_names:
            #这里利用反射去我们自己定义的类实例化的对象中查找get属性或方法getattr(obj,'get')
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)#加括号调用该方法

给CBV内部的方法加装饰器:

方法1:使用内置模块

代码语言:javascript
复制
from django.utils.decorators import method_decorator
#先导入 method_decorator
#可以指定给哪个方法装(outter是我们定义的装饰器名称,这里略去装饰器的定义代码)
# @method_decorator(outter,name='post')
# @method_decorator(outter,name='dispatch')
class MyLogin(View):
    @method_decorator(outter)
    def dispatch(self, request, *args, **kwargs):  # 如果你想在视图函数执行之前做一些操作,你可以在你的CBV中定义dispatch方法来拦截
        return super().dispatch(request,*args,**kwargs)
  
    # @method_decorator(outter)  # 1.推荐写法
    def get(self,request):
        print('我是MyLogin里面的get方法')
        return render(request,'login.html')
    def post(self,request):
        print('我是MyLogin里面的post方法')
        time.sleep(1)
        return HttpResponse('post')

方法2:把类的方法当成普通函数,直接在对应的方法上添加。

代码语言:javascript
复制
class MyLogin(View):
    @outter
    def get(self,request):
        print('我是MyLogin里面的get方法')
        return render(request,'login.html')
    @outter
    def post(self,request):
        print('我是MyLogin里面的post方法')
        time.sleep(1)
        return HttpResponse('post')

二、模板层

2.1模板语法

2.1.1模板语法的取值

模板语法的取值方式只有一种:统一采用句点符取值(点的方式取值)

如:

代码语言:javascript
复制
#python代码
user_obj = {'name':'zgh','pwd':123,'hoppy':['book','music','movie']}
#模板语法取值
{{ user_obj.hobby.0}}#book
#句点符取值,如果从字典取值则点key值,如果从列表取值则点索引号

模板语法有两种书写格式:

代码语言:javascript
复制
{{}}#变量相关
{% %}#逻辑相关

2.1.2模板传值

模板支持的数据类型

模板支持的数据类型:整型、浮点型、字符串、字典、列表、元组、集合、bool,也就是支持python基本的数据类型全都支持。

模板传值

1.传函数名:{{ 函数名 }}

给HTML传函数名的时候,模板语法会自动加括号调用该函数,并将函数的返回值当做页面展示的依据,注意模板语法不支持函数传参,也就是说只能给页面传无参函数。

2.传类名:{{ 类名 }}

给HTML传类名的时候会自动加括号实例化产生对象,在HTML页面可以进行如下对对象的使用。

代码语言:javascript
复制
<p>传对象:{{ obj }}</p>
<p>{{ obj.get_self }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func }}</p>

模板传值特点:只要能够加括号调用的类函数等传到HTML页面都会自动加上括号调用。

2.2过滤器

过滤器类似于python的内置函数,用来把视图函数传入的变量值加以修饰以后再显示

语法结构:{{ 变量名 | 过滤器名 : 传给过滤器的参数 }}

注意:过滤器最多只能有两个参数

常用的内置过滤器:

代码语言:javascript
复制
#1、default
#作用:如果一个变量值是False或者为空,使用default后指定的默认值,否则,使用变量本身的值,如果
value=’‘则输出“nothing”
{{ value|default:"nothing" }}
#2、length
#作用:返回值的长度。它对字符串、列表、字典等容器类型都起作用,如果value是 ['a', 'b', 'c', 'd'],那
么输出是4
{{ value|length }}
#3、filesizeformat
#作用:将值的格式化为一个"人类可读的"文件尺寸(如13KB、4.1 MB、102bytes等等),如果 value 是12312312321,输出将会是 11.5 GB
{{ value|filesizeformat }}
#4、date
#作用:将日期按照指定的格式输出,如果value=datetime.datetime.now(),按照格式Y-m-d则输出2019-02-02
{{ value|date:"Y-m-d" }}
#5、slice
#作用:对输出的字符串进行切片操作,顾头不顾尾,如果value=“ylpb“,则输出"yl"
{{ value|slice:"0:2" }}
#6、truncatechars
#作用:如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾,
如果value="hello world abc def ",则输出"hello...",注意8个字符也包含末尾的3个点
{{ value|truncatechars:8 }}
#7、truncatewords
#作用:同truncatechars,但truncatewords是按照单词截断,注意末尾的3个点不算作单词,如果value="
hello world abc def" ,则输出"hello world ..."
{{ value|truncatewords:2 }}
#8、safe
#作用:出于安全考虑,Django的模板会对HTML标签、JS等语法标签进行自动转义,例如value="
<script>alert(123)</script>",模板变量{{ value }}会被渲染成
&lt;script&gt;alert(123)&lt;/script&gt;交给浏览器后会被解析成普通字符”<script>alert(123)
</script>“,失去了js代码的语法意义,但如果我们就想让模板变量{{ value }}被渲染的结果又语法意义,那么就
用到了过滤器safe,比如value='<a href="https://www.baidu.com">点我啊</a>',在被safe过滤器处理后
就成为了真正的超链接,不加safe过滤器则会当做普通字符显示’<a href="https://www.baidu.com">点我啊
</a>‘
{{ value|safe }}

最为常用的过滤器有:统计长度、自动转文件大小格式、展示带有标签的文本。

2.3标签

标签(逻辑相关)是为了在模板中完成一些特殊的功能,语法为{% %},下面介绍几个常用的标签。

2.3.1for标签

代码语言:javascript
复制
'''语法:{% for user in 容器类数据类型 %}
             for循环体
         {% endfor %}'''
#如下面代码循环循环出列表中的每一个元素并展示元素的属性
{% for user in user_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.auth_name }}</td>
<td>{{ user.detail }}</td>
<td>
<a href="{% url 'app01_edit_author'%}?edit_id={{ user.id }} " class="btn btn-primary btn-xs">编辑</a>
<a href="{% url 'app01_delete_author' %}?delete_id={{ user.id }}" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{% endfor %}

2.3.2if标签

代码语言:javascript
复制
{% if 条件1 %}
    执行内容1
{% elif 条件2%}
    执行内容2
{% else %}
    执行内容3
{% endif %}

#if 标签长和for标签联合使用如:
{% for foo in l %}#l是一个列表
{% if forloop.first %}
<p>first</p>
{% elif forloop.last %}
<p>last</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>当for循环的对象是空的时候会走</p>
{% endfor %}

2.3.3with标签

with标签用来给一个复杂的变量名起别名,如果变量的值来自于数据库,在起别名后只需要使用别名即可,无需每次都向数据库发送请求重新获取变量的值,这里需要说明的是别名只能在with标签内部使用,如果在外部还是要用原名的。

代码语言:javascript
复制
{% with 原变量名 as 别名 %}
<p>{{ 别名 }}</p>
{% endwith %}

2.3.4csrf_token标签

代码语言:javascript
复制
# 当用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请求,否则拒绝,以此来确定客户端的身份

2.4自定义过滤器和标签

当内置的过滤器或标签无法满足我们的需求时,我们可以自定义标签和过滤器。

2.4.1自定义前的准备

django支持用户自定义过滤器和标签但前提必须要先执行以下三步:

1.在应用名下新建一个名为templatetags(必须是这个名字)的文件夹

2.在该文件夹内新建一个任意名称的py文件

3.在该py文件中先写下面两行代码(必须)

代码语言:javascript
复制
from django.template import Library

register = Library()

完成上面的步骤就可以利用register来自定义过滤器和标签了。

2.4.2自定义过滤器

代码语言:javascript
复制
@register.filter(name='test')
def index(a,b):
    return a + b
#name为给过滤器起的名字,可以不写

自定义的过滤器最多只能有两个参数。

2.4.3自定义标签

代码语言:javascript
复制
# 自定义标签,可以接受任意多个参数
@register.simple_tag(name='mytag')
def mytag(a,b,c,d):
    return '%s?%s?%s?%s'%(a,b,c,d)

2.4.4自定义inclusion_tag

inclusion_tag是一个函数,能够接受外界传入的参数,然后传递给一个HTML页面,页面获取数据,渲染完成后将渲染好的页面放到调用inclusion_tag的地方。

代码语言:javascript
复制
@register.inclusion_tag('mytag.html',name='xxx')
def index666(n):
    l = []
    for i in range(n):
        l.append('第%s项'%i)
        return locals()  # 将l直接传递给mytag.html页面
    # 给html页面传值的两种方式
    # 第一种,指名道姓当需要传递的变量名特别多的情况下 有点麻烦
    # return render(request,'test.html',{'n':n})
    # 第二种,使用locals()会将当前所在名称空间中所有的名字全部传递给html页面

2.5模板的继承和导入

在实际开发中,模板文件彼此之间可能会有大量的冗余代码,为此Django提供了专门的语法来解决这一问题,即模板的继承和导入。

2.5.1继承

如果你想使用某个已有的页面,首先你需要先在你想使用的页面上划定区域,在继承这个区域之后,你就可以使用划定的这个区域。

block标签

划定区域使用block标签,只需将你想要修改的区域放在block内部即可:

代码语言:javascript
复制
{% block content %}
划定的区域
{% endblock %}
extends标签

在新的页面通过extends标签继承前面划定的区域:

代码语言:javascript
复制
{% extends 'XXX.html' %} {#XXX.html是之前的页面#}
                  
{% block content %}
修改模板中content区域内容
{% endblock %}

建议一个模板页面至少划分为三个区域:css区、html代码区、JS区,这样方便每一个页面都有自己独立的css和JS代码。

2.5.2模板的导入

include标签

作用:在一个模板文件中引入另一个模板文件的内容,与继承不同的是include引用了目标模板的整个文件。

代码语言:javascript
复制
{% include 'xxx.html' %}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、视图层
    • 1.1请求对象(HttpRequest)
      • 1.1.1HttpRequest请求对象常用属性
    • 1.2响应对象(HttpResponse)
      • 1.2.1HttpResponse()
      • 1.2.2render()
      • 1.2.3redirect()
    • 1.3JsonResponse
      • 1.4FBV与CBV
        • 1.4.1FBV
        • 1.4.2CBV
      • 1.5CBV源码
      • 二、模板层
        • 2.1模板语法
          • 2.1.1模板语法的取值
          • 2.1.2模板传值
        • 2.2过滤器
          • 2.3标签
            • 2.3.1for标签
            • 2.3.2if标签
            • 2.3.3with标签
            • 2.3.4csrf_token标签
          • 2.4自定义过滤器和标签
            • 2.4.1自定义前的准备
            • 2.4.2自定义过滤器
            • 2.4.3自定义标签
            • 2.4.4自定义inclusion_tag
          • 2.5模板的继承和导入
            • 2.5.1继承
            • 2.5.2模板的导入
        相关产品与服务
        文件存储
        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档