zoukankan      html  css  js  c++  java
  • Django基础之视图层(views.py)和模板层

    Django基础之视图层(views.py)和模板层

    视图层

    JsonResponse对象

    首先提一下,之前讲到过小白必会三板斧(重要三对象):HttpResponse、render、redirect,要注意的是django视图函数必须要返回一个HttpResponse对象

    render内部工作原理

    from django.template import Template,Context  # 用到两个模块
    def index(request):
    	res = Template("<h1> {{ user }} </h1>")
    	con = Context({'user':{'username':'jason','pwd':'123'}})
    	ret = res.render(con)
    	print(ret)
    	return HttpResponse(ret)
    

    用来返回json格式数据的为什么要给前端返回json格式字符串?

    因为涉及到一个前后端分离的概念。

    前后端分离就是基于json格式传输数据,后端就专门写接口,前端调用你这个接口,就能够拿到一个json格式的字符串,然后前端利用序列化反序列化转换成前端对应的数据类型。

    json常用数据类型
    数值类型
    字符类型
    数组 []
    自定义对象 {}
    undefined与null
    布尔值 true false
    symbol

    前端的序列化 : JSON.stringify() >>>>>>>> json.dumps()

    前端的反序列化:JSON.parse() >>>>>>>>> json.loads()

    eg:

    from django.http import JsonResponse
    def index(request):
    	data = {'name':'jason好帅哦 我好喜欢','password':123}
    	l = [1,2,3,4,5,6,7,8]
    	# 后端朝前端返回json格式的字符串方式一
    	# res = json.dumps(data,ensure_ascii=False) # 把参数ensure_ascii=False就不会把中文转成json格式
    	# return HttpResponse(res)
    	# 方式二
    	# return JsonResponse(data,json_dumps_params={'ensure_ascii':False})  # 让参数json_dumps_params={'ensure_ascii':False}作用也是不把中文转成json格式
    	return JsonResponse(l,safe=False)  # JsonResponse默认只支持序列化字典,如果你想序列化其他类型(json能够支持的类型),需要将safe参数由默认的True改为False。
    

    form表单上传文件

    注意事项:

    1. enctype属性需要由默认的urlencoded变成formdata

    2. method属性需要由默认的get变成post

      (目前还需要考虑的是 提交post请求需要将配置文件中的csrf中间件注释)

    3. 如果form表单上传文件 后端需要在request.FILES获取文件数据 而不再是POST里面

    eg:

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from homework import views
    
    urlpatterns = [
    	url(r'^file/$', views.file)
    ]
    

    views.py

    from django.shortcuts import render, HttpResponse, redirect, reverse
    
    def file(request):
        if request.method == 'POST':
            print(request.FILES)
            # 获取文件对象
            file_obj = request.FILES.get('myfile')
            print(file_obj.name)
            with open(file_obj.name, 'wb') as f:
                # for line in file_obj:   # file_obj可以直接看成文件句柄f
                #     f.write(line)
                # 也可以用下面一种方法
                for chunk in file_obj.chunks():
                    f.write(chunk)
        return render(request, 'file.html')
    

    在templates目录下新建file.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        {% load static %}
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
        <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    </head>
    <body>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="myfile">
        <input type="submit" value="提交">
    </form>
    
    </body>
    </html>
    

    FBV与CBV 即CBV源码分析

    FBV(Function Based View):基于函数的视图

    CBV(Class Based View):基于类的视图

    CBV和FBV在路由匹配上,规则都是一样的,都是路由后面跟的函数的内存地址

    在类中写了两个方法 一个叫get一个叫post
    为什么前端get请求来就会触发get方法
    post请求来就会触发post方法 如何实现的???

    这就讲一下CBV源码的实现思路

    1、CBV路由层

    url(r'^reg/',views.MyReg.as_view())  # 在这必须调用自己写的MyReg类中的as_view方法
        
    # as_view的源码
    @classonlymethod
    def as_view(cls, **initkwargs):
    	def view(request, *args, **kwargs):
    		self = cls(**initkwargs)  # cls就是我们自己的写的MyReg类
             if hasattr(self, 'get') and not hasattr(self, 'head'):
             	self.head = self.get
             self.request = request
             self.args = args
             self.kwargs = kwargs
             # 上面的一通操作 就是给我们自己写的类的对象赋值
             return self.dispatch(request, *args, **kwargs)
             # 对象在查找属性或方法的时候 顺序是什么?  先从自己找 再从产生对象的类中找  再去类的父类中找...
     		"""也就意味着你在看源码的时候 你一定要牢记上面的话"""
    	return view
    

    2、视图层views.py中写上继承view的类

    from django.views import View
    
    class MyReg(View):
        def get(self,request):
        	return render(request,'reg.html')
    
        def post(self,request):
        	return HttpResponse("我是MyReg类中post方法")
    
    

    3、在前端发送请求的时候就会进到CBV源码的dispatch方法判断请求方式在不在默认的八个请求方式中。

    """CBV源码最精髓的部分"""
    def dispatch(self, request, *args, **kwargs):
    	if request.method.lower() in self.http_method_names:  # 判断当前请求方式在不在默认的八个请求方式中
    		handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    		# handler = getattr(自己写的类产生的对象,'小写的请求方法(getpost)','获取不到对应的方法就报错')
    		# handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址
    	else:
    		handler = self.http_method_not_allowed
    	return handler(request, *args, **kwargs)  # 再调用获取到的方法
            
    

    django settings源码分析及实际应用

    django的配置文件有两个
    一个是暴露给用户可以自定义配置的
    一个是默认的全局配置文件
    用户指定了就用用户的
    用户没有指定就用默认的

    from django.conf import settings
          
    settings = LazySettings()
    
    class LazySettings(LazyObject):
    	def _setup(self, name=None):
    		# os.environ你可以把它看成是一个全局的大字典
    		settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 从大字典中取值
    		# settings_module = 'day59.settings'
    		self._wrapped = Settings(settings_module) # Settings('day59.settings')
    class Settings(object):
    	def __init__(self, settings_module):  # settings_module = 'day59.settings'
    		for setting in dir(global_settings):  # 循环获取global_settings文件中所有的名字
    			if setting.isupper():  # 在判断名字是否是大写
                 # 如果是大写 利用反射 获取到大写的名字所对应的值  不停地添加到对象中
                 	setattr(self, setting, getattr(global_settings, setting))
                    # store the settings module in case someone later cares
                    self.SETTINGS_MODULE = settings_module
                    mod = importlib.import_module(self.SETTINGS_MODULE)  # 'day59.settings'
                    # from day59 import settings
                    # mod 指代的就是暴露给用户的配置文件模块名
                   
                    for setting in dir(mod):  # 循环获取暴露给用户配置文件中所有的名字
                        if setting.isupper():  # 判断是否是大写
                            setting_value = getattr(mod, setting)  # 如果是大写 获取大写的变量名所对应的值
                            setattr(self, setting, setting_value)  # 不停的给对象设置值
            
        
    

    模板层

    模板传值

    传函数名的时候,会自动加括号调用函数,将函数的返回值展示在html页面上,django模板语法不支持函数传参。

    django模板语法在获取容器类型内部元素的值得时候,统一只采用句点符(.)

    句点符既可以引用容器类型的元素,也可以引用对象的方法,如下
    test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <!--调用字符串对象的upper方法,注意不要加括号-->
    <p>{{ msg.upper }}</p>
    
    <!--取字典中k1对应的值-->
    <p>{{ dic.k1 }}</p>
    
    <!--取对象的name属性-->
    <p>{{ obj.name }}</p>
    
    <!--取列表的第2个元素,然后变成大写-->
    <p>{{ li.1.upper }}</p>
    
    <!--取列表的第3个元素,并取该元素的age属性-->
    <p>{{ li.2.age }}</p>
    
    
    </body>
    </html>
    

    例如给html页面传了一个列表l,那在前端取值就用<p>{{ l.1 }}</p>,就用列表.索引取值。

    过滤器( | )

    1、优点类似于小的方法,特点:会将|左边的当做过滤器的第一个参数,将
    右边的当做过滤器第二个参数。

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

    {{ 变量名|过滤器名:传给过滤器的参数 }}
    

    常用内置过滤器

    # 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=“egon“,则输出"eg"
    {{ value|slice:"0:2" }} 
    
    #6、truncatechars
    #作用:如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾,如果value=”hello world egon 嘎嘎“,则输出"hello...",注意8个字符也包含末尾的3个点
    {{ value|truncatechars:8 }}
    
    #7、truncatewords
    #作用:同truncatechars,但truncatewords是按照单词截断,注意末尾的3个点不算作单词,如果value=”hello world egon 嘎嘎“,则输出"hello world ..."
    {{ value|truncatewords:2 }}
    
    #8、safe
    #作用:出于安全考虑,Django的模板会对HTML标签、JS等语法标签进行自动转义,例如value="<script>alert(123)</script>",模板变量{{ value }}会被渲染成<script>alert(123)</script>交给浏览器后会被解析成普通字符”<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 }}
    内置过滤器safe用来前后端取消转义(前端代码并不一定非要在前端写,也可以在后端写好,传递给前端页面)
    
    前端取消转义:|safe
    
    后端取消转义:要先导一个模块:
    from django.utils.safestring import mark_safe
    sss = "<a href='www.baidu.com'>渡我不渡她</a>"
    res = mark_safe(sss)
    # 再把这个res传到前端
    <p>{{ res }}</p> # 前端就能识别a标签了
    
    # 9、add
    给value加上一个add后面的数值
    eg:给前端传个n=123,`{{ n|add:100 }}`这个过滤器结果就是n+100,在页面上显示的结果就是223.
    

    其他过滤器(了解)

    过滤器 描述 示例
    upper 以大写方式输出 {{ user.name | upper }}
    add 给value加上一个数值 {{ user.age | add:”5” }}
    addslashes 单引号加上转义号
    capfirst 第一个字母大写 {{ ‘good’| capfirst }} 返回”Good”
    center 输出指定长度的字符串,把变量居中 {{ “abcd”| center:”50” }}
    cut 删除指定字符串 {{ “You are not a Englishman” | cut:”not” }}
    date 格式化日期
    default 如果值不存在,则使用默认值代替 {{ value | default:”(N/A)” }}
    default_if_none 如果值为None, 则使用默认值代替
    dictsort 按某字段排序,变量必须是一个dictionary {% for moment in moments | dictsort:”id” %}
    dictsortreversed 按某字段倒序排序,变量必须是dictionary
    divisibleby 判断是否可以被数字整除 `{{ 224 | divisibleby:2 }} 返回 True`
    escape 按HTML转义,比如将”<”转换为”&lt”
    filesizeformat 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 `{{ 1024 | filesizeformat }} 返回 1.0KB`
    first 返回列表的第1个元素,变量必须是一个列表
    floatformat 转换为指定精度的小数,默认保留1位小数 {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入
    get_digit 从个位数开始截取指定位置的数字 {{ 123456 | get_digit:’1’}}
    join 用指定分隔符连接列表 {{ [‘abc’,’45’] | join:’*’ }} 返回 abc*45
    length 返回列表中元素的个数或字符串长度
    length_is 检查列表,字符串长度是否符合指定的值 {{ ‘hello’| length_is:’3’ }}
    linebreaks 用或
    标签包裹变量
    {{ “Hi David”|linebreaks }} 返回HiDavid
    linebreaksbr
    标签代替换行符
    linenumbers 为变量中的每一行加上行号
    ljust 输出指定长度的字符串,变量左对齐 {{‘ab’|ljust:5}}返回 ‘ab ’
    lower 字符串变小写
    make_list 将字符串转换为列表
    pluralize 根据数字确定是否输出英文复数符号
    random 返回列表的随机一项
    removetags 删除字符串中指定的HTML标记 {{value | removetags: “h1 h2”}}
    rjust 输出指定长度的字符串,变量右对齐
    slice 切片操作, 返回列表 {{[3,9,1] | slice:’:2’}} 返回 [3,9] `{{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’`
    slugify 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 `{{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23`
    stringformat 字符串格式化,语法同python
    time 返回日期的时间部分
    timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
    timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量
    title 每个单词首字母大写
    truncatewords 将字符串转换为省略表达方式 `{{ 'This is a pen' | truncatewords:2 }}返回``This is ...`
    truncatewords_html 同上,但保留其中的HTML标签 `{{ '

    This is a pen

    ' | truncatewords:2 }}返回``

    This is ...

    `
    urlencode 将字符串中的特殊字符转换为url兼容表达方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}}
    urlize 将变量字符串中的url由纯文本变为链接
    wordcount 返回变量字符串中的单词数
    yesno 将布尔变量转换为字符串yes, no 或maybe `{{ True | yesno }}{{ False | yesno }}{{ None | yesno }} ``返回 ``yes``no ``maybe`

    标签

    if判断,for循环、with标签、csrf_token标签等。

    if判断

    eg:

    <!--注意:{% if 条件 %}条件为真时if的子句才会生效,条件也可以是一个变量,if会对变量进行求值,在变量值为空、或者视图没有为其传值的情况下均为False-->
    
    {% if xo %}
    	<p>xo有值</p>
    {% else %}
    	<p>xo没有值</p>
    {% endif %}
    
    {% 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判断。
    

    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 %}
    
    {% for key in dic.keys %}
        <p>{{ key }}</p>
    {% endfor %}
    
    {% for val in dic.values %}
        <p>{{ 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 %}
    

    eg:

    urls.py

    from django.urls import url
    from app01 import views
    
    urlpatterns = [
        url(r'^test/',views.test)
    ]
    

    view.py

    def test(request):
        names=['egon','kevin']
        dic={'name':'egon','age':18,'sex':'male'}
    
        list1=[]
    
        return render(request,'test.html',locals())
    

    test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <hr>
    {% for name in names %}
        <p>{{ forloop.counter0 }} {{ name }}</p>
    {% endfor %}
    <!--
    输出结果为:
    0 egon
    1 kevin
    -->
    
    <hr>
    {% for name in names reversed %}
        <p>{{ forloop.revcounter0 }} {{ name }}</p>
    {% endfor %}
    <!--
    输出结果为:
    1 kevin
    0 egon
    -->
    
    <hr>
    {% for k,v in dic.items %}
        <p>{{ forloop.counter }} {{ k }} {{ v }}</p>
    {% endfor %}
    <!--
    输出结果为:
    1 name egon
    2 age 18
    3 sex male
    -->
    
    <hr>
    {% for item in list1 %}
        <p>{{ item }}</p>
        {% empty %}
            <p>sorry,no value here</p>
    {% endfor %}
    <!--
    输出结果为:
    sorry,no value here
    -->
    
    </body>
    </html>
    

    with标签

    # with标签用来为一个复杂的变量名起别名,如果变量的值来自于数据库,在起别名后只需要使用别名即可,无需每次都向数据库发送请求来重新获取变量的值
    {% with li.1.upper as v %}
        {{ v }}
    {% 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请求,否则拒绝,以此来确定客户端的身份
    

    自定义过滤器和标签

    步骤:

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

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

    3. 在该py文件内,固定先写两行代码:

      ​ from django.template import Library

      ​ register = Library()

    自定义过滤器

    后端my_tag.py

    from django.template import Library
    register = Library()
    
    @register.filter(name='myplus')
    def index(a, b):
    return a+b
    

    前端index.html

    {% load my_tag %}
    {{ 123|myplus:123 }}
    

    这样前端页面显示的结果就是246

    自定义标签

    my_tag.py

    from django.template import Library
    register = Library()
    
    @register.simple_tag(name='mysm')
    def login(a, b, c, d):
    return '%s/%s/%/%s'%(a, b, c, d)
    

    login.html

    {% load my_tag %}
    {% mysm 1 2 3 4 %}
    

    结果是1/2/3/4

    自定义过滤器和标签的区别

    #1、自定义过滤器只能传两个参数,而自定义标签却可以传多个参数
    
    #2、过滤器可以用于if判断,而标签不能
    {% if salary|my_multi_filter:12 > 200 %}
        <p>优秀</p>
    {% else %}
        <p>垃圾</p>
    {% endif %}
    

    模板的继承

    extends标签和block标签

    实现需要在要继承的模板中,通过block划定区域

    {% block 区域名字 %}
    
    {% endblock %}
    

    子模板中如何使用

    # include有的功能extends全都有,但是extends可以搭配一个block标签,用于在继承的基础上定制新的内容
    {% extends '想要继承的模板' %}
    
    {% block 区域名字 %}
    	<h1>登录页面</h1>
    {% endblock %}
    

    一个页面上block块越多,页面的扩展性越高,通常情况下,都应该有三片区域

    {% block content %}
    
    {% endblock %}
    
    {% block css %}
    
    {% endblock %}
    
    {% block js %}
    
    {% endblock %}
    
    

    eg:

    Django模版引擎中最复杂且最强大的部分就是模版继承了。我们以先创建一个基本的“骨架”模版,它包含我们站点中的全部元素,并且可以定义多处blocks ,例如我们创建base.html内容如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            {% block title %}自定义title名{% endblock %}
        </title>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            .header {
                height: 50px;
                 100%;
                background-color: #919191;
                margin-bottom: 20px;
            }
    
        </style>
    
    </head>
    <body>
    <div class="header"></div>
    
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <div class="list-group">
                    {% block sidebar %}
                        <a href="#" class="list-group-item active">服装城</a>
                        <a href="#" class="list-group-item">美妆馆</a>
                        <a href="#" class="list-group-item">超市</a>
                        <a href="#" class="list-group-item">全球购</a>
                        <a href="#" class="list-group-item">闪购</a>
                        <a href="#" class="list-group-item">团购</a>
                    {% endblock %}
    
                </div>
            </div>
    
            <div class="col-md-9">
                {% block content %}
                    base.html页面内容
                {% endblock %}
            </div>
        </div>
    
    </div>
    
    </body>
    </html>
    

    模板base.html 定义了一个可以用于两列排版页面的简单HTML骨架。我们新建子模板index.html的主要工作就是继承base.html然后填充/覆盖其内部的blocks。

    {% extends "base.html" %}
    
    <!--用新内容完全覆盖了父模板内容-->
    {% block title %}
        index页面
    {% endblock %}
    
    
    {% block sidebar %}
        <!--该变量会将父模板中sidebar中原来的内容继承过来,然后我们可以在此基础上新增,否则就是纯粹地覆盖-->
        {{ block.super }}
    
        <!--在继承父模板内容的基础上新增的标签-->
        <a href="#" class="list-group-item">拍卖</a>
        <a href="#" class="list-group-item">金融</a>
    {% endblock %}
    
    {% block content %}
        <!--用新内容完全覆盖了父模板内容-->
        <p>index页面内容</p>
    {% endblock %}
    

    我们通过django访问index.html看到内容如下(block标签的内容都完成了替换或更新)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            index页面
        </title>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            .header {
                height: 50px;
                 100%;
                background-color: #919191;
                margin-bottom: 20px;
            }
    
        </style>
    
    </head>
    <body>
    <div class="header"></div>
    
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <div class="list-group">
                    <!--该变量会将父模板中sidebar中原来的内容继承过来,然后我们可以在此基础上新增,否则就是纯粹地覆盖-->
                    <a href="#" class="list-group-item active">服装城</a>
                    <a href="#" class="list-group-item">美妆馆</a>
                    <a href="#" class="list-group-item">超市</a>
                    <a href="#" class="list-group-item">全球购</a>
                    <a href="#" class="list-group-item">闪购</a>
                    <a href="#" class="list-group-item">团购</a>
    
    
                    <!--在继承父模板内容的基础上新增的标签-->
                    <a href="#" class="list-group-item">拍卖</a>
                    <a href="#" class="list-group-item">金融</a>
                </div>
            </div>
    
            <div class="col-md-9">
                <!--用新内容完全覆盖了父模板内容-->
                <p>index页面内容</p>
            </div>
        </div>
    
    </div>
    
    </body>
    </html>
    

    总结与注意

    #1、标签extends必须放在首行,base.html中block越多可定制性越强
    
    #2、include仅仅只是完全引用其他模板文件,而extends却可以搭配block在引用的基础上进行扩写
    
    #3、子模板中变量{{ block.super }} 可以重用父类的内容,然后在父类基础上增加新内容,而不是完全覆盖
    
    #4、为了提升可读性,我们可以给标签{% endblock %} 起一个名字 。例如:
        {% block content %}
        ...
        {% endblock content %}  
    #5、在一个模版中不能出现重名的block标签。
    

    模板的导入

    当你写了一个特别好看的form表单,想在多个页面上都使用这个form表单,你就可以将你写的form表单当做模块的形式导入,导入过来之后,就可以直接展示。

    模板导入之include标签,作用:在一个模板文件中,引入/重用另外一个模板文件的内容

    语法:{% include '要导入的模板名称' %}

    eg:

    可以把广告栏写到专门的文件里advertise.html

    <div class="adv">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
            </div>
            <div class="panel-body">
                Panel content
            </div>
        </div>
        <div class="panel panel-danger">
            <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
            </div>
            <div class="panel-body">
                Panel content
            </div>
        </div>
        <div class="panel panel-warning">
            <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
            </div>
            <div class="panel-body">
                Panel content
            </div>
        </div>
    </div>
    

    然后在base.html文件中用include标签引入advertise.html文件的内容

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            .header {
                height: 50px;
                 100%;
                background-color: black;
            }
            
        </style>
    </head>
    <body>
    <div class="header"></div>
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <!--在base.html引入advertise.html文件的内容-->
                {% include "advertise.html" %}
            </div>
            <div class="col-md-9"></div>
        </div>
    </div>
    </body>
    </html>
    

  • 相关阅读:
    ASP字符串16进制互转
    LINQ Dictionary加速查询(TryGetValue)
    ASP中将UTF8格式的URL进行解码。函数
    C# 保护进程不被结束(源代码)防任务管理器结束进程
    用WebBrowser做web 打印时的权限不足。。。。
    .net 2.0 中 ‘注册为 allowDefinition='MachineToApplication' 的节是错误的’
    sql 2005 中分页
    BitComet web 插件和 flash get web 插件 对脚本的影响
    同时使用 C# and VB.NET 在 .net 2.0 中
    用触发器实现主从表关系(主表更改从表更改 )
  • 原文地址:https://www.cnblogs.com/zhuangyl23/p/11729515.html
Copyright © 2011-2022 走看看