django视图层,模板层、插拔式设计、过滤器、标签、模板的继承和导入

一、视图层

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

FBV和CBV

django的视图层由两种形式构成:FBV和CBV

FBV:基于函数的视图(Function base view)

CBV:基于类的视图(Class base view)

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方法')
views.py
# CBV路由配置
url(r'^login/',views.MyLogin.as_view()),

# 等价于
url(r'^login/',views.view)  # FBV与CBV在路由匹配上本质是一样的 都是路由与函数内存地址的对应关系
urls.py

源码:

1.

 

 2.

 

 3.

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)
views.py

插拔式设计

基于django settings源码实现项目配置文件的插拔式设计

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

lib文件夹下的conf文件夹下的__init__:

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()
lib.conf.__init__.py

lib文件夹下的conf文件夹下的settings:

NAME = '我是项目默认的配置文件'
lib.conf.global_settings.py

conf文件夹下的settings.:

# NAME = '我是暴露给用户的配置文件'
conf.settings.py

 

importlib

使用conf下面的b,要想通过b.的方式使用,还可以使用imporlib

# from conf import b
# print(b.name)

import importlib
res = 'conf.b'
md = importlib.import_module(res)
# 该方法最小单位是模块 不能是模块里面的单个名字
print(md.name)    #    == print(b.name)
importlib

使用conf下面的b,要想通过b.的方式使用,还可以使用imporlib

 

 

 

 

 

二、模板层

模板语法的传值

  • python基本数据类型全部支持传递给html文件
  • 函数
  • 类(函数和对象会自动加括号)
import time
from datetime import datetime
from django.utils.safestring import mark_safe

def index(request):

    # python所有的数据类型都支持传递给html页面
    n = 11
    f = 11.11
    s = 'hello world'
    l = [1,2,3,4,5,6]
    d = {"username":'nick','password':123,'hobby':['read',{'username':['bonny','pam']}]}
    t = (1,2,3,4,5,6,7,)
    se = {1,2,3,4,5,6}
    b = True
    ff = False
    ss = 'kjasdklas ksdlk  akjsdkl da  kjda klak d ka dk  ska d'
    sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
    file_size = 32213213424

    def func(xxx,yyy):
        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()

    # 1 给模板传递数据
    # return render(request,'index.html',{'n':n,'f':f})
    # 2 给模板传递数据

    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',locals())
views.py

对象:后端给html文件传递数据的两种方式

# 1.指名道姓
return render(request,'index.html',{'n':n,'f':f})

# 2.locals()  # 会将当前名称空间中所有的变量名全部传递给html页面
return render(request,'index.html',locals())


# html页面上 如何获取到后端传递过来的数据 
# {{ 变量名 }}
views.py

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

  • 点索引
  • 点键

模板语法符号

  • { { 变量相关 } }  
  • { % 逻辑相关 % } 
<!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 }}</p>#}
{#<p>{{ MyClass.get_func }}</p>#}
{#<p>{{ MyClass.get_cls }}</p>#}
{#<p>{{ MyClass.get_self }}</p>#}
{#<p>{{ obj }}</p>#}
{#<p>{{ obj.get_func }}</p>#}
{#<p>{{ obj.get_self }}</p>#}
{#<p>{{ obj.get_cls }}</p>#}

{#<p>取值</p>#}
{#<p>{{ l.2 }}</p>#}
{#<p>{{ d.username }}</p>#}
{#<p>{{ d.password }}</p>#}
{#<p>{{ d.hobby.1.username.1 }}</p>#}


</body>
</html>
取值

过滤器

|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>
index.html

前后端取消转义
前端

  • |safe

后端

from django.utils.safestring import mark_safe
mark_safe('<h1>安全滴</h1>')

总结:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用

标签(逻辑相关)

{#<p>标签</p>#}
{#{% for foo in l %}#}
{#    <p>{{ forloop }}</p>#}
{#{% endfor %}#}

{#{% for foo in bbb %}  <!--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 %}#}
View Code

当一个值获取的步骤非常繁琐,但是又需要在很多地方用到,我们可以用起别名的方式来简化代码

{#<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码</p>#}
{#{% with  d.hobby.1.username.1 as eg  %}#}
{#    <p>别名只能在with内使用:{{ eg }}</p>#}
{#    <p>{{ d.hobby.1.username.1 }}</p>#}
{#{% endwith %}#}
取值起别名

自定义过滤器及标签 inclusion_tag

先完成以下前期准备工作

  • 1.在应用名下新建一个名字必须叫templatetags文件夹
  • 2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
  • 3.在该文件内 必须先写以下两句代码
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}
views.py
<p>自定义过滤器的使用</p>
        {% load mytag %}
        <p>{{ 10|my_sum:90 }}</p>

        <p>自定义标签的使用</p>
        {% load mytag %}
        <p>{% my_baby 1 2 3 'hello world' %}</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 %}
        # 总结 页面上使用他们 统一先导入
            {% load mytag %}
.html

 

模板的继承

某一个页面大部分区域都是公用的 那这个页面就可以作为模板页面
当别人继承这个页面之后,修改对应的区域.

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

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

子页面中先导入整个模板

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

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

{% block css %}    
                模板页面内容
            {% endblock %}
            {% block content %}    
                模板页面内容
            {% endblock %}
            {% block js %}    
                模板页面内容
            {% endblock %}
        # 模板的block块越多 可扩展性越高
        
        还支持子页面调用父页面对应区域的内容 并且可以无限次调用
            {{ block.super }}
.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>
    <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="/register/" 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>
View Code

子页面

{% 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 %}
View Code
{% extends 'mdzz.html' %}

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

 

模板的导入

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

{% include 'left.html' %}

 

 

end

posted @ 2020-01-07 18:54  小猪皮蛋  阅读(227)  评论(0编辑  收藏  举报