• Django(视图层、模板层)


    render原理:

    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict':{'username':'jason','password':123}})
        res = temp.render(user_dict)
        return HttpResponse(res)

    一、视图层

    视图函数必须返回一个HttpResponse对象。

    视图函数可以是一个函数,也可以是一个类

    FBV:基于函数的视图

    CBV:基于类的视图

    CBV

    # 视图中语法
    from django.views import View
    
    
    class MyLogin(View):
        
        def get(self,request):
            return render(request,'login.html')
        def post(self,request):
            return HttpResponse('我是类里面的post方法')
        
    
    # 路由中语法
    url(r'^login/',views.MyLogin.as_view())

    朝login提交get请求会自动执行MyLogin里面的get方法,而提交post请求也会自动执行MyLogin里面的post方法

    为什么MyLogin针对不同的请求方法能够自动执行对应的方法?

    可以查看as_view源码:

     

    1.通过查看源码,我们得知 as_view是一个闭包类的绑定方法,返回一个view方法,调用views.MyLogin.as_view()方法等价于:views.view。再次去view源代码中去查看:

     2.view方法中,首先会产生一个我们自己写的类即MyLogin的对象self,然后给这个对象的名称空间中添加request、位置参数、关键字参数属性,返回一个dispatch方法(我们自己创建的对象和类中没有,会去父类View中查询)

    3.去父类中的dispatch方法查看,会判断request中返回的请求方式是否在八个基本请求方式中,如果在,则通过反射获取该请求方式的在我们的类中的方法,最后返回该方法的调用

    django settings源码

    1.在from django.conf import global_settings, settings,去settings中查看

     2.再去LazySettings类中查看

     3.再去类中的Settings查看

     4.在Settings类中,我们可以发现里面有两个遍历的for循环,第一次是设置默认的全局的设置:global_settings,第二次是设置用户可以配置的设置:settings。用户配置了就用用户的,用户没有配就用默认的

     二、模板层

    1.模板语法符号

    {{}}      变量相关

    {%%}  逻辑相关

    2.模板传值

    Python基本数据数据类型全部支持传递给html文件

    注意:传递函数和对象时候,会自动加括号,也就是传递时候会直接调用

    对象

      后端给html文件传递数据有两种方式:

      1.以一个字典方式,指名道姓传值

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

      2.locals():将当前名称空间中所有的变量名全部传递给html页面

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

    取值:django模板语法取值只有一种操作方式:句点符"."

      .索引

      .键

    <p>{{ l.2 }}</p>    # 索引
    <p>{{ d.username }}</p>    # 键
    <p>{{ d.hobby.1.username.1 }}</p>    # 索引和键混合

    3.过滤器

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

    |length:求数据长度
    |add:假发运算
    |default:默认值(判断是否为空)
    |truncatechars:截取字符
    |truncatewords:截取单词
    |filesizeformat:文件大小
    |slice:切片操作
    |date:日期格式化
    |safe:转义

    <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>

    补充:前后端取消转义

      前端:|safe

      后端:from django.utils.safestring import mark_safe

         mark_safe('<h1>安全滴</h1>')

    小结:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用,这样的话,你就可以利用到后端更加多的逻辑语法

    4.标签

    {% 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 %}

    5.自定义

    过滤器、标签、inclusion_tag可以自定义

    前期步骤:

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

      - 在该文件夹内新建一个任意名称的py文件(eg:mytag)

      - 在该文件内 必须先写以下两句代码

    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}
                

    使用自定义时候,需要在html文件中导入mytag

    {% load mytag %}

    6.继承

    某一个页面大部分区域都是公用的,那这个页面就可以作为模板页面

      - 先在模板页面上通过block实现划定区域

    {% block content %}    
        模板页面内容
    {% endblock %}

      - 子页面中先导入整个模板

    {% extends '模板页面.html'%}
    修改特定的区域  通过实现划定好的区域名称
    {% block content %}
        子页面内容
    {% endblock %}

    通常情况下,模板页面页面应该起码有三块区域

    css、js、content

    模板的block块越多,可扩展性越高

    子页面调用父页面对应区域的内容,并且可以无限次调用

    {{ block.super }}

    7.导入

    将html页面当做模块使用 哪里需要导哪里,这个html页面通常都不是完整的 只是一个局部样式

    语法:

    {% include 'left.html' %}

    补充:基于django settings源码实现项目配置文件的,插拔式设计示例:

    文件目录:

    -mysetting

      - conf

        - settings.py

      - lib

        - conf

          - __init__.py

          - global_settings.py

      start.py

    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 = '我是暴露给用户的配置文件'
    settings.py
    NAME = '我是项目默认的配置文件'
    global_settings.py
    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)  # jason
                    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)  # jason
                    setattr(self,k,v)
    
    
    
    
    
    settings = Settings()
    __init__.py
  • 相关阅读:
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
  • 原文地址:https://www.cnblogs.com/hexianshen/p/12163266.html
Copyright © 2020-2023  润新知