zoukankan      html  css  js  c++  java
  • django源码剖析以及模板语法

    一、python 之禅

      用一行就带你体会python的美及简洁

      使用方法:在cmd中输入python然后回车,再输入import this 

     二、render 的原理

      render原理其实就是相当于是Template以及Context的结合体,接下来我们就简单的模拟下,那么在使用之前我们需要在views.py中导入这两个模块

      from django.template import Template,Context

    注意:前期我们在使用post 请求的时候记得一定要把settings总的MIDDLEWARE下的一个csrf.CsrfViewMiddleware给注释掉

    - 演示代码

    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    Views.py
    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    ]
    urls.py

    效果图:

     三、CBV(基于类的视图)的基本使用

      这里就得要介绍下两种名词,我们知道视图函数并不一定就是函数,也可以是类,所以就有下面的两种写法

      FBV: 基于函数的视图

      CBV:基于类的视图

    1、CBV的基本写法

      from django.views import View

      路由中写法:

      url(r'^login/', views.Mylogin.as_view())  # 注意:一定要在对应的视图函数后面.as_view()

    2、代码演示

    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    
        # CBV路由配置
        url(r'^login/', views.Mylogin.as_view())
        # 注意一定要在对应的视图函数后面.as_view()
    ]
    urls.py
    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    
    
    
    from django.views import View
    
    
    class Mylogin(View):
        def get(self, request):
    
            return render(request, 'login.html')
    
        def post(self, request):
    
            return HttpResponse('我是类里面的post方法')
    Views.py
    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    <form action="" method="post">
        <input type="submit">
    </form>
    </body>
    </html>
    login.html

    3、效果图

     

     四、CBV源码剖析

      通过刚刚的演示,我们可以看到我们朝login提交get请求会自动执行Mylogin里面的get方法,而提交post请求也会自动的执行Mylogin里面的post方法,那么为什么Mylogin可以针对不同的请求方式会自动执行相对应的方法,接下来我们就来研究下Django中的CBV源码剖析

    1、研究源码的突破口

      url(r'^login/', views.Mylogin.as_view())

      猜想:

        as_view要么是类里面定义的普通函数 @staticmethod

        要么是类里面定义的绑定给类的方法 @classmethod

      所以接下来我们就点进去as_view看下,结果看源码发现是@classmethod,可以确定是绑定给类的方法

    注意:看源码并一定要每一句都能够看懂 只看自己能够看懂的即可

    2、演示

     五、Django settings源码剖析

    1、用户可以看到的settings

      Django在配置中暴露给用户可以查看的settings源码其实不多,也就100多行,那其实这并不是Django真正的settings源码,其实Django真正的settings源码是另一个叫settings,我们可以在settings中去通过from  djjango.conf import global_settings ,settings前面是查看全局源码, 后面通过django.conf导入的settings是真正的配置文件。

    总结:这里有一个结论很重要,用户自己配置了就用用户的,用户没有配置的就用Django默认的,比如之前会默认给我们加一个斜杠/

    2、研究Django默认的settings源码的原理

    1、点击我们之前从django.conf导入的settings,发现这里有一个单例模式

     2、点击LazySettings

     3、去manage.py中

     4、继续研究LazySettings

     5、点击Settings这个类

     6、得出结论

    - importlib补充说明

    name = 'yafeng'
    # from conf import b
    # #
    # # print(b.name)
    
    import importlib    # 注意:importlib这个最小识别单位只能到py文件, 不然会报错
    
    # res = 'conf.b.name'  #ModuleNotFoundError: No module named 'conf.b.name'; 'conf.b' is not a package
    
    res = 'conf.b'
    md = importlib.import_module(res)
    
    # print(md)   #<module 'conf.b' from 'D:\python的pycharm\ab_imp\conf\b.py'>
    
    print(md.name)  # yafeng

    六、模板语法之传值取值

    1、给模板传值的两种方式

      (一)python基本数据类型全部支持传递给前端HTML文件

      1、后端给HTML传值的两种方式

      a:自己手动去传数据(指名道姓)

      return render(request, 'index.html', {'n':n, 'f': f, .....})

      b:locals()会自动将当前名称空间所有的变量名全部传递给html页面

      return render(request, 'index.html', locals())

      2、HTML页面上 如何获取后端传递过来的数据

      {{ 变量名 }}

      (二)函数也可以传递给前端HTML文件

       注意:函数传递给前端的时候会自动加括号执行,在浏览器上展示的是函数的返回值

          但是模板语法并不支持给函数传参,这是限制死的

         (二)类,对象也可以传递给前端HTML文件

        函数和类会自动加括号并且也可以拥有.的方法


    2、取值

      django模板语法取值 只有一种操作方式 句点符. 这个 点可以点索引,点key

    - 演示代码

    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    
        # CBV路由配置
        url(r'^login/', views.Mylogin.as_view()),
        # 注意一定要在对应的视图函数后面.as_view()
        # 通过观看源码我们可以得出此时上面的等价于
        # url(r'^login/', views.view)
        # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系
    
    
        url(r'^index', views.index)
    ]
    urls.py
    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    
    
    
    from django.views import View
    
    
    class Mylogin(View):
        def get(self, request):
    
            return render(request, 'login.html')
    
        def post(self, request):
    
            return HttpResponse('我是类里面的post方法')
    
    
    import time
    from datetime import datetime
    
    from django.utils.safestring import mark_safe
    def index(request):
    
        # python 所有的数据类型都支持传递给html页面
        n = 11
        f = 12.11
        s = 'hello world'
        l = [1,2,3,4,5,6]
        d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]}
        t = (1,2,3,4,5,6,7,)
        se = {1,2,3,4,5,6}
        b = True
        ff = False
        ss = 'kjasdklas ksd;lk  akjsdkl da  kjda k;lak d k;a dk  ska d'
        sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
        file_size = 32213213424
    
        def func():
            print('func被执行了')
            return 'from func'
    
    
        class MyClass(object):
            def get_self(self):
                return 'from self'
    
    
            @staticmethod
            def get_func():
                return 'from func'
    
    
            @classmethod
            def get_cls(cls):
                return 'from cls'
    
        obj = MyClass()
    
        # # 给模板传递数据方式一(自己手动传)
        # return render(request, 'index.html', {'n':n, 'f':f,.....})
        #
        # 给模板传递数据第二种方式
        return render(request, 'index.html', locals())
    
        # locals()会将当前名称空间中所有的变量名全部传递给html页面
    Views.py
    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    {#<p>{{ n }}</p>#}
    {# 这种注释是模板语法的注释不会显示到浏览器上 #}
    <!--这种注释可以显示-->
    {#<p>{{ f }}</p>#}
    {#<p>{{ s }}</p>#}
    {#<p>{{ l }}</p>#}
    {#<p>{{ d }}</p>#}
    {#<p>{{ t }}</p>#}
    {#<p>{{ se }}</p>#}
    {#<p>{{ b }}</p>#}
    {#<p>{{ func }}</p>#}
    
    {#<p>传类名也会 自动实例化 {{ MyClass }}</p>#}
    {#<p>{{ MyClass.get_self }}</p>#}
    {#<p>{{ MyClass.get_cls }}</p>#}
    {#<p>{{ MyClass.get_func }}</p>#}
    {#<p>{{ obj }}</p>#}
    {#<p>{{ obj.get_cls }}</p>#}
    {#<p>{{ obj.get_func }}</p>#}
    {#<p>{{ obj.get_self }}</p>#}
    
    <p>取值</p>
    <p>{{ l.2 }}</p>
    <p>{{ d.username }}</p>
    <p>{{ d.password }}</p>
    <p>{{ d.hobby.1.username.1 }}</p>
    
    
    
    </body>
    </html>
    index.html

    - 效果图

     七、模板语法之过滤器

      过滤器其实就是一堆方法,有以下几种:

      过滤器:|

        语法:

          左边的会当做过滤器的第一个参数 | 过滤器名字右边的会当做第二个参数 

        | length        求数据长

        | add           加法运算

        | default        默认值(判断值是否为空)

        | truncatewords   截取单词(可指定截取个数  三个点不算在内) 

        | truncatechars   截取字符(可指定截取个数  三个点算在内)

        | filesizeformat     文件大小

        | slice              切片

        | date              日期格式化(time模块不可以,datatime可以被格式化)

        | safe              取消转义(告诉浏览器我是安全的值得信赖)

    前后端取消转义

      前端

        | safe

      后端

        from django.utils.safestring import mark_safe

        比如:mark_safe('<h1>我是安全滴</h1>')

    总结(转义的优点):

      前端代码就不一定非得在前端页面书写,可以在后端下好然后传递给前端使用,这样你就可以利用到后端更多的逻辑语法

    -代码演示

    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    
        # CBV路由配置
        url(r'^login/', views.Mylogin.as_view()),
        # 注意一定要在对应的视图函数后面.as_view()
        # 通过观看源码我们可以得出此时上面的等价于
        # url(r'^login/', views.view)
        # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系
    
    
        url(r'^index', views.index)
    ]
    urls.py
    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    {#<p>{{ n }}</p>#}
    {# 这种注释是模板语法的注释不会显示到浏览器上 #}
    <!--这种注释可以显示-->
    {#<p>{{ f }}</p>#}
    {#<p>{{ s }}</p>#}
    {#<p>{{ l }}</p>#}
    {#<p>{{ d }}</p>#}
    {#<p>{{ t }}</p>#}
    {#<p>{{ se }}</p>#}
    {#<p>{{ b }}</p>#}
    {#<p>{{ func }}</p>#}
    
    {#<p>传类名也会 自动实例化 {{ MyClass }}</p>#}
    {#<p>{{ MyClass.get_self }}</p>#}
    {#<p>{{ MyClass.get_cls }}</p>#}
    {#<p>{{ MyClass.get_func }}</p>#}
    {#<p>{{ obj }}</p>#}
    {#<p>{{ obj.get_cls }}</p>#}
    {#<p>{{ obj.get_func }}</p>#}
    {#<p>{{ obj.get_self }}</p>#}
    
    {#<p>取值</p>#}
    {#<p>{{ l.2 }}</p>#}
    {#<p>{{ d.username }}</p>#}
    {#<p>{{ d.password }}</p>#}
    {#<p>{{ d.hobby.1.username.1 }}</p>#}
    
    <p>过滤器</p>
    <p>求数据长度:{{ s|length }}</p>
    <p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>
    <p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>
    <p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
    <p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>
    <p>文件大小:{{ file_size|filesizeformat }}</p>
    <p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>
    <p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
    <p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>
    
    </body>
    </html>
    index.html
    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    
    
    
    from django.views import View
    
    
    class Mylogin(View):
        def get(self, request):
    
            return render(request, 'login.html')
    
        def post(self, request):
    
            return HttpResponse('我是类里面的post方法')
    
    
    import time
    from datetime import datetime
    
    from django.utils.safestring import mark_safe
    def index(request):
    
        # python 所有的数据类型都支持传递给html页面
        n = 11
        f = 12.11
        s = 'hello world'
        l = [1,2,3,4,5,6]
        d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]}
        t = (1,2,3,4,5,6,7,)
        se = {1,2,3,4,5,6}
        b = True
        ff = False
        ss = 'kjasdklas ksd;lk  akjsdkl da  kjda k;lak d k;a dk  ska d'
        sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
        file_size = 32213213424
    
        def func():
            print('func被执行了')
            return 'from func'
    
    
        class MyClass(object):
            def get_self(self):
                return 'from self'
    
    
            @staticmethod
            def get_func():
                return 'from func'
    
    
            @classmethod
            def get_cls(cls):
                return 'from cls'
    
        obj = MyClass()
    
        ttt = time.time()
        ddd = datetime.now()
    
        res = "<h1>你好啊</h1>"
        bbb = []
        res1 = "<script>alert(123)</script>"
        res2 = mark_safe("<h1>你好啊</h1>")
    
        # # 给模板传递数据方式一(自己手动传)
        # return render(request, 'index.html', {'n':n, 'f':f,.....})
        #
        # 给模板传递数据第二种方式
        return render(request, 'index.html', locals())
    
        # locals()会将当前名称空间中所有的变量名全部传递给html页面
    Views.py

    - 效果图

     八、模板语法之标签

      模板语法的符号:
    
        { {  } }   变量相关
    
        {% %}   逻辑相关
    
      那么模板语法的标签其实就是(逻辑相关)

    1、for循环的内置对象forloop的原理解析

     2、for循环

    {% for foo in l %}  <!--l = [1,2,3,4,5,6]-->
       {% if forloop.first %}
          <p>这是我的第一次</p>
       {% elif forloop.last %}
          <p>这是最后一次了啊~</p>
       {% else %}
          <p>{{ foo }}</p>
       {% endif %}
       {% empty %}
           <p>for循环的对象内部没有值</p>
    {% endfor %}

     3、for循环之取字典

    {% for foo in d.keys %}
        <p>{{ foo }}</p>
    {% endfor %}
    
    
    {% for foo in d.values %}
        <p>{{ foo }}</p>
    {% endfor %}
    
    {% for foo in d.items %}
        <p>{{ foo }}</p>
    {% endfor %}

    4、for循环之with起别名

    <p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码</p>
    {% with  d.hobby.1.username.1 as eg  %}
        <p>别名只能在with内使用:{{ eg }}</p>
        <p>{{ d.hobby.1.username.1 }}</p>
    {% endwith %}
    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    
        # CBV路由配置
        url(r'^login/', views.Mylogin.as_view()),
        # 注意一定要在对应的视图函数后面.as_view()
        # 通过观看源码我们可以得出此时上面的等价于
        # url(r'^login/', views.view)
        # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系
    
    
        url(r'^index', views.index)
    ]
    urls.py
    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    
    
    
    from django.views import View
    
    
    class Mylogin(View):
        def get(self, request):
    
            return render(request, 'login.html')
    
        def post(self, request):
    
            return HttpResponse('我是类里面的post方法')
    
    
    import time
    from datetime import datetime
    
    from django.utils.safestring import mark_safe
    def index(request):
    
        # python 所有的数据类型都支持传递给html页面
        n = 11
        f = 12.11
        s = 'hello world'
        l = [1,2,3,4,5,6]
        d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]}
        t = (1,2,3,4,5,6,7,)
        se = {1,2,3,4,5,6}
        b = True
        ff = False
        ss = 'kjasdklas ksd;lk  akjsdkl da  kjda k;lak d k;a dk  ska d'
        sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
        file_size = 32213213424
    
        def func():
            print('func被执行了')
            return 'from func'
    
    
        class MyClass(object):
            def get_self(self):
                return 'from self'
    
    
            @staticmethod
            def get_func():
                return 'from func'
    
    
            @classmethod
            def get_cls(cls):
                return 'from cls'
    
        obj = MyClass()
    
        ttt = time.time()
        ddd = datetime.now()
    
        res = "<h1>你好啊</h1>"
        bbb = []
        res1 = "<script>alert(123)</script>"
        res2 = mark_safe("<h1>你好啊</h1>")
    
        # # 给模板传递数据方式一(自己手动传)
        # return render(request, 'index.html', {'n':n, 'f':f,.....})
        #
        # 给模板传递数据第二种方式
        return render(request, 'index.html', locals())
    
        # locals()会将当前名称空间中所有的变量名全部传递给html页面
    Views.py
    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    {#<p>{{ n }}</p>#}
    {# 这种注释是模板语法的注释不会显示到浏览器上 #}
    <!--这种注释可以显示-->
    {#<p>{{ f }}</p>#}
    {#<p>{{ s }}</p>#}
    {#<p>{{ l }}</p>#}
    {#<p>{{ d }}</p>#}
    {#<p>{{ t }}</p>#}
    {#<p>{{ se }}</p>#}
    {#<p>{{ b }}</p>#}
    {#<p>{{ func }}</p>#}
    
    {#<p>传类名也会 自动实例化 {{ MyClass }}</p>#}
    {#<p>{{ MyClass.get_self }}</p>#}
    {#<p>{{ MyClass.get_cls }}</p>#}
    {#<p>{{ MyClass.get_func }}</p>#}
    {#<p>{{ obj }}</p>#}
    {#<p>{{ obj.get_cls }}</p>#}
    {#<p>{{ obj.get_func }}</p>#}
    {#<p>{{ obj.get_self }}</p>#}
    
    {#<p>取值</p>#}
    {#<p>{{ l.2 }}</p>#}
    {#<p>{{ d.username }}</p>#}
    {#<p>{{ d.password }}</p>#}
    {#<p>{{ d.hobby.1.username.1 }}</p>#}
    
    {#<p>过滤器</p>#}
    {#<p>求数据长度:{{ s|length }}</p>#}
    {#<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>#}
    {#<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>#}
    {#<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>#}
    {#<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>#}
    {#<p>文件大小:{{ file_size|filesizeformat }}</p>#}
    {#<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>#}
    {#<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>#}
    {#<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>#}
    
    <p>标签</p>
    {#{% for foo in l %}#}
    {#    <p>{{ forloop }}</p>  {# forloop是for循环内置的对象 #}
    {#{% endfor %}#}
    
    {#{% for foo in l %}  <!--l = [1,2,3,4,5,6]-->#}
    {#    {% if forloop.first %}#}
    {#        <p>这是我的第一次</p>#}
    {#    {% elif forloop.last %}#}
    {#        <p>这是最后一次了啊~</p>#}
    {#    {% else %}#}
    {#        <p>{{ foo }}</p>#}
    {#    {% endif %}#}
    {#    {% empty %}#}
    {#        <p>for循环的对象内部没有值</p>#}
    {##}
    {#    #}
    {#{% endfor %}#}
    
    {% for foo in d.keys %}
        <p>{{ foo }}</p>
    {% endfor %}
    
    
    {% for foo in d.values %}
        <p>{{ foo }}</p>
    {% endfor %}
    
    {% for foo in d.items %}
        <p>{{ foo }}</p>
    {% endfor %}
    
    <p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码</p>
    {% with  d.hobby.1.username.1 as eg  %}
        <p>别名只能在with内使用:{{ eg }}</p>
        <p>{{ d.hobby.1.username.1 }}</p>
    {% endwith %}
    
    </body>
    </html>
    index.html

    九、自定义过滤器、标签、inclusion_tag

    1、前期准备工作

      1、在应用名下新建一个名字必须叫做templatetags文件夹

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

      3、在该py文件内 必须要先写以下两行代码

        from django.template import Library

        register = Library()

    2、自定义过滤器

    from django.template import Library
    
    register = Library()    # 这两行代码一定要先写好
    
    
    # 自定义过滤器
    @register.filter(name='my_sum')
    def index(a, b):   # 过滤器最多最多接收两个参数
        return a + b
    <p>自定义过滤器的使用</p>
    {% load mytag %}      {# 字使用自定义过滤器之前得先把他导入过来 
    <p>{{ 10|my_sum:90 }}</p>   {# 自定义过滤器的使用{{  }} #}

    演示

     3、自定义标签

    # 自定义标签
    @register.simple_tag(name='my_baby')
    def xxx(a, b, c, d):
         return '%s?%s?%s?%s'%(a,b,c,d)
    <p>自定义标签的使用</p>    {# 自定义标签的使用{%  %} #}
    {% load mytag %}
    <p>{% my_baby 1 2 3 'hello baby' %}</p>

    演示

    4、自定义过滤器与自定义标签的区别

    1、自定义过滤器用{{ }},而自定义标签用{% %}

    2、自定义过滤器可以在逻辑语句比如if中使用而自定义的标签则不可以

    5、自定义inclusion_tag

      调用inclusion_tag 是作用到HTML页面上,可以通过传参数让他帮你渲染到某一片区域

    然后放到页面的某一个位置,可以通过参数动态的改变HTML页面的一些内容

    # 自定义inclusion_tag
    @register.inclusion_tag('demo.html', name='myin')
    def index1(n):
        l = []
        for i in range(n):
            l.append(i)
    
        # 将列表传递给demo.html
        # return locals()
        return {'l':l}
    <p>自定义inclusion_tag的使用</p>
    {% load mytag %}
    {% myin 5 %}
    </body>
    </html>
    <ul>
        {% for foo in l %}
            <li>{{ foo }}</li>
        {% endfor %}
    </ul>
    demo.py

    6、总结

      在前端页面上使用自定义的过滤器,标签,inclusion_tag都要统一先导入

    {% load 你自定义的py文件名(比如mytag) %}

    
    
    """day52 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^ab_render/', views.ab_render),
    
        # CBV路由配置
        url(r'^login/', views.Mylogin.as_view()),
        # 注意一定要在对应的视图函数后面.as_view()
        # 通过观看源码我们可以得出此时上面的等价于
        # url(r'^login/', views.view)
        # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系
        
        
        url(r'^index', views.index)
    ]
    urls.py
    from django.template import Library
    
    register = Library()
    
    
    # 自定义过滤器
    @register.filter(name='my_sum')
    def index(a, b):   # 过滤器最多最多接收两个参数
        return a + b
    
    # 自定义标签
    @register.simple_tag(name='my_baby')
    def xxx(a, b, c, d):
         return '%s?%s?%s?%s'%(a,b,c,d)
    
    
    # 自定义inclusion_tag
    @register.inclusion_tag('demo.html', name='myin')
    def index1(n):
        l = []
        for i in range(n):
            l.append(i)
    
        # 将列表传递给demo.html
        # return locals()
        return {'l':l}
    mytag.py
    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    {#<p>{{ n }}</p>#}
    {# 这种注释是模板语法的注释不会显示到浏览器上 #}
    <!--这种注释可以显示-->
    {#<p>{{ f }}</p>#}
    {#<p>{{ s }}</p>#}
    {#<p>{{ l }}</p>#}
    {#<p>{{ d }}</p>#}
    {#<p>{{ t }}</p>#}
    {#<p>{{ se }}</p>#}
    {#<p>{{ b }}</p>#}
    {#<p>{{ func }}</p>#}
    
    {#<p>传类名也会 自动实例化 {{ MyClass }}</p>#}
    {#<p>{{ MyClass.get_self }}</p>#}
    {#<p>{{ MyClass.get_cls }}</p>#}
    {#<p>{{ MyClass.get_func }}</p>#}
    {#<p>{{ obj }}</p>#}
    {#<p>{{ obj.get_cls }}</p>#}
    {#<p>{{ obj.get_func }}</p>#}
    {#<p>{{ obj.get_self }}</p>#}
    
    {#<p>取值</p>#}
    {#<p>{{ l.2 }}</p>#}
    {#<p>{{ d.username }}</p>#}
    {#<p>{{ d.password }}</p>#}
    {#<p>{{ d.hobby.1.username.1 }}</p>#}
    
    {#<p>过滤器</p>#}
    {#<p>求数据长度:{{ s|length }}</p>#}
    {#<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>#}
    {#<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>#}
    {#<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>#}
    {#<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>#}
    {#<p>文件大小:{{ file_size|filesizeformat }}</p>#}
    {#<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>#}
    {#<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>#}
    {#<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>#}
    
    {#<p>标签</p>#}
    {#{% for foo in l %}#}
    {#    <p>{{ forloop }}</p>  {# forloop是for循环内置的对象 #}
    {#{% endfor %}#}
    
    {#{% for foo in l %}  <!--l = [1,2,3,4,5,6]-->#}
    {#    {% if forloop.first %}#}
    {#        <p>这是我的第一次</p>#}
    {#    {% elif forloop.last %}#}
    {#        <p>这是最后一次了啊~</p>#}
    {#    {% else %}#}
    {#        <p>{{ foo }}</p>#}
    {#    {% endif %}#}
    {#    {% empty %}#}
    {#        <p>for循环的对象内部没有值</p>#}
    {##}
    {#    #}
    {#{% endfor %}#}
    {##}
    {#{% for foo in d.keys %}#}
    {#    <p>{{ foo }}</p>#}
    {#{% endfor %}#}
    {##}
    {##}
    {#{% for foo in d.values %}#}
    {#    <p>{{ foo }}</p>#}
    {#{% endfor %}#}
    {##}
    {#{% for foo in d.items %}#}
    {#    <p>{{ foo }}</p>#}
    {#{% endfor %}#}
    {##}
    {#<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码</p>#}
    {#{% with  d.hobby.1.username.1 as eg  %}#}
    {#    <p>别名只能在with内使用:{{ eg }}</p>#}
    {#    <p>{{ d.hobby.1.username.1 }}</p>#}
    {#{% endwith %}#}
    
    
    {#<p>自定义过滤器的使用</p>#}
    {#{% load mytag %}      {# 字使用自定义过滤器之前得先把他导入过来#}
    {#<p>{{ 10|my_sum:90 }}</p>   {# 自定义过滤器的使用{{  }} #}
    {##}
    {#<p>自定义标签的使用</p>    {# 自定义标签的使用{%  %} #}
    {#{% load mytag %}#}
    {#<p>{% my_baby 1 2 3 'hello baby' %}</p>#}
    
    {#<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>#}
    {#{% if 10|my_sum:100 %}#}
    {#    <p>条件成立</p>#}
    {#{% endif %}#}
    
    {#{% if my_baby 1 2 3 4 %}#}
    {#    <p>条件成立</p>#}
    {#{% endif %}#}
    
    <p>自定义inclusion_tag的使用</p>
    {% load mytag %}
    {% myin 5 %}
    </body>
    </html>
    index.html
    from django.shortcuts import render, HttpResponse, redirect
    
    # Create your views here.
    from django.template import Template, Context
    # Django的render原理其实就相当于Template, Context的结合
    
    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    
    
    
    from django.views import View
    
    
    class Mylogin(View):
        def get(self, request):
    
            return render(request, 'login.html')
    
        def post(self, request):
    
            return HttpResponse('我是类里面的post方法')
    
    
    import time
    from datetime import datetime
    
    from django.utils.safestring import mark_safe
    def index(request):
    
        # python 所有的数据类型都支持传递给html页面
        n = 11
        f = 12.11
        s = 'hello world'
        l = [1,2,3,4,5,6]
        d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]}
        t = (1,2,3,4,5,6,7,)
        se = {1,2,3,4,5,6}
        b = True
        ff = False
        ss = 'kjasdklas ksd;lk  akjsdkl da  kjda k;lak d k;a dk  ska d'
        sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
        file_size = 32213213424
    
        def func():
            print('func被执行了')
            return 'from func'
    
    
        class MyClass(object):
            def get_self(self):
                return 'from self'
    
    
            @staticmethod
            def get_func():
                return 'from func'
    
    
            @classmethod
            def get_cls(cls):
                return 'from cls'
    
        obj = MyClass()
    
        ttt = time.time()
        ddd = datetime.now()
    
        res = "<h1>你好啊</h1>"
        bbb = []
        res1 = "<script>alert(123)</script>"
        res2 = mark_safe("<h1>你好啊</h1>")
    
        # # 给模板传递数据方式一(自己手动传)
        # return render(request, 'index.html', {'n':n, 'f':f,.....})
        #
        # 给模板传递数据第二种方式
        return render(request, 'index.html', locals())
    
        # locals()会将当前名称空间中所有的变量名全部传递给html页面
    Views.py
    <ul>
        {% for foo in l %}
            <li>{{ foo }}</li>
        {% endfor %}
    </ul>
    demo.html

    十、模板的继承

      某一各页面大部分区域都是公用的,那这个页面就可以当做模板页面
    
      当别人继承这个页面之后 如何修改这个对应的区域
    
      先在模板页面上通过block实现划定区域
    
      {%  block content %}   # block后面加你的别名
    
        模板页面内容
    
      {%  endblock %}
    
      子页面中先导入整个模板
    
      {%  extends  '模板页面.html'%}  ##模板的继承
    
        修改特定的区域 通过事先划定好的区域名称
    
        {%  block content %}
    
          子页面内容
    
        {%  endblock %}
    
      通常情况下,模板页面上应该有三块区域   
    
        {%  block css %}
    
          模板页面内容
    
        {%  endblock %}
    
        {%  block content %}
    
          模板页面内容
    
        {%  endblock %}
    
        {%  block js %}
    
          模板页面内容
    
        {%  endblock %}

      一般情况下 模板的block快越多 可扩展性越强,,除此之外还支持子页面调用父页面对应区域 的内容  {{ block.super  }}

    - 代码

    <!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>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
        {% block css %}
    
        {% endblock %}
    </head>
    <body>
    <nav class="navbar navbar-inverse">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>
    
        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
            <li><a href="#">Link</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li><a href="#">Action</a></li>
                <li><a href="#">Another action</a></li>
                <li><a href="#">Something else here</a></li>
                <li role="separator" class="divider"></li>
                <li><a href="#">Separated link</a></li>
                <li role="separator" class="divider"></li>
                <li><a href="#">One more separated link</a></li>
              </ul>
            </li>
          </ul>
          <form class="navbar-form navbar-left">
            <div class="form-group">
              <input type="text" class="form-control" placeholder="Search">
            </div>
            <button type="submit" class="btn btn-default">Submit</button>
          </form>
          <ul class="nav navbar-nav navbar-right">
            <li><a href="#">Link</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li><a href="#">Action</a></li>
                <li><a href="#">Another action</a></li>
                <li><a href="#">Something else here</a></li>
                <li role="separator" class="divider"></li>
                <li><a href="#">Separated link</a></li>
              </ul>
            </li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-3">
                <div class="list-group">
                  <a href="/mdzz/" class="list-group-item active">
                    首页
                  </a>
                  <a href="/reg/" class="list-group-item">注册</a>
                  <a href="/loginn/" class="list-group-item">登录</a>
                  <a href="#" class="list-group-item">Porta ac consectetur ac</a>
                  <a href="#" class="list-group-item">Vestibulum at eros</a>
                </div>
            </div>
            <div class="col-md-9">
                <div class="panel panel-primary">
                  <div class="panel-heading">
                    <h3 class="panel-title">Panel title</h3>
                  </div>
                  <div class="panel-body">
                    {% block content %}
                    <div class="jumbotron">
                      <h1>Hello, world!</h1>
                      <p>...</p>
                      <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
                    </div>
                    {% endblock %}
                  </div>
                </div>
            </div>
        </div>
    </div>
    
    {% block js %}
    
    {% endblock %}
    </body>
    </html>
    mdzz.hyml
    {% extends 'mdzz.html' %}
    
    {% block css %}
        <style>
            h2  {
                color: red;
            }
        </style>
    {% endblock %}
    
    {% block content %}
        {% include 'left.html' %}
    
    
    
    <h2 class="text-center">登录页面</h2>
        <form action="">
            <p>username:
                <input type="text" class="form-control">
            </p>
        <p>password:
                <input type="text" class="form-control">
            </p>
            <input type="submit" class="btn btn-primary">
        </form>
        {{ block.super }}  {# 继承引用模板的内容 #}
    
    {% endblock %}
    
    
    {% block js %}
    {#    <script>#}
    {#        alert(123)#}
    {#    </script>#}
    {% endblock %}
    loginn.html
    {% extends 'mdzz.html' %}   {# extend把就可以继承mdzz #}
    
    {% block css %}
        <style>
            h2 {
                color: green;
            }
        </style>
    {% endblock %}
    
    
    {% block content %}
    <h2 class="text-center">注册页面</h2>
        <form action="">
            <p>username:
                <input type="text" class="form-control">
            </p>
        <p>password:
                <input type="text" class="form-control">
            </p>
            <input type="submit" class="btn btn-danger">
        </form>
        {{ block.super }}
        {{ block.super }}
        {{ block.super }}
        {{ block.super }}
        {{ block.super }}
        {{ block.super }}
        {{ block.super }}
    {% endblock %}
    
    
    {% block js %}
    {#    <script>#}
    {#        alert(666)#}
    {#    </script>#}
    {% endblock %}
    reg.html

    - 效果图

     

     十一、模板的导入

       将HTML页面当做模块使用  哪里需要就导到那里去 通常这个HTML页面都是不完整的

    方法:{%  include  ‘模板.html’  %}

    十二、基于django settings源码实现插拔式设计

    import os
    import sys
    
    
    BASE_DIR = os.path.dirname(__file__)
    sys.path.append(BASE_DIR)
    
    
    if __name__ == '__main__':
         # 项目启动就应该朝全局的大字典中设置键值对
        os.environ['xxx'] = 'conf.settings'
        from lib.conf import settings
        print(settings.NAME)
    start.py
    # NAME = '我是暴露给用户的配置文件'
    conf下的配置
    NAME = '我是项目默认的配置文件'
    lib默认的配置
    import importlib
    import os
    from lib.conf import global_settings
    
    
    class Settings(object):
        def __init__(self):
            # 先循环遍历项目默认的全局配置文件
            for name in dir(global_settings):
                # 判断变量名是否是大写
                if name.isupper():
                    # 键值对设置给对象
                    k = name   # NAME
                    v = getattr(global_settings, name)   # yafeng
                    setattr(self, k, v)
    
    
            # 先获取暴露给用户的配置文件的字符串路径
            module_path = os.environ.get('xxx')   # conf.settings
            # 里面importlib模块 导入settings文件
            md = importlib.import_module(module_path) # md = settings
    
            for name in dir(md):
                # 判断变量名是否是大写
                if name.isupper():
                    # 键值对设置给对象
                    k = name   # NAME
                    v = getattr(md, name)   # yafeng
                    setattr(self, k, v)
    
    
    settings = Settings()
    lib下的conf下的__init__

    - 演示


     
  • 相关阅读:
    重构改善既有代码设计--重构手法19:Replace Data Value with Object (以对象取代数据值)
    重构改善既有代码设计--重构手法18:Self Encapsulate Field (自封装字段)
    重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)
    重构改善既有代码设计--重构手法15:Remove Middle Man (移除中间人)
    重构改善既有代码设计--重构手法14:Hide Delegate (隐藏委托关系)
    JAVA设计模式:蝇量模式
    JAVA设计模式:桥接模式
    重构改善既有代码设计--重构手法13:Inline Class (将类内联化)
    leetcode-485-Max Consecutive Ones
    leetcode-475-Heaters
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12163889.html
Copyright © 2011-2022 走看看